diff --git a/.gitignore b/.gitignore index 6aebd05..b418b5f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,6 @@ -# 运行时生成,不入库 .env +.env.local +.env.*.local components/ .selftest/ data/ - -# Flutter 手机端构建产物 -mobile/.dart_tool/ -mobile/build/ -mobile/.flutter-plugins* diff --git a/account-service/server.js b/account-service/server.js index 2574d1f..5a21e83 100644 --- a/account-service/server.js +++ b/account-service/server.js @@ -179,7 +179,7 @@ function send(res, status, obj) { res.writeHead(status, { 'Content-Type': 'application/json; charset=utf-8', 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Headers': 'Content-Type, admin-token', + 'Access-Control-Allow-Headers': 'Content-Type, admin-token, authorization', 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', }); res.end(body); diff --git a/pc-client/.env.example b/pc-client/.env.example new file mode 100644 index 0000000..8bed870 --- /dev/null +++ b/pc-client/.env.example @@ -0,0 +1,7 @@ +# 内网测试环境(192.168.200.11,见仓库根目录 README 端口表) +VITE_WS_URL=ws://192.168.200.11:10001 +VITE_API_URL=http://192.168.200.11:10002 +# 自研公司账号服务(登录 + 通话令牌)。本地联调可建 .env.local 覆盖为 mock:http://127.0.0.1:11010 +VITE_ACCOUNT_URL=http://192.168.200.11:10010 +# LiveKit 语音通话(宿主端口已改映射为 17880) +VITE_LIVEKIT_URL=ws://192.168.200.11:17880 diff --git a/pc-client/.gitignore b/pc-client/.gitignore new file mode 100644 index 0000000..e319255 --- /dev/null +++ b/pc-client/.gitignore @@ -0,0 +1,36 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +pnpm-debug.log* + +# 依赖与构建产物 +node_modules +dist +dist-ssr +dist-electron +package +release + +# 本地环境覆盖(.env 由仓库根 .gitignore 忽略) +*.local + +# Editor directories and files +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# 测试产物(截图等) +/test-results/ +/playwright-report/ +/playwright/.cache/ +e2e/screenshots/ + +# sdk core +open-im-sdk-core.* +OpenIM_* diff --git a/pc-client/LICENSE b/pc-client/LICENSE new file mode 100644 index 0000000..0ad25db --- /dev/null +++ b/pc-client/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/pc-client/README.md b/pc-client/README.md new file mode 100644 index 0000000..35fd700 --- /dev/null +++ b/pc-client/README.md @@ -0,0 +1,48 @@ +# 畅联 PC 端(pc-client) + +公司内部通讯工具「畅联」的 PC 客户端,基于 OpenIM 官方 Electron 样板(openim-electron-demo,Electron + React 18 + TypeScript + antd 5 + zustand)改造: + +- 登录改为**工号 + 密码**,走自研账号服务(不部署 OpenIM 官方 chat 业务服务 :10008) +- 用户信息、音视频通话令牌等原走 chat 服务的调用,已全部改道 OpenIM SDK 或自研账号服务 +- 界面文案全中文,默认语言简体中文 + +## 依赖的服务端 + +见仓库根目录 `README.md`:OpenIM 服务端(REST :10002 / WS :10001)、自研账号服务(:10010,接口见 `account-service/README.md`)、LiveKit(:17880)。客户端连接地址在 `.env` 里配置(`VITE_ACCOUNT_URL`、`VITE_WS_URL`、`VITE_API_URL` 等)。 + +## 本地开发 + +```bash +npm install +npm run dev +``` + +- `npm install` 时注意:本仓库用 allow-scripts 白名单管理依赖安装脚本,需批准 `electron` / `esbuild` / `koffi` 等包的 postinstall(package.json 里已配好 `allowScripts` 字段)。 +- `npm run dev` 启动 Vite 开发服务器(默认同时拉起 Electron 窗口)。 + +### 本地 mock 登录服务(联调用) + +真实员工账号由管理员在服务器上开通。本地开发没有真实账号时,可以起一个 mock 账号服务: + +```bash +npm run mock:account +``` + +然后新建 `.env.local`(已被 gitignore)写入 `VITE_ACCOUNT_URL=http://127.0.0.1:11010` 覆盖 `.env` 里的真实地址,用 `test001 / test123`(或 `test002 / test123`)登录。mock 服务实现了与真实账号服务相同的 `/api/login` 和 `/api/rtc_token` 接口(登录时会真实调用 OpenIM 管理接口换取 imToken;`/api/rtc_token` 同样要求 `Authorization: Bearer `)。 + +> ⚠️ mock 服务内置测试环境默认密钥,仅供本地开发,禁止打包、禁止用于正式环境。 + +## 打包 + +先 `npm run build`(vite build,产物在 `dist/`),再用 electron-builder 打包安装包。打包用的脚本在 `package_electron.json` 里(打包前按原样板说明用它替换 `package.json`): + +```bash +npm run build:win # Windows 安装包 +``` + +如果只想验证构建不产出安装包:`npm run build && npx electron-builder`(此命令未验证,以 `package_electron.json` 里的脚本为准)。 + +## 其他 + +- 本项目基于 openim-electron-demo(AGPL-3.0 附加条款),仅作公司内部使用。 +- 原样板说明(英文、功能清单等)见上游仓库 。 diff --git a/pc-client/commitlint.config.js b/pc-client/commitlint.config.js new file mode 100644 index 0000000..9ed9fce --- /dev/null +++ b/pc-client/commitlint.config.js @@ -0,0 +1,132 @@ +module.exports = { + parserPreset: "conventional-changelog-conventionalcommits", + rules: { + "body-leading-blank": [1, "always"], + "body-max-line-length": [2, "always", 100], + "footer-leading-blank": [1, "always"], + "footer-max-line-length": [2, "always", 100], + "header-max-length": [2, "always", 100], + "subject-case": [ + 2, + "never", + ["sentence-case", "start-case", "pascal-case", "upper-case"], + ], + "subject-empty": [2, "never"], + "subject-full-stop": [2, "never", "."], + "type-case": [2, "always", "lower-case"], + "type-empty": [2, "never"], + "type-enum": [ + 2, + "always", + [ + "build", + "chore", + "ci", + "docs", + "feat", + "fix", + "perf", + "refactor", + "revert", + "style", + "test", + ], + ], + }, + prompt: { + questions: { + type: { + description: "Select the type of change that you're committing", + enum: { + feat: { + description: "A new feature", + title: "Features", + emoji: "✨", + }, + fix: { + description: "A bug fix", + title: "Bug Fixes", + emoji: "🐛", + }, + docs: { + description: "Documentation only changes", + title: "Documentation", + emoji: "📚", + }, + style: { + description: + "Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)", + title: "Styles", + emoji: "💎", + }, + refactor: { + description: "A code change that neither fixes a bug nor adds a feature", + title: "Code Refactoring", + emoji: "📦", + }, + perf: { + description: "A code change that improves performance", + title: "Performance Improvements", + emoji: "🚀", + }, + test: { + description: "Adding missing tests or correcting existing tests", + title: "Tests", + emoji: "🚨", + }, + build: { + description: + "Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)", + title: "Builds", + emoji: "🛠", + }, + ci: { + description: + "Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)", + title: "Continuous Integrations", + emoji: "⚙️", + }, + chore: { + description: "Other changes that don't modify src or test files", + title: "Chores", + emoji: "♻️", + }, + revert: { + description: "Reverts a previous commit", + title: "Reverts", + emoji: "🗑", + }, + }, + }, + scope: { + description: "What is the scope of this change (e.g. component or file name)", + }, + subject: { + description: "Write a short, imperative tense description of the change", + }, + body: { + description: "Provide a longer description of the change", + }, + isBreaking: { + description: "Are there any breaking changes?", + }, + breakingBody: { + description: + "A BREAKING CHANGE commit requires a body. Please enter a longer description of the commit itself", + }, + breaking: { + description: "Describe the breaking changes", + }, + isIssueAffected: { + description: "Does this change affect any open issues?", + }, + issuesBody: { + description: + "If issues are closed, the commit requires a body. Please enter a longer description of the commit itself", + }, + issues: { + description: 'Add issue references (e.g. "fix #123", "re #123".)', + }, + }, + }, +}; diff --git a/pc-client/docs/images/logo.jpg b/pc-client/docs/images/logo.jpg new file mode 100644 index 0000000..0849fde Binary files /dev/null and b/pc-client/docs/images/logo.jpg differ diff --git a/pc-client/docs/images/preveiw.zh-CN.png b/pc-client/docs/images/preveiw.zh-CN.png new file mode 100644 index 0000000..489283c Binary files /dev/null and b/pc-client/docs/images/preveiw.zh-CN.png differ diff --git a/pc-client/docs/images/preview.png b/pc-client/docs/images/preview.png new file mode 100644 index 0000000..19b13ce Binary files /dev/null and b/pc-client/docs/images/preview.png differ diff --git a/pc-client/e2e/debug-page.cjs b/pc-client/e2e/debug-page.cjs new file mode 100644 index 0000000..d92bff6 --- /dev/null +++ b/pc-client/e2e/debug-page.cjs @@ -0,0 +1,21 @@ +const { chromium } = require("@playwright/test"); + +(async () => { + const browser = await chromium.launch({ + executablePath: + "C:/Users/MoBai/AppData/Local/ms-playwright/chromium_headless_shell-1228/chrome-headless-shell-win64/chrome-headless-shell.exe", + }); + const page = await browser.newPage({ viewport: { width: 1200, height: 800 } }); + page.on("console", (msg) => console.log("[" + msg.type() + "]", msg.text().slice(0, 300))); + page.on("pageerror", (err) => console.log("[pageerror]", String(err).slice(0, 500))); + + await page.goto("http://localhost:5173/"); + await page.waitForTimeout(6000); + const html = await page.content(); + console.log("body length:", html.length); + console.log(html.slice(0, 800)); + await browser.close(); +})().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/pc-client/e2e/example.spec.ts b/pc-client/e2e/example.spec.ts new file mode 100644 index 0000000..c9a1f7a --- /dev/null +++ b/pc-client/e2e/example.spec.ts @@ -0,0 +1,8 @@ +import { test, expect, _electron as electron } from "@playwright/test"; + +test("homepage has title and links to intro page", async () => { + const app = await electron.launch({ args: [".", "--no-sandbox"] }); + const page = await app.firstWindow(); + expect(await page.title()).toBe("OpenCorp"); + await page.screenshot({ path: "e2e/screenshots/example.png" }); +}); diff --git a/pc-client/e2e/screenshot-check.cjs b/pc-client/e2e/screenshot-check.cjs new file mode 100644 index 0000000..9ca75db --- /dev/null +++ b/pc-client/e2e/screenshot-check.cjs @@ -0,0 +1,46 @@ +/* 临时截图脚本:mock 登录后截取登录页/主界面/通讯录 */ +const { chromium } = require("@playwright/test"); + +(async () => { + const browser = await chromium.launch({ + executablePath: + "C:/Users/MoBai/AppData/Local/ms-playwright/chromium_headless_shell-1228/chrome-headless-shell-win64/chrome-headless-shell.exe", + }); + const page = await browser.newPage({ viewport: { width: 1200, height: 800 } }); + page.on("console", (msg) => { + if (msg.type() === "error") console.log("[console.error]", msg.text().slice(0, 200)); + }); + + await page.goto("http://localhost:5173/", { waitUntil: "networkidle" }); + await page.waitForTimeout(2000); + await page.screenshot({ path: "e2e/screenshots/01-login.png" }); + + await page.fill('input[placeholder="请输入工号"]', "test001"); + await page.fill('input[placeholder="请输入您的密码"]', "test123"); + await page.click('button:has-text("登录")'); + + // 等 SDK 登录 + 同步 + await page.waitForTimeout(18000); + await page.screenshot({ path: "e2e/screenshots/02-main.png" }); + + // 进入会话 + await page.click('text=测试二号'); + await page.waitForTimeout(4000); + await page.screenshot({ path: "e2e/screenshots/04-chat.png" }); + + // 发一条文字消息看气泡 + await page.fill("textarea", "好,我开完会就看,下午给你回复"); + await page.keyboard.press("Enter"); + await page.waitForTimeout(2500); + await page.screenshot({ path: "e2e/screenshots/05-chat-sent.png" }); + + await page.goto("http://localhost:5173/#/contact"); + await page.waitForTimeout(4000); + await page.screenshot({ path: "e2e/screenshots/03-contact.png" }); + + await browser.close(); + console.log("done"); +})().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/pc-client/e2e/screenshot-detail.cjs b/pc-client/e2e/screenshot-detail.cjs new file mode 100644 index 0000000..0036e0f --- /dev/null +++ b/pc-client/e2e/screenshot-detail.cjs @@ -0,0 +1,44 @@ +const { chromium } = require("@playwright/test"); + +(async () => { + const browser = await chromium.launch({ + executablePath: + "C:/Users/MoBai/AppData/Local/ms-playwright/chromium_headless_shell-1228/chrome-headless-shell-win64/chrome-headless-shell.exe", + }); + const page = await browser.newPage({ viewport: { width: 1200, height: 800 } }); + + await page.goto("http://localhost:5173/"); + await page.waitForTimeout(1500); + + const hasLogin = await page.$('input[placeholder="请输入工号"]'); + if (hasLogin) { + await page.fill('input[placeholder="请输入工号"]', "test001"); + await page.fill('input[placeholder="请输入您的密码"]', "test123"); + await page.click('button:has-text("登录")'); + await page.waitForTimeout(15000); + } else { + await page.waitForTimeout(12000); + } + + await page.click("text=测试二号"); + await page.waitForTimeout(3000); + + // 「…」菜单 + await page.click(".anticon-more"); + await page.waitForTimeout(800); + await page.screenshot({ path: "e2e/screenshots/06-header-menu.png" }); + await page.keyboard.press("Escape"); + await page.waitForTimeout(500); + + // 表情面板 + await page.click(".anticon-smile"); + await page.waitForTimeout(800); + await page.screenshot({ path: "e2e/screenshots/07-emoji.png" }); + await page.keyboard.press("Escape"); + + await browser.close(); + console.log("done"); +})().catch((e) => { + console.error(e); + process.exit(1); +}); diff --git a/pc-client/electron-builder.json5 b/pc-client/electron-builder.json5 new file mode 100644 index 0000000..e2172c7 --- /dev/null +++ b/pc-client/electron-builder.json5 @@ -0,0 +1,94 @@ +/** + * @see https://www.electron.build/configuration/configuration + */ +{ + appId: "com.changlian.desktop", + productName: "畅联", + asar: true, + asarUnpack: ["**/*.node"], + extends: null, + directories: { + output: "release/Base/${version}", + }, + files: [ + "dist", + "!dist/*.wasm", + "dist-electron", + "!node_modules/rxjs/**/*", + "!node_modules/koffi/src/**/*", + "!node_modules/koffi/build/**/*", + "!node_modules/koffi/vendor/**/*", + "!node_modules/@openim/wasm-client-sdk/assets/**/*", + "!node_modules/@openim/electron-client-sdk/assets/**/*", + ], + extraResources: [ + { + from: "extraResources", + to: "extraResources", + }, + { + from: "node_modules/rxjs", + to: "app.asar.unpacked/node_modules/rxjs", + }, + ], + mac: { + artifactName: "${productName}_${version}_${arch}.${ext}", + target: ["dmg"], + icon: "./dist/icons/mac_icon.png", + extraResources: [ + { + from: "node_modules/@openim/electron-client-sdk/assets/mac_${arch}/", + to: "app.asar.unpacked/node_modules/@openim/electron-client-sdk/assets/mac_${arch}", + }, + { + from: "node_modules/koffi/build/koffi/darwin_${arch}/", + to: "koffi/darwin_${arch}", + }, + ], + }, + win: { + target: [ + { + target: "nsis", + }, + ], + artifactName: "${productName}_${version}.${ext}", + icon: "./dist/icons/icon.ico", + extraResources: [ + { + from: "node_modules/@openim/electron-client-sdk/assets/win_${arch}/", + to: "app.asar.unpacked/node_modules/@openim/electron-client-sdk/assets/win_${arch}", + }, + { + from: "node_modules/koffi/build/koffi/win32_${arch}/", + to: "koffi/win32_${arch}", + }, + ], + }, + linux: { + icon: "./dist/icons/icon.png", + target: "deb", + maintainer: "opencorp-base", + artifactName: "${productName}_${version}_${arch}.${ext}", + extraResources: [ + { + from: "node_modules/@openim/electron-client-sdk/assets/linux_${arch}/", + to: "app.asar.unpacked/node_modules/@openim/electron-client-sdk/assets/linux_${arch}", + }, + { + from: "node_modules/koffi/build/koffi/linux_${arch}/", + to: "koffi/linux_${arch}", + }, + ], + }, + nsis: { + oneClick: false, + perMachine: true, + allowElevation: true, + allowToChangeInstallationDirectory: true, + createDesktopShortcut: true, + createStartMenuShortcut: true, + deleteAppDataOnUninstall: true, + shortcutName: "OpenCorp-Base", + } +} diff --git a/pc-client/electron/constants/index.ts b/pc-client/electron/constants/index.ts new file mode 100644 index 0000000..7ca89ce --- /dev/null +++ b/pc-client/electron/constants/index.ts @@ -0,0 +1,17 @@ +export const IpcMainToRender = { + appResume: "appResume", +}; + +export const IpcRenderToMain = { + showMainWindow: "showMainWindow", + clearSession: "clearSession", + minimizeWindow: "minimizeWindow", + maxmizeWindow: "maxmizeWindow", + closeWindow: "closeWindow", + showMessageBox: "showMessageBox", + setKeyStore: "setKeyStore", + getKeyStore: "getKeyStore", + getKeyStoreSync: "getKeyStoreSync", + showInputContextMenu: "showInputContextMenu", + getDataPath: "getDataPath", +}; diff --git a/pc-client/electron/electron-env.d.ts b/pc-client/electron/electron-env.d.ts new file mode 100644 index 0000000..f414b9b --- /dev/null +++ b/pc-client/electron/electron-env.d.ts @@ -0,0 +1,7 @@ +/// + +declare namespace NodeJS { + interface ProcessEnv { + VSCODE_DEBUG?: "true"; + } +} diff --git a/pc-client/electron/i18n/index.ts b/pc-client/electron/i18n/index.ts new file mode 100644 index 0000000..e57e30d --- /dev/null +++ b/pc-client/electron/i18n/index.ts @@ -0,0 +1,40 @@ +import i18n from "i18next"; + +import { getStore } from "../main/storeManage"; +import { app } from "electron"; + +import translation_en from "./resources/en-US"; +import translation_zh from "./resources/zh-CN"; + +const store = getStore(); + +export const initI18n = () => { + const systemLanguage = app.getLocale(); + const language = store.get("language", systemLanguage) as string; + + const resources = { + "en-US": { + translation: translation_en, + }, + "zh-CN": { + translation: translation_zh, + }, + zh: { + translation: translation_zh, + }, + }; + + i18n.init( + { + resources, + lng: language, + fallbackLng: "zh-CN", + }, + (err) => { + if (err) return console.error("Error loading i18n resources:", err); + console.log("i18n resources loaded successfully"); + }, + ); +}; + +export const changeLanguage = i18n.changeLanguage; diff --git a/pc-client/electron/i18n/resources/en-US.ts b/pc-client/electron/i18n/resources/en-US.ts new file mode 100644 index 0000000..241741a --- /dev/null +++ b/pc-client/electron/i18n/resources/en-US.ts @@ -0,0 +1,21 @@ +export default { + system: { + showWindow: "ShowWindow", + hideWindow: "HideWindow", + hide: "Hide", + about: "About", + quit: "Quit", + window: "Window", + toggleDevTools: "ToggleDevTools", + minimize: "Minimize", + close: "Close", + copy: "Copy", + paste: "Paste", + cut: "Cut", + undo: "Undo", + redo: "Redo", + selectAll: "SelectAll", + fastKeys: "FastKeys", + magnifier_position_label:"Position" + }, +}; diff --git a/pc-client/electron/i18n/resources/zh-CN.ts b/pc-client/electron/i18n/resources/zh-CN.ts new file mode 100644 index 0000000..b7d1db3 --- /dev/null +++ b/pc-client/electron/i18n/resources/zh-CN.ts @@ -0,0 +1,21 @@ +export default { + system: { + showWindow: "显示", + hideWindow: "隐藏", + hide: "隐藏", + about: "关于", + quit: "退出", + window: "窗口", + toggleDevTools: "调试", + minimize: "最小化", + close: "关闭", + copy: "复制", + paste: "粘贴", + cut: "剪切", + undo: "撤销", + redo: "重做", + selectAll: "全选", + fastKeys: "快键键", + magnifier_position_label: "坐标", + }, +}; diff --git a/pc-client/electron/main/appManage.ts b/pc-client/electron/main/appManage.ts new file mode 100644 index 0000000..60c1180 --- /dev/null +++ b/pc-client/electron/main/appManage.ts @@ -0,0 +1,93 @@ +import { app, powerMonitor } from "electron"; +import { isExistMainWindow, sendEvent, showWindow } from "./windowManage"; +import { join } from "node:path"; +import fs from "fs"; +import { isMac, isProd, isWin } from "../utils"; +import { getStore } from "./storeManage"; +import { IpcMainToRender } from "../constants"; +import { logger } from "."; + +const store = getStore(); + +export const setSingleInstance = () => { + if (!app.requestSingleInstanceLock()) { + app.quit(); + process.exit(0); + } + + app.on("second-instance", () => { + showWindow(); + }); +}; + +export const setAppListener = (startApp: () => void) => { + app.on("activate", () => { + if (isExistMainWindow()) { + showWindow(); + } else { + startApp(); + } + }); + + app.on("window-all-closed", () => { + if (isMac && !getIsForceQuit()) return; + + app.quit(); + }); + + powerMonitor.on("suspend", () => { + logger.debug("app suspend"); + }); + + powerMonitor.on("resume", () => { + logger.debug("app resume"); + sendEvent(IpcMainToRender.appResume); + }); +}; + +export const setAppGlobalData = () => { + const electronDistPath = join(__dirname, "../"); + const distPath = join(electronDistPath, "../dist"); + const publicPath = isProd ? distPath : join(electronDistPath, "../public"); + const asarPath = process.resourcesPath; + + global.pathConfig = { + electronDistPath, + distPath, + publicPath, + asarPath, + logsPath: join(app.getPath("userData"), `/OpenIMData/logs`), + sdkResourcesPath: join(app.getPath("userData"), `/OpenIMData/sdkResources`), + imsdkLibPath: isProd + ? join( + asarPath, + "/app.asar.unpacked/node_modules/@openim/electron-client-sdk/assets", + ) + : join(__dirname, "../../node_modules/@openim/electron-client-sdk/assets"), + trayIcon: join(publicPath, `/icons/${isWin ? "icon.ico" : "tray.png"}`), + emptyTrayIcon: join(publicPath, `/icons/${"empty_tray.png"}`), + indexHtml: join(distPath, "index.html"), + splashHtml: join(distPath, "splash.html"), + preload: join(__dirname, "../preload/index.js"), + }; + + if (isProd) { + fs.promises + .readdir(global.pathConfig.logsPath) + .catch( + (err) => + err.code === "ENOENT" && + fs.promises.mkdir(global.pathConfig.logsPath, { recursive: true }), + ); + fs.promises + .readdir(global.pathConfig.sdkResourcesPath) + .catch( + (err) => + err.code === "ENOENT" && + fs.promises.mkdir(global.pathConfig.sdkResourcesPath, { recursive: true }), + ); + } +}; + +export const getIsForceQuit = () => + store.get("closeAction") === "quit" || global.forceQuit; diff --git a/pc-client/electron/main/index.ts b/pc-client/electron/main/index.ts new file mode 100644 index 0000000..f07501a --- /dev/null +++ b/pc-client/electron/main/index.ts @@ -0,0 +1,28 @@ +import { app } from "electron"; +import { join } from "node:path"; +import { createMainWindow } from "./windowManage"; +import { createTray } from "./trayManage"; +import { setIpcMainListener } from "./ipcHandlerManage"; +import { setAppGlobalData, setAppListener, setSingleInstance } from "./appManage"; +import createAppMenu from "./menuManage"; +import { isLinux } from "../utils"; +import { getLogger } from "../utils/log"; +import { initI18n } from "../i18n"; + +export const logger = getLogger(join(app.getPath("userData"), `/OpenIMData/logs`)); + +const init = () => { + initI18n(); + createMainWindow(); + createAppMenu(); + createTray(); +}; + +setAppGlobalData(); +setIpcMainListener(); +setSingleInstance(); +setAppListener(init); + +app.whenReady().then(() => { + isLinux ? setTimeout(init, 300) : init(); +}); diff --git a/pc-client/electron/main/ipcHandlerManage.ts b/pc-client/electron/main/ipcHandlerManage.ts new file mode 100644 index 0000000..a2c043d --- /dev/null +++ b/pc-client/electron/main/ipcHandlerManage.ts @@ -0,0 +1,102 @@ +import { BrowserWindow, Menu, app, dialog, ipcMain } from "electron"; +import { + clearCache, + closeWindow, + minimize, + showWindow, + splashEnd, + updateMaximize, +} from "./windowManage"; +import { t } from "i18next"; +import { IpcRenderToMain } from "../constants"; +import { getStore } from "./storeManage"; +import { changeLanguage } from "../i18n"; + +const store = getStore(); + +export const setIpcMainListener = () => { + ipcMain.handle(IpcRenderToMain.clearSession, () => { + clearCache(); + }); + + // window manage + ipcMain.handle("changeLanguage", (_, locale) => { + store.set("language", locale); + changeLanguage(locale).then(() => { + app.relaunch(); + app.exit(0); + }); + }); + ipcMain.handle("main-win-ready", () => { + splashEnd(); + }); + ipcMain.handle(IpcRenderToMain.showMainWindow, () => { + showWindow(); + }); + ipcMain.handle(IpcRenderToMain.minimizeWindow, () => { + minimize(); + }); + ipcMain.handle(IpcRenderToMain.maxmizeWindow, () => { + updateMaximize(); + }); + ipcMain.handle(IpcRenderToMain.closeWindow, () => { + closeWindow(); + }); + ipcMain.handle(IpcRenderToMain.showMessageBox, (_, options) => { + return dialog + .showMessageBox(BrowserWindow.getFocusedWindow(), options) + .then((res) => res.response); + }); + + // data transfer + ipcMain.handle(IpcRenderToMain.setKeyStore, (_, { key, data }) => { + store.set(key, data); + }); + ipcMain.handle(IpcRenderToMain.getKeyStore, (_, { key }) => { + return store.get(key); + }); + ipcMain.on(IpcRenderToMain.getKeyStoreSync, (e, { key }) => { + e.returnValue = store.get(key); + }); + ipcMain.handle(IpcRenderToMain.showInputContextMenu, () => { + const menu = Menu.buildFromTemplate([ + { + label: t("system.copy"), + type: "normal", + role: "copy", + accelerator: "CommandOrControl+c", + }, + { + label: t("system.paste"), + type: "normal", + role: "paste", + accelerator: "CommandOrControl+v", + }, + { + label: t("system.selectAll"), + type: "normal", + role: "selectAll", + accelerator: "CommandOrControl+a", + }, + ]); + menu.popup({ + window: BrowserWindow.getFocusedWindow()!, + }); + }); + ipcMain.on(IpcRenderToMain.getDataPath, (e, key: string) => { + switch (key) { + case "public": + e.returnValue = global.pathConfig.publicPath; + break; + case "sdkResources": + e.returnValue = global.pathConfig.sdkResourcesPath; + break; + case "logsPath": + e.returnValue = global.pathConfig.logsPath; + break; + default: + e.returnValue = global.pathConfig.publicPath; + break; + } + }); +}; diff --git a/pc-client/electron/main/menuManage.ts b/pc-client/electron/main/menuManage.ts new file mode 100644 index 0000000..416a711 --- /dev/null +++ b/pc-client/electron/main/menuManage.ts @@ -0,0 +1,55 @@ +import { app, Menu } from "electron"; +import { t } from "i18next"; +import { isMac } from "../utils"; + +const createAppMenu = () => { + if (isMac) { + const template: Electron.MenuItemConstructorOptions[] = [ + { + label: app.getName(), + submenu: [ + { label: t("system.about"), role: "about" }, + { type: "separator" }, + { label: t("system.hide"), role: "hide" }, + { type: "separator" }, + { + label: t("system.quit"), + click: () => { + global.forceQuit = true; + app.quit(); + }, + }, + ], + }, + { + label: t("system.fastKeys"), + submenu: [ + { label: t("system.copy"), role: "copy", accelerator: "CmdOrCtrl+C" }, + { label: t("system.paste"), role: "paste", accelerator: "CmdOrCtrl+V" }, + { label: t("system.cut"), role: "cut", accelerator: "CmdOrCtrl+X" }, + { label: t("system.undo"), role: "undo", accelerator: "CmdOrCtrl+Z" }, + { label: t("system.redo"), role: "redo", accelerator: "CmdOrCtrl+Y" }, + { + label: t("system.selectAll"), + role: "selectAll", + accelerator: "CmdOrCtrl+A", + }, + ], + }, + { + label: t("system.window"), + role: "window", + submenu: [ + { label: t("system.minimize"), role: "minimize", accelerator: "CmdOrCtrl+W" }, + { label: t("system.close"), role: "close" }, + ], + }, + ]; + + Menu.setApplicationMenu(Menu.buildFromTemplate(template)); + } else { + Menu.setApplicationMenu(null); + } +}; + +export default createAppMenu; diff --git a/pc-client/electron/main/shortcutManage.ts b/pc-client/electron/main/shortcutManage.ts new file mode 100644 index 0000000..a8ecd07 --- /dev/null +++ b/pc-client/electron/main/shortcutManage.ts @@ -0,0 +1,10 @@ +import { globalShortcut } from "electron"; +import { toggleDevTools } from "./windowManage"; + +export const registerShortcuts = () => { + globalShortcut.register("CmdOrCtrl+F12", toggleDevTools); +}; + +export const unregisterShortcuts = () => { + globalShortcut.unregisterAll(); +}; diff --git a/pc-client/electron/main/storeManage.ts b/pc-client/electron/main/storeManage.ts new file mode 100644 index 0000000..e8ab405 --- /dev/null +++ b/pc-client/electron/main/storeManage.ts @@ -0,0 +1,12 @@ +import Store from "electron-store"; + +let store: Store; + +export const getStore = () => { + if (!store) { + store = new Store(); + } + return store; +}; + +export { Store }; diff --git a/pc-client/electron/main/trayManage.ts b/pc-client/electron/main/trayManage.ts new file mode 100644 index 0000000..602c370 --- /dev/null +++ b/pc-client/electron/main/trayManage.ts @@ -0,0 +1,41 @@ +import { app, Menu, Tray } from "electron"; +import { t } from "i18next"; +import { hideWindow, showWindow } from "./windowManage"; + +let appTray: Tray; + +export const createTray = () => { + const trayMenu = Menu.buildFromTemplate([ + { + label: t("system.showWindow"), + click: showWindow, + }, + { + label: t("system.hideWindow"), + click: hideWindow, + }, + { + label: t("system.toggleDevTools"), + role: "toggleDevTools", + }, + { + label: t("system.quit"), + click: () => { + global.forceQuit = true; + app.quit(); + }, + }, + ]); + appTray = new Tray(global.pathConfig.trayIcon); + appTray.setToolTip(app.getName()); + appTray.setIgnoreDoubleClickEvents(true); + appTray.on("click", showWindow); + + appTray.setContextMenu(trayMenu); +}; + +export const destroyTray = () => { + if (!appTray || appTray.isDestroyed()) return; + appTray.destroy(); + appTray = null; +}; diff --git a/pc-client/electron/main/windowManage.ts b/pc-client/electron/main/windowManage.ts new file mode 100644 index 0000000..343ae19 --- /dev/null +++ b/pc-client/electron/main/windowManage.ts @@ -0,0 +1,259 @@ +import { join } from "node:path"; +import { BrowserWindow, dialog, shell } from "electron"; +import { isLinux, isMac, isWin } from "../utils"; +import { destroyTray } from "./trayManage"; +import { getIsForceQuit } from "./appManage"; +import { registerShortcuts, unregisterShortcuts } from "./shortcutManage"; +import { initIMSDK } from "../utils/imsdk"; +import OpenIMSDKMain from "@openim/electron-client-sdk"; + +const url = process.env.VITE_DEV_SERVER_URL; +let mainWindow: BrowserWindow | null = null; +let splashWindow: BrowserWindow | null = null; +let sdkInstance: OpenIMSDKMain | null = null; + +function createSplashWindow() { + splashWindow = new BrowserWindow({ + frame: false, + width: 200, + height: 200, + resizable: false, + transparent: true, + }); + splashWindow.loadFile(global.pathConfig.splashHtml); + splashWindow.on("closed", () => { + splashWindow = null; + }); +} + +export function createMainWindow() { + createSplashWindow(); + mainWindow = new BrowserWindow({ + title: "畅联", + icon: join(global.pathConfig.publicPath, "favicon.ico"), + frame: false, + show: false, + width: 1200, + height: 800, + minWidth: 1024, + minHeight: 726, + titleBarStyle: "hiddenInset", + webPreferences: { + preload: global.pathConfig.preload, + // Warning: Enable nodeIntegration and disable contextIsolation is not secure in production + // Consider using contextBridge.exposeInMainWorld + // Read more on https://www.electronjs.org/docs/latest/tutorial/context-isolation + nodeIntegration: false, + contextIsolation: true, + sandbox: false, + devTools: true, + webSecurity: false, + }, + }); + + sdkInstance = initIMSDK(mainWindow.webContents); + + if (process.env.VITE_DEV_SERVER_URL) { + // Open devTool if the app is not packaged + mainWindow.loadURL(url); + } else { + mainWindow.loadFile(global.pathConfig.indexHtml); + } + + // Test actively push message to the Electron-Renderer + mainWindow.webContents.on("did-finish-load", () => { + mainWindow?.webContents.send("main-process-message", new Date().toLocaleString()); + }); + + // // Make all links open with the browser, not with the application + mainWindow.webContents.setWindowOpenHandler(({ url }) => { + if (url.startsWith("https:") || url.startsWith("http:")) shell.openExternal(url); + return { action: "deny" }; + }); + + mainWindow.on("focus", () => { + mainWindow?.flashFrame(false); + registerShortcuts(); + }); + + mainWindow.on("blur", () => { + unregisterShortcuts(); + }); + + mainWindow.on("close", (e) => { + if (getIsForceQuit() || !mainWindow.isVisible()) { + mainWindow = null; + destroyTray(); + } else { + e.preventDefault(); + if (isMac && mainWindow.isFullScreen()) { + mainWindow.setFullScreen(false); + } + mainWindow?.hide(); + } + }); + return mainWindow; +} + +export function splashEnd() { + splashWindow?.close(); + mainWindow?.show(); +} + +// utils +export const isExistMainWindow = (): boolean => + !!mainWindow && !mainWindow?.isDestroyed(); +export const isShowMainWindow = (): boolean => { + if (!mainWindow) return false; + return mainWindow.isVisible() && (isWin ? true : mainWindow.isFocused()); +}; + +export const closeWindow = () => { + if (!mainWindow) return; + mainWindow.close(); +}; + +export const hotReload = () => { + if (!mainWindow) return; + mainWindow.reload(); +}; + +export const sendEvent = (name: string, ...args: any[]) => { + if (!mainWindow) return; + mainWindow.webContents.send(name, ...args); +}; + +export const showSelectDialog = async (options: Electron.OpenDialogOptions) => { + if (!mainWindow) throw new Error("main window is undefined"); + return await dialog.showOpenDialog(mainWindow, options); +}; +export const showDialog = ({ + type, + message, + detail, +}: Electron.MessageBoxSyncOptions) => { + if (!mainWindow) return; + dialog.showMessageBoxSync(mainWindow, { + type, + message, + detail, + }); +}; +export const showSaveDialog = async (options: Electron.SaveDialogOptions) => { + if (!mainWindow) throw new Error("main window is undefined"); + return await dialog.showSaveDialog(mainWindow, options); +}; +export const minimize = () => { + if (!mainWindow) return; + mainWindow.minimize(); +}; +export const updateMaximize = () => { + if (!mainWindow) return; + if (mainWindow.isMaximized()) { + mainWindow.unmaximize(); + } else { + mainWindow.maximize(); + } +}; +export const toggleHide = () => { + if (!mainWindow) return; + mainWindow.isVisible() ? mainWindow.hide() : mainWindow.show(); +}; +export const toggleMinimize = () => { + if (!mainWindow) return; + if (mainWindow.isMinimized()) { + if (!mainWindow.isVisible()) { + mainWindow.show(); + } + mainWindow.restore(); + mainWindow.focus(); + } else { + mainWindow.minimize(); + } +}; +export const showWindow = () => { + if (!mainWindow) return; + if (mainWindow.isMinimized()) { + mainWindow.restore(); + } + if (mainWindow.isVisible()) { + mainWindow.focus(); + } else { + mainWindow.show(); + } +}; +export const hideWindow = () => { + if (!mainWindow) return; + mainWindow.hide(); +}; +export const toggleWindowVisible = (visible: boolean) => { + if (!mainWindow) return; + const opacity = mainWindow.getOpacity() ? 0 : 1; + if (Boolean(opacity) !== visible) return; + mainWindow.setOpacity(opacity); +}; +export const setProgressBar = ( + progress: number, + options?: Electron.ProgressBarOptions, +) => { + if (!mainWindow) return; + mainWindow.setProgressBar(progress, options); +}; +export const taskFlicker = () => { + if ( + isMac || + (mainWindow.isVisible() && mainWindow.isFocused() && !isExistMainWindow()) + ) + return; + mainWindow?.flashFrame(true); +}; +export const setIgnoreMouseEvents = ( + ignore: boolean, + options?: Electron.IgnoreMouseEventsOptions, +) => { + if (!mainWindow) return; + mainWindow.setIgnoreMouseEvents(ignore, options); +}; +export const toggleDevTools = () => { + if (!mainWindow) return; + if (mainWindow.webContents.isDevToolsOpened()) { + mainWindow.webContents.closeDevTools(); + } else { + mainWindow.webContents.openDevTools({ + mode: "detach", + }); + } +}; + +export const setFullScreen = (isFullscreen: boolean): boolean => { + if (!mainWindow) return false; + if (isLinux) { + // linux It needs to be resizable before it can be full screen + if (isFullscreen) { + mainWindow.setResizable(isFullscreen); + mainWindow.setFullScreen(isFullscreen); + } else { + mainWindow.setFullScreen(isFullscreen); + mainWindow.setResizable(isFullscreen); + } + } else { + mainWindow.setFullScreen(isFullscreen); + } + return isFullscreen; +}; + +export const clearCache = async () => { + if (!mainWindow) throw new Error("main window is undefined"); + await mainWindow.webContents.session.clearCache(); + await mainWindow.webContents.session.clearStorageData(); +}; + +export const getCacheSize = async () => { + if (!mainWindow) throw new Error("main window is undefined"); + return await mainWindow.webContents.session.getCacheSize(); +}; + +export const getWebContents = (): Electron.WebContents => { + if (!mainWindow) throw new Error("main window is undefined"); + return mainWindow.webContents; +}; diff --git a/pc-client/electron/preload/index.ts b/pc-client/electron/preload/index.ts new file mode 100644 index 0000000..cdc15f4 --- /dev/null +++ b/pc-client/electron/preload/index.ts @@ -0,0 +1,118 @@ +import fs from "fs"; +import path from "path"; +import { DataPath, IElectronAPI } from "./../../src/types/globalExpose.d"; +import { contextBridge, ipcRenderer } from "electron"; +import { isProd } from "../utils"; +import "@openim/electron-client-sdk/lib/preload"; +import { Platform } from "@openim/wasm-client-sdk"; + +const getPlatform = () => { + if (process.platform === "darwin") { + return Platform.MacOSX; + } + if (process.platform === "win32") { + return Platform.Windows; + } + return Platform.Linux; +}; + +const getDataPath = (key: DataPath) => { + switch (key) { + case "public": + return isProd ? ipcRenderer.sendSync("getDataPath", "public") : ""; + case "sdkResources": + return isProd ? ipcRenderer.sendSync("getDataPath", "sdkResources") : ""; + case "logsPath": + return isProd ? ipcRenderer.sendSync("getDataPath", "logsPath") : ""; + default: + return ""; + } +}; + +const subscribe = (channel: string, callback: (...args: any[]) => void) => { + const subscription = (_, ...args) => callback(...args); + ipcRenderer.on(channel, subscription); + return () => ipcRenderer.removeListener(channel, subscription); +}; + +const subscribeOnce = (channel: string, callback: (...args: any[]) => void) => { + ipcRenderer.once(channel, (_, ...args) => callback(...args)); +}; + +const unsubscribeAll = (channel: string) => { + ipcRenderer.removeAllListeners(channel); +}; + +const ipcInvoke = (channel: string, ...arg: any) => { + return ipcRenderer.invoke(channel, ...arg); +}; + +const ipcSendSync = (channel: string, ...arg: any) => { + return ipcRenderer.sendSync(channel, ...arg); +}; + +const getUniqueSavePath = (originalPath: string) => { + let counter = 0; + let savePath = originalPath; + let fileDir = path.dirname(originalPath); + let fileName = path.basename(originalPath); + let fileExt = path.extname(originalPath); + let baseName = path.basename(fileName, fileExt); + + while (fs.existsSync(savePath)) { + counter++; + fileName = `${baseName}(${counter})${fileExt}`; + savePath = path.join(fileDir, fileName); + } + + return savePath; +}; + +const getFileByPath = async (filePath: string) => { + try { + const filename = path.basename(filePath); + const data = await fs.promises.readFile(filePath); + return new File([data], filename); + } catch (error) { + console.log(error); + return null; + } +}; + +const saveFileToDisk = async ({ + file, + sync, +}: { + file: File; + sync?: boolean; +}): Promise => { + const arrayBuffer = await file.arrayBuffer(); + const saveDir = ipcRenderer.sendSync("getDataPath", "sdkResources"); + const savePath = path.join(saveDir, file.name); + const uniqueSavePath = getUniqueSavePath(savePath); + if (!fs.existsSync(saveDir)) { + fs.mkdirSync(saveDir, { recursive: true }); + } + if (sync) { + await fs.promises.writeFile(uniqueSavePath, Buffer.from(arrayBuffer)); + } else { + fs.promises.writeFile(uniqueSavePath, Buffer.from(arrayBuffer)); + } + return uniqueSavePath; +}; + +const Api: IElectronAPI = { + getDataPath, + getVersion: () => process.version, + getPlatform, + getSystemVersion: process.getSystemVersion, + subscribe, + subscribeOnce, + unsubscribeAll, + ipcInvoke, + ipcSendSync, + getFileByPath, + saveFileToDisk, +}; + +contextBridge.exposeInMainWorld("electronAPI", Api); diff --git a/pc-client/electron/utils/imsdk.ts b/pc-client/electron/utils/imsdk.ts new file mode 100644 index 0000000..e451617 --- /dev/null +++ b/pc-client/electron/utils/imsdk.ts @@ -0,0 +1,22 @@ +import path from "path"; +import os from "os"; +import OpenIMSDKMain from "@openim/electron-client-sdk"; +import { WebContents } from "electron"; + +export const getLibSuffix = () => { + const platform = process.platform; + const arch = os.arch(); + if (platform === "darwin") { + return path.join(`mac_${arch === "arm64" ? "arm64" : "x64"}`, "libopenimsdk.dylib"); + } + if (platform === "win32") { + return path.join(`win_${arch === "ia32" ? "ia32" : "x64"}`, "libopenimsdk.dll"); + } + return path.join(`linux_${arch === "arm64" ? "arm64" : "x64"}`, "libopenimsdk.so"); +}; + +export const initIMSDK = (webContents: WebContents) => + new OpenIMSDKMain( + path.join(global.pathConfig.imsdkLibPath, getLibSuffix()), + webContents, + ); diff --git a/pc-client/electron/utils/index.ts b/pc-client/electron/utils/index.ts new file mode 100644 index 0000000..a86076c --- /dev/null +++ b/pc-client/electron/utils/index.ts @@ -0,0 +1,4 @@ +export const isLinux = process.platform == "linux"; +export const isWin = process.platform == "win32"; +export const isMac = process.platform == "darwin"; +export const isProd = !process.env.VITE_DEV_SERVER_URL; diff --git a/pc-client/electron/utils/log.ts b/pc-client/electron/utils/log.ts new file mode 100644 index 0000000..ebac9ff --- /dev/null +++ b/pc-client/electron/utils/log.ts @@ -0,0 +1,17 @@ +import log from "electron-log/main"; +import { join } from "node:path"; +import fs from "fs"; + +const getLogger = (logsPath: string) => { + log.transports.file.level = "debug"; + log.transports.file.maxSize = 104857600; // max size 100M + log.transports.file.format = "[{y}-{m}-{d} {h}:{i}:{s}.{ms}] [{level}]{scope} {text}"; + let date = new Date(); + // let dateStr = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate(); + // log.transports.file.resolvePathFn = () => join(logsPath, `log${dateStr}.log`); + log.transports.file.resolvePathFn = () => join(logsPath, `OpenIM.log`); + log.initialize({ preload: true }); + return log.scope("ipcMain"); +}; + +export { getLogger }; diff --git a/pc-client/index.html b/pc-client/index.html new file mode 100644 index 0000000..c2bdb35 --- /dev/null +++ b/pc-client/index.html @@ -0,0 +1,18 @@ + + + + + + + + 畅联 + + +
+ + + + diff --git a/pc-client/package-lock.json b/pc-client/package-lock.json new file mode 100644 index 0000000..825cdcc --- /dev/null +++ b/pc-client/package-lock.json @@ -0,0 +1,16323 @@ +{ + "name": "OpenCorp-Base", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "OpenCorp-Base", + "version": "1.0.0", + "hasInstallScript": true, + "dependencies": { + "@ant-design/icons": "^5.1.4", + "@ckeditor/ckeditor5-react": "^8.0.0", + "@livekit/components-react": "2.6.9", + "@livekit/components-styles": "1.1.4", + "@openim/electron-client-sdk": "^3.8.3-patch.10", + "@openim/wasm-client-sdk": "^3.8.3-patch.10", + "adm-zip": "^0.5.10", + "ahooks": "^3.7.7", + "antd": "5.10.0", + "axios": "^1.4.0", + "ckeditor5": "^43.0.0", + "clsx": "^1.2.1", + "date-fns": "^2.30.0", + "dayjs": "^1.11.7", + "electron-log": "^5.0.0", + "electron-screenshots": "^0.5.27", + "electron-store": "^8.1.0", + "electron-updater": "^5.3.0", + "emoji-picker-element": "1.21.3", + "i18next": "^22.5.0", + "i18next-browser-languagedetector": "^7.0.2", + "i18next-fs-backend": "^2.2.0", + "livekit-client": "2.7.0", + "localforage": "^1.10.0", + "md5": "^2.3.0", + "mitt": "^3.0.0", + "react-draggable": "^4.4.5", + "react-i18next": "^12.3.1", + "react-image-file-resizer": "^0.4.8", + "react-query": "^3.39.3", + "react-resizable-panels": "^2.0.2", + "react-router-dom": "^6.11.1", + "react-use": "^17.4.0", + "react-virtuoso": "4.3.8", + "sudo-prompt": "^9.2.1", + "twemoji": "14.0.1", + "uuid": "^9.0.1", + "xgplayer": "^3.0.5", + "zustand": "^4.3.3" + }, + "devDependencies": { + "@commitlint/cli": "^17.4.4", + "@commitlint/config-conventional": "^17.4.4", + "@playwright/test": "^1.31.0", + "@types/md5": "^2.3.2", + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "@types/uuid": "^9.0.1", + "@typescript-eslint/eslint-plugin": "^5.53.0", + "@typescript-eslint/parser": "^5.53.0", + "@vitejs/plugin-legacy": "^4.1.0", + "@vitejs/plugin-react": "^3.1.0", + "autoprefixer": "^10.4.13", + "electron": "^22.3.27", + "electron-builder": "^23.6.0", + "eslint": "^8.34.0", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "husky": "^8.0.3", + "lint-staged": "^13.1.2", + "patch-package": "^8.0.0", + "postcss": "^8.4.21", + "postcss-nesting": "^12.0.2", + "prettier": "^2.8.4", + "prettier-plugin-tailwindcss": "^0.2.3", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.58.3", + "tailwindcss": "^3.2.7", + "terser": "^5.19.0", + "typescript": "^4.9.5", + "vite": "^4.1.4", + "vite-electron-plugin": "^0.8.2", + "vite-plugin-electron": "^0.11.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@ant-design/colors": { + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/@ant-design/colors/-/colors-7.2.1.tgz", + "integrity": "sha512-lCHDcEzieu4GA3n8ELeZ5VQ8pKQAWcGGLRTQ50aQM2iqPpq2evTxER84jfdPvsPAtEcZ7m44NI45edFMo8oOYQ==", + "license": "MIT", + "dependencies": { + "@ant-design/fast-color": "^2.0.6" + } + }, + "node_modules/@ant-design/cssinjs": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@ant-design/cssinjs/-/cssinjs-1.24.0.tgz", + "integrity": "sha512-K4cYrJBsgvL+IoozUXYjbT6LHHNt+19a9zkvpBPxLjFHas1UpPM2A5MlhROb0BT8N8WoavM5VsP9MeSeNK/3mg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "@emotion/hash": "^0.8.0", + "@emotion/unitless": "^0.7.5", + "classnames": "^2.3.1", + "csstype": "^3.1.3", + "rc-util": "^5.35.0", + "stylis": "^4.3.4" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/fast-color": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/@ant-design/fast-color/-/fast-color-2.0.6.tgz", + "integrity": "sha512-y2217gk4NqL35giHl72o6Zzqji9O7vHh9YmhUVkPtAOpoTCH4uWxo/pr4VE8t0+ChEPs0qo4eJRC5Q1eXWo3vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.24.7" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@ant-design/icons": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/@ant-design/icons/-/icons-5.6.1.tgz", + "integrity": "sha512-0/xS39c91WjPAZOWsvi1//zjx6kAp4kxWwctR6kuU6p133w8RU0D2dSCvZC19uQyharg/sAvYxGYWl01BbZZfg==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/icons-svg": "^4.4.0", + "@babel/runtime": "^7.24.8", + "classnames": "^2.2.6", + "rc-util": "^5.31.1" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/@ant-design/icons-svg": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@ant-design/icons-svg/-/icons-svg-4.5.0.tgz", + "integrity": "sha512-1BTUFyKPTBZ53MuTP8s0k5SFEXL7o3VHEOwLgzaoWKwnBeqIcqUtVshc4SKzhI6uACfqhJqBwBUE9FsWR3uULA==", + "license": "MIT" + }, + "node_modules/@ant-design/react-slick": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@ant-design/react-slick/-/react-slick-1.0.2.tgz", + "integrity": "sha512-Wj8onxL/T8KQLFFiCA4t8eIRGpRR+UPgOdac2sYzonv+i0n3kXHmvHLLiOYL655DQx2Umii9Y9nNgL7ssu5haQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.4", + "classnames": "^2.2.5", + "json2mq": "^0.2.0", + "resize-observer-polyfill": "^1.5.1", + "throttle-debounce": "^5.0.0" + }, + "peerDependencies": { + "react": ">=16.9.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.7.tgz", + "integrity": "sha512-Aup7aUOfpbAUg2ROOJN6Iw5f9DMBlzu0mIkm/malLQFN/YQgO48wCj0Kxa3sEHJvPVFg7siR+qRInwXd2qhQKw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.29.7", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.7.tgz", + "integrity": "sha512-locTkQyKvwIEgBzVrn8693ebc97F2U8ZHjbXwDXJ5Fn2TCpNwTlKcaKLkdHop5c/icOFE7qt7Q9JC5hnKNa6Gg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.7.tgz", + "integrity": "sha512-RgHBCvtjbOK2gXSNBNIkNoEc9qoVEtau3hj8gEqKQuL3HZAibKarWFEI3Lfm6EYKkLalOh8eSrj9b+ch9H/VBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helpers": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.8.tgz", + "integrity": "sha512-gZbepsdh3WDtgZKWL+vTPh71LSBrm/Y4/QDZBVCcYfmeTEEuoOYwlSy+G1StfJg+/Zy550u/3TATbm7qDbbMtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.8", + "@babel/types": "^7.29.8", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.29.7.tgz", + "integrity": "sha512-OoK6239jHPuSQOoS0kfTVKn0b/rVTk0seKq4Gd2UMLtmOVLjDC0ki3e+c90Trqv2gMfvJFqkiljrr568+qddiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.29.7.tgz", + "integrity": "sha512-wem6WaBj4NaVYVdNhLPPVacES6ZJ+KBBfSkTMD3YZxbP3rm3Di85tJU5ljaUNhaOynt+Aj0xruhYuzQBt8n71g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.7.tgz", + "integrity": "sha512-IY3ZD9Tmooqr3TUhc3DUWxiuo8xx1DWLhd5M7hQ+ZWJamqM2BbalrBJb2MisSLoYorOj75U03qULCxQTY9r3hg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/traverse": "^7.29.7", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.29.7.tgz", + "integrity": "sha512-907Uymvqgg1dwUA+7IGwFAOSYzQOuzPXKNJ1yxzwPffzkYFg2q2eHi1fIOs6sXkG9NbIUMunnUlkYsfRFNvomg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz", + "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-plugin-utils": "^7.28.6", + "debug": "^4.4.3", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.11" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.29.7.tgz", + "integrity": "sha512-3nQVUAtvkKH9zahfWgw96Jc/uFOmjACE1kQz82E2lqWmHBgjzbNlsC22nuQTfahmWeQtTq5nQ/4Nnd2A1wj4zA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.29.7.tgz", + "integrity": "sha512-j+7JYmk1JYDtACIGj0QJqqWZjoUpMoEikQGADMaHgCMCSDqd2+P32rfcibUNrGOMWrlzK1WJBdxrB3JJQZwWtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.29.7.tgz", + "integrity": "sha512-ejHwrQQYcm9xnTivShn2IDOlIzInN34AXskvq9QicvCtEzq1Vzclu/tKF8Jq1Cg8JG2GL6/EmjgsCT7lXepE3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.29.7.tgz", + "integrity": "sha512-UPUVSyXbOh627KiCIGQSgwWzGeBKLkaJ9PJEdrngIwMSzxLR4jS4+f1f1jb7VzBbg8nFLaYotvVPFCTqdrmTAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.29.7.tgz", + "integrity": "sha512-+kmGVjcT9RGYzoDwdwEqEvGgKe3BYq+O1iGzjFubaNgZHwYHP6lsF2Yghf4kEuv9BV7tYDZ913aBW9am6YKong==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.29.7.tgz", + "integrity": "sha512-G7sHYigPY17oO5SYWnfD/0MTBwVR781S/JI643e/JhUYgVgWE/61SoW3NH9KWUKyKq5LVh3npif99Wkt6j86Jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.29.7.tgz", + "integrity": "sha512-16AMiW26DbXWBbr3B8wNozKM0ydMLB892vaOaJW/fPJdnT8vJk5sdkQcU/isqUxyCE0cEoa8wZOcbgDuC4b6Og==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-wrap-function": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.29.7.tgz", + "integrity": "sha512-atfGXWSeCiF4DnKZIfmJfQRkSw9b9gNNXR1kqKjbhG4pGYCOnkp8OcTB8E3NXjBu8NpheSnOeNKz8KT7UNFTmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.29.7", + "@babel/helper-optimise-call-expression": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.29.7.tgz", + "integrity": "sha512-brcMGQaVzIeUb+6/bs1Av0f8YuNNjKY2JyvfRCsFuFsdKccEQ5Ges2y74D74NZ1Rz8lKJ9ksJkfqwQFJ/iNEyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz", + "integrity": "sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz", + "integrity": "sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.29.7.tgz", + "integrity": "sha512-N9ZErrD+yW5geCDtBqnOoxmR8+tNKiGuxKlDpuJxfsqpa2dFcexaziGAE/qoHLiDDreVNMupxGmSoNlyvsA3gw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.29.7.tgz", + "integrity": "sha512-iES0Skag9ERIF68aXadpO6dbXa03mNWK3sEqJaMnLNs/eC3l0lkImdfoy6Y09/SfkpawdAB4RjQ7PVA7TcVGdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/traverse": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.7.tgz", + "integrity": "sha512-1k2lAGRMfHTcwuNYcCNUmaUffmQv8KWMfh2iJUUeRlwlwH4FdNG7mfPI10NPfLHJFThE4Tyr4mv7kTNZOiPuBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.8.tgz", + "integrity": "sha512-E8lTAYNB1KW+FH+VGJuZM1ioAx2E6oVlvQFRrf5P8ZZmsiJXYAD9vTFV7yyEURNzgh1dFqMZuO6tUwcARbqFCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.8" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.29.7.tgz", + "integrity": "sha512-j8SrR0zLZrRsC09DlszEx8FpMiwukKffYXMK0d5LmOglO7vGG6sz/BR/20yHqWH+Lnn31JTt2PE3hIWNgM2J6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.29.7.tgz", + "integrity": "sha512-r8j8escF+U2FUHo0KOhPUdMzUO+jp9fInva6+ACVAF3Y97Ev+5iNZwiqTghmzNeWwDkOPlYuTcfb1vDaoZKmAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.29.7.tgz", + "integrity": "sha512-GE1TFSiuFeGsCxmYXZl8HwoPrVlwe4rHPFE8weieGKZqnDORK+Ar3vgWMgW+AOxQ6/2TgLSKx9p6W7O4rC6qgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.7.tgz", + "integrity": "sha512-oBNVCvnO5tND+xSopWvV8WNGfpTfgP4Zr/YXXSj8zfmcPktp5Ku/aZlsIowgSD4fjmgHn6sGmB9APVsU5zOdhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.29.7.tgz", + "integrity": "sha512-QQt9qKHZ2sg/kivaLr7lnQr8HVrQDdBNSfCsTjiDxRuX/K5ORyKq+Bu8Xr0cDE3Dfkv0cw28Ve0EKyKMvulkOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.29.7.tgz", + "integrity": "sha512-pn6QacGLgvCcwc+syUhKE/qSjV2D1IHDB84RNxWYSt1mW3K/SCtjinZ2p0cETJxAWBjPy3K/1lHwG5BjjPxNlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.29.7.tgz", + "integrity": "sha512-/An1OCBN93thpBAGyfsK2pcf0jvju1SAtKkL2Ny++B5Sy6sqgzXDQH1cZxWbF96Wuk+bn41MDA9bLd4VVAw6rw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.29.7.tgz", + "integrity": "sha512-zGYcYfq/WmZ4V+kBIXQon9dSSc8ircGZqw9ZaNhhGj9nZkeBu1jHLBDQqYYi5WA9uawvA2sIMbry2nCFhf5Djg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.29.7.tgz", + "integrity": "sha512-N7zArUXWzAMzm+/N0uPBeVB3Fam5lMxtUwMmDK5f/IBBS7a7p1qeUoxd/6CckXoxUdgsntq1Dh8xNW06maZbDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.7.tgz", + "integrity": "sha512-d98gXZkgswvkyohMBABkhm3GeXhYj8psWfwQ2C7gtfrKGTykQa/iOIi+JJhwMjPlZ6Vm2XN+DCf3Es1EoG4ZLA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.29.7.tgz", + "integrity": "sha512-pcUb2SS+RMo9TWVBwKGI5ShtoG7R+zBsFmCKDa6fe8c+hPr3XJlZgoE5j6i8W7gDjhyvy+85vmYexanvXh3d1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-remap-async-to-generator": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.29.7.tgz", + "integrity": "sha512-cUSmjh72N+rN4PrkFlN1dJwNCwjVp5d38/CQrEsFggkD10UiFlBFgdH3tv5dNsLuHY+3S8db2xCHjhZcv5WgvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.29.7.tgz", + "integrity": "sha512-ONyr4+AZhKh8yKWInVxU9AXA9EbsyeLcL6V0dJy6M2/62vuvpGm29zzuymbTpdc451GEpDIdAyPLP3r+P61yKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.29.7.tgz", + "integrity": "sha512-GtcpjFvanPfzNQi3eTitsCqtRRmmqzpy/A+yhTR1HaZo1Ly3EA8ZXxlPyHdR8/IuRMYc3E4wdGBewB2QKQjAaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.29.7.tgz", + "integrity": "sha512-kibJgmEdX2iMwsHY2tSZNDgj8PwIlCQz7FK9KuGKO8zsuoUwSEhoNnNVp/emKWrbY4HeO6kkXfdMqRKKKXBm2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.29.7.tgz", + "integrity": "sha512-qV0OGGBVacduzQHE649JyCneOFI/maT+YKsO+K4Yi3xv2wTPNjM/W2o2gdzMwEAZz7fXNTHAe0NcSg30bIN69g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-globals": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.29.7.tgz", + "integrity": "sha512-RK7/IyU5phpuCdBAuig5VkzG/EnbDaui5SQGdU9BFrHdV+mV4cUjLMQ9lJDjLNtWHsqtiefpGZUXQP2BiTYMsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/template": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.29.7.tgz", + "integrity": "sha512-iPX8aD6H9zV5s7ZsqTdNocPN/MGQ5sSMnElKrktxjJRMnB2jN/1p2+R7GkfD6CAYoVFqy5A4XnSIUeGgJzIWpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.29.7.tgz", + "integrity": "sha512-3qc18hsD2RdZiyJNDNc7HQpv6xbncwh8FYtxNFFzclSyh/trPD9KkVR9BDECUjDLvb7yJVF15GfYUuC+LMkkiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.29.7.tgz", + "integrity": "sha512-6IvRRriEMqnBwD6chtxdLpMYCHWEzN+oL5cyQtjykya19UgzbmKhxmhZgKC/LHxS2nYr9Q/qYPZ5Lr6jOL9+yQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-2wiIyo2BjtgU7HufSeDnL9L2O7zr8jmhFKuSr65VpRkUiRKRNpb0mdlk56+XPPKoIrfHqzbMuglDvZun0RISsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.29.7.tgz", + "integrity": "sha512-giOlEm/EFjfjr+te9NsdjkUo2v4f8rS/SXPumRVHAtbNcyNlvtREkU1dZzaIDclNpnaVhlCqRdFKhJBjBikzLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.29.7.tgz", + "integrity": "sha512-Rstj7coNz8sE+7Ju7ihpHLI564lsK5pUpNNlvptCIC/16E/S5hbl6n3kESPKdNRmqEWlpn5xpS5Q2dvXBsySLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.29.7.tgz", + "integrity": "sha512-zFpMOTLZBdW5LfObqcSbL6kefg4R4eLdmvS0wbN9M6D5Mym/sKm9toOoWyVOa+xDjvCnuWcHls2YonXwHvH3CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.29.7.tgz", + "integrity": "sha512-24B2nOy2TeJSMheqwPD4DDQOV/elLSIlKxjZt4i05H5AgdPdWR3n18HnNrcJ+j76WJd9gbwb9jPjNYUy6RautA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.29.7.tgz", + "integrity": "sha512-zeSIHh0+E1Um1WJRXCFlHQYu2ieJNdivLLjlBEp+dIBu3S51n+SZZmIXjxnItw6pz56Cn+KvK68BIBVsxq2JiQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.29.7.tgz", + "integrity": "sha512-otRWaHXE6fbAGkePvaj/kvs3HsqXfPhlnzwSOlnFgbqCPMd975dW+4wZ00WFBt+/YlBGcJwNrARQTOJOb4ZrIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.29.7.tgz", + "integrity": "sha512-RRnE2+eon1rJAq8MnoF1b5kTpY1vU88twHcvcKMrsqP/jxIRqDVs9iJB5fqPuqyeFAW0wJo4MlUIPpQCq/aRsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.29.7.tgz", + "integrity": "sha512-DZ/oLP21ZuWx1vKqnoNv6/tvEK48AQOBRai40CX9dTjGluvT/YZCyY3rryDtyUqCEoyNroy5KKPwX2iQCiRvyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.29.7.tgz", + "integrity": "sha512-A0H91hh6W8MFRkp5TqJmMr39jzGD1A1E1Ysiv2O06Sfbhkapm+XyIzxWCEh5kqwOZ1/8QZ0dY3SeQ7XBqfJd5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.29.7.tgz", + "integrity": "sha512-hl1kwFZCCiDyfH25Xmco9jTrkPgnS9pmOzSG7W5I4SaGbLeqKv417hcU2RKmaxoPEgsoJh7ZPOrnPGq99bHoUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.29.7.tgz", + "integrity": "sha512-fxtQoH3m5ywUSIfaH0FGCzWu4McsYon5bD3K4XnskC7f+OyQMj7rsOMi4NvvmJ83WwBAg4UCe+ov4VZlqEvyew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.29.7.tgz", + "integrity": "sha512-j0vCldybPC5b5dwCQOJ21uKtHzt7hxLygJTg9eF1ScfaikEDNfzn94XoW5Fi+seBR0nCyL23xaBFFkq7dTM8XQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.8.tgz", + "integrity": "sha512-6iSnEK0zlkLKU4heofK/AdmRD4e2SHVpJMtrwnTCzhnaM98ria4rTrOXBBi45BTTYnJtO8txnPsX4fChYXkmeA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7", + "@babel/traverse": "^7.29.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.29.7.tgz", + "integrity": "sha512-B4UkaTK3QpgCwJnrxKfMPKdo92CN7OKXAlpAAnM3UPu0Q0lCCk57ylA9AJbRy2v8dDKOPAAWcoR6CMyeoHwRCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.7.tgz", + "integrity": "sha512-vuFoLwr4qnv2xbZ16SQd6uPcH5FNrLHhk/Jzo++0XJFcaDsr4gjJVg6j398oMHiC+83k/GiBzviwF5KBJkPUtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.29.7.tgz", + "integrity": "sha512-fEo41GmsOUhOBlw8ioo6zvjX5Xc2Lqkzlyfqbpsk3eB6TReV18uhxZ0esfEokVbY2+PVJAQHNKxER6lGrzNd3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.29.7.tgz", + "integrity": "sha512-idmp1dFaekP9GbcMvG24Kvw2BfhFZjHnNJCkV4WuIY4PskJzwI3f1N5OdgYke38T7rftO6ERulFRn2cFeZwRkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.29.7.tgz", + "integrity": "sha512-zR7fv/z14OjgHl4AgRtkDBvBMhIzCxqV/qN/2BCRC7LjFwvuzjYe7gDWxC4Wl/SNsLM6SE1IWvRPYMgSJaUvNw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.29.7.tgz", + "integrity": "sha512-Ld98jn4c0smUywL57m7SgsHq3OpThOa6LqZJif3G6jYOovPleoFhVrBJ1WegRApSFB2wu4+RelAj9AC9G08Z4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/traverse": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.29.7.tgz", + "integrity": "sha512-Ea/diGcw0twB5IlZPO5sgET6fJsLJqPABqTuFWIR+iMPGPZJkATEIWx0wa+aEQ5UY1CBQyP/gkAiLEqn1vBiQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-replace-supers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.29.7.tgz", + "integrity": "sha512-sLsyndxK2VwX6yNUOakMb7Sh553ZTe/vVM1XJ+9Z5aW1ytsc8xOIwmyk05NNjN60vkc5/KqoTH6hB4V41LJhng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.29.7.tgz", + "integrity": "sha512-6GM1dhvK3gNODkXcEcMCOLEDCLSoZ/sBbro2Ax8HURyasQ4NshagQixkRFdh5niI6E4gmA/jYI/4aT7rRos3ZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.29.7.tgz", + "integrity": "sha512-ZDOBqV/qLYJI0YElr8DcENEyARsFQeESqWXH6gZlghYXuPPjvweuDhP4VyEi4BlUBlLRFZVjxoZDMjxhLW766g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.29.7.tgz", + "integrity": "sha512-/6Rz4DK1ETDEM/bWHsPHcaEe7ZaT1EqSXjtSP/L0DijOYuaUhiRiOKcwpZ8P7zR4xXEHc2ITdiCgBm9Tpyv9ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.29.7.tgz", + "integrity": "sha512-+BNo06dnrzdNNqCm1X6YUaVv0DKk8Q+JYcoZfOkLhYWNCXzlwTSRq8zGWayT1csjcpNXV9CQTBRRbmTLZac5cA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.29.7", + "@babel/helper-create-class-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.29.7.tgz", + "integrity": "sha512-bOMRLQuI0A5ZqHq3OWJ89/rXpJ/NJrbVhXiP4zwPGMs6kpcVsuTUNjwoE30K0Qm3mf48a/TnRYYD6vPNqcg6jA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.29.7.tgz", + "integrity": "sha512-TL0hMc9xzy86VD31nUiwzd5otRAcyEPcsegCxolO0PvcXuH1v0kECe/UIznYFihpkvU5wg/jk4v0TTEFfm53fw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.29.7.tgz", + "integrity": "sha512-06IyK09H3wi4cGbhDBwp5gUGo0IKtnYa8tyTiephirPCK6fbobVGiXMMI5zLQ4aKEYP3wZ3ArU44o+8KMrSG/Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.8.tgz", + "integrity": "sha512-0UpIXPtdDtMXfnV2OJAVMLpj3H/92vmkA6lpSRakmycJvj3VUy6Xs1dM8tXRugupykr5WB+LpiVl0J8LMVg2mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.29.7.tgz", + "integrity": "sha512-mB5Fs0VWrJ42ZCmc8114v60qetdaUVNkj9PmSZRmanCZM3S9hm0CFRLjRmYIsuXav14l2jvZ+4T8iiCGnhj3nQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.29.7.tgz", + "integrity": "sha512-5+YhdpVgmfSmwZyLMftfaiffLRMHjzIRHFHHLdibcSyJm2pasMrKHrO3Ptrt2DRshjvpgjEJJ1zVW14WPq/6QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.29.7.tgz", + "integrity": "sha512-I+WYbGBAiCn7nA6xBrlgPH+MB7HWb4u8pv5S0Pv7OtwNvIFvCCb24YlttKEeUFVurfBCEaOTnuhlqsb7f0Z5Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.29.8.tgz", + "integrity": "sha512-4S9ksMGVWUshvgK0mKfvZky7leuG5/uoFVwMpAomJ8bMoDJiNHRVmc1EglwW/CmGVSqqWpEbXm9FmbRit22qoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.29.7.tgz", + "integrity": "sha512-BCHzNYJGe9l7EpwwDBN/ztlL2NYFFq8hp9ddjtUEM9f2O7S7kKV/lL6Fwo7IF7NSkYhPK2vO+86nIGltA90MsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.29.7.tgz", + "integrity": "sha512-NCSEJ4sLFU2gqAub45HYh4fus2yQ36rr6ei6vpU7NdoJqCpxvEG8E6eJpscGyXP3VHD2Ny+fSXr04k1hoUrFqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.29.7.tgz", + "integrity": "sha512-223mNGoTkBiTEWFoK+Q6Go3tueMRclO8vxxxxquNCYuNI4jWOofFKJRRDu6SDrB8Sgo1UEGW9T4GAQ8ZyRso1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.29.7.tgz", + "integrity": "sha512-jCfXxSjf94lf4E0hKE0AByxF6F3/pVFqRdUUNkDJhsY0m1ZKjnN6ZYyMeHNpzflxb/0q5b7t3p+BE+SLF1WOtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.29.7.tgz", + "integrity": "sha512-OgZ+zoAJgZLUCunsTRQ5LAjOywDv5zzZ2/hQ5aMw1pGXyY2rtE8/chXYUmu3AlVHKpm10KEdG9aMwbI/K76ZGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.29.7.tgz", + "integrity": "sha512-7D/x/23/d/3VqZ0QA+LGbZMlGwZjztBygSWWWsfTPoQ1oQ6Q1P6Mr3d0kk42XabyUVw+fha3LqdRsFqeKqvCyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.29.7.tgz", + "integrity": "sha512-BLOhLht9DOJwIxlmp91wHvkXv1lguuHS3/FwUO8HL1H0u8s4hR1gASVFyilu9iGtcTRYqjTZmlsFFeQletntEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.7.tgz", + "integrity": "sha512-GYzX36n1nsciIb0uyH0GHwxwtNwPQIcpxSeiVLDtG/B7jB5xXgchnmL1f/jCX5o+pwnaDBtO60ONSJhEBJfxYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.29.7", + "@babel/helper-compilation-targets": "^7.29.7", + "@babel/helper-plugin-utils": "^7.29.7", + "@babel/helper-validator-option": "^7.29.7", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.29.7", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.29.7", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.29.7", + "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.7", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.29.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.29.7", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.29.7", + "@babel/plugin-syntax-import-attributes": "^7.29.7", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.29.7", + "@babel/plugin-transform-async-generator-functions": "^7.29.7", + "@babel/plugin-transform-async-to-generator": "^7.29.7", + "@babel/plugin-transform-block-scoped-functions": "^7.29.7", + "@babel/plugin-transform-block-scoping": "^7.29.7", + "@babel/plugin-transform-class-properties": "^7.29.7", + "@babel/plugin-transform-class-static-block": "^7.29.7", + "@babel/plugin-transform-classes": "^7.29.7", + "@babel/plugin-transform-computed-properties": "^7.29.7", + "@babel/plugin-transform-destructuring": "^7.29.7", + "@babel/plugin-transform-dotall-regex": "^7.29.7", + "@babel/plugin-transform-duplicate-keys": "^7.29.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-dynamic-import": "^7.29.7", + "@babel/plugin-transform-explicit-resource-management": "^7.29.7", + "@babel/plugin-transform-exponentiation-operator": "^7.29.7", + "@babel/plugin-transform-export-namespace-from": "^7.29.7", + "@babel/plugin-transform-for-of": "^7.29.7", + "@babel/plugin-transform-function-name": "^7.29.7", + "@babel/plugin-transform-json-strings": "^7.29.7", + "@babel/plugin-transform-literals": "^7.29.7", + "@babel/plugin-transform-logical-assignment-operators": "^7.29.7", + "@babel/plugin-transform-member-expression-literals": "^7.29.7", + "@babel/plugin-transform-modules-amd": "^7.29.7", + "@babel/plugin-transform-modules-commonjs": "^7.29.7", + "@babel/plugin-transform-modules-systemjs": "^7.29.7", + "@babel/plugin-transform-modules-umd": "^7.29.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.7", + "@babel/plugin-transform-new-target": "^7.29.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.29.7", + "@babel/plugin-transform-numeric-separator": "^7.29.7", + "@babel/plugin-transform-object-rest-spread": "^7.29.7", + "@babel/plugin-transform-object-super": "^7.29.7", + "@babel/plugin-transform-optional-catch-binding": "^7.29.7", + "@babel/plugin-transform-optional-chaining": "^7.29.7", + "@babel/plugin-transform-parameters": "^7.29.7", + "@babel/plugin-transform-private-methods": "^7.29.7", + "@babel/plugin-transform-private-property-in-object": "^7.29.7", + "@babel/plugin-transform-property-literals": "^7.29.7", + "@babel/plugin-transform-regenerator": "^7.29.7", + "@babel/plugin-transform-regexp-modifiers": "^7.29.7", + "@babel/plugin-transform-reserved-words": "^7.29.7", + "@babel/plugin-transform-shorthand-properties": "^7.29.7", + "@babel/plugin-transform-spread": "^7.29.7", + "@babel/plugin-transform-sticky-regex": "^7.29.7", + "@babel/plugin-transform-template-literals": "^7.29.7", + "@babel/plugin-transform-typeof-symbol": "^7.29.7", + "@babel/plugin-transform-unicode-escapes": "^7.29.7", + "@babel/plugin-transform-unicode-property-regex": "^7.29.7", + "@babel/plugin-transform-unicode-regex": "^7.29.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.29.7", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.15", + "babel-plugin-polyfill-corejs3": "^0.14.0", + "babel-plugin-polyfill-regenerator": "^0.6.6", + "core-js-compat": "^3.48.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.7.tgz", + "integrity": "sha512-Nq8OhGWiZIZGV6hLHoyAKLLcJihP/xFeBMGJoUrxTX2psI8dCifzLhZISFb+VWS3wFMRDmCGw5R+dOySCqPLhw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.29.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.29.7.tgz", + "integrity": "sha512-puq+Gf35oI24FeN11LkoUQFqv9uwNeWpxXZi/Ji3rRIoKAzKnxRaZ+Gkj0vKS9ZCiTESfng1N9LyOyXvo+m+Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/parser": "^7.29.7", + "@babel/types": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.8.tgz", + "integrity": "sha512-I5z7H3bf/41ktsNVLtpN0wAa336HkqIHQ5BuPLEhTkt1jVSyZpeNKIzTgEWmlxjdg81R0IgUCcaE+Ok3NvrfZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.7", + "@babel/generator": "^7.29.8", + "@babel/helper-globals": "^7.29.7", + "@babel/parser": "^7.29.8", + "@babel/template": "^7.29.7", + "@babel/types": "^7.29.8", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.8", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.8.tgz", + "integrity": "sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.29.7", + "@babel/helper-validator-identifier": "^7.29.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bufbuild/protobuf": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@bufbuild/protobuf/-/protobuf-1.10.1.tgz", + "integrity": "sha512-wJ8ReQbHxsAfXhrf9ixl0aYbZorRuOWpBNzm8pL8ftmSxQx/wnJD5Eg861NwJU/czy2VXFIebCeZnZrI9rktIQ==", + "license": "(Apache-2.0 AND BSD-3-Clause)" + }, + "node_modules/@ckeditor/ckeditor5-adapter-ckfinder": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-43.3.1.tgz", + "integrity": "sha512-fOnEq31euR9B/awWZCOc8KfgLwwG4ACtqBhSv7Hu6VOgHa5TKWyWAdhr9ILSiUp7NMfYJoTQStbxcXZIWPqQXQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-upload": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-alignment": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-43.3.1.tgz", + "integrity": "sha512-E+04zNdNBFDNgQajrWl8iFQqA1sB29y/XDFFRK+bzhcUaWdMadr88yodjHHdcax8/zI+GzBElCvWGEGchyrL+Q==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-autoformat": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-43.3.1.tgz", + "integrity": "sha512-hSQxIXIObrMfxijMPmz8odOtz/wD5SwuGZWVoF5km3EtRQxZwAcQr1Vjy+VHHPo6PZ+o3YoLP+IHCaULtNobYg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-autosave": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-43.3.1.tgz", + "integrity": "sha512-28667m7ea0wBZMb3uIzgipanB4DrDvKn4o+mRUDExlRT8M14vn1u/ILX8ZJy28Rihbg2wPcVh6rP3zoQjcucHw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-basic-styles": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-43.3.1.tgz", + "integrity": "sha512-1RBnPmgsIoxPL7wZhId2KsfPujITbEAfzHhi0c6m4kuWlkmcVXYldWvUvCvAUguAznx4LOxhKlp6RdFSPTFTbg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-block-quote": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-43.3.1.tgz", + "integrity": "sha512-cgY4GKwMlIVLnhszPoc1ortp+T/s3TLowrwRFtWYxTKSsHWBGFlZUL6oMASPunpXvvJqHcgnKlCMxVSh2VMCkQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-enter": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-ckbox": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-43.3.1.tgz", + "integrity": "sha512-KObL9w/QBWJi0lG2zfm+x124Kzd7aVt+UaJHJEwsAPwhZvqM0LCUeR6wwb0oCN6ph5qrCjXoj09z7z8Txk5IwA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-upload": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "blurhash": "2.0.5", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-ckfinder": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-43.3.1.tgz", + "integrity": "sha512-Yji6c1/0H5fExDcT+NNyQQePx2cd8Ul1Xuko1UVmsLN2Vhi7VIDJjEkCFndJozd8VQqI62Obe1GTyjmapBV5+A==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-clipboard": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-43.3.1.tgz", + "integrity": "sha512-Ke6fVEy1fF3AWHMtKvF1pAoDYBVOG4q+gDHD8+dcV6KPK1uA/CR0mw6TZsslQQquT4jC79y05IWu2bq1Mxv01w==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "@ckeditor/ckeditor5-widget": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-cloud-services": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-43.3.1.tgz", + "integrity": "sha512-JppySF+uWedDXPTVZBsTfZCe3qedDAdWSgw0Ww/qi4/sPFcgf/MaQ0LBHbl2Ii7JlJjng82F1F2kv9Ny/Rkauw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-code-block": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-43.3.1.tgz", + "integrity": "sha512-UGhGCPNfFXLua0TmszLSWX6BlkemaPULN1EZ+FBPsUZb757qWWWVWI9GKLmAc4jSPqOv+azU+JAZJzX9bE1oYA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-clipboard": "43.3.1", + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-enter": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-core": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-43.3.1.tgz", + "integrity": "sha512-6pil2OF4auF3PKrg1Oa86CqC91ZYc+NuHih0ebM0JW/I06d+0smnJg5dw4yN7mKbghbJS8mNrusxA5cf6Hkh6w==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "@ckeditor/ckeditor5-watchdog": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-easy-image": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-43.3.1.tgz", + "integrity": "sha512-Cd5NojL0Vfa1SQj6uzbP3oSHvQY5ys2hXF/2jNsYKLePTCybSvGkg5REv1JifM6kSNRH1VXdad7a2LkqvXnCnA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-upload": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-editor-balloon": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-balloon/-/ckeditor5-editor-balloon-43.3.1.tgz", + "integrity": "sha512-klS1FZG29nJE/XbfRXrXtwYU/9uCFdi7xGbYfaJnmyNt54h46aiquKacosbiffA87Tr5sT3Oqm3dBbNlsU158w==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-editor-classic": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-43.3.1.tgz", + "integrity": "sha512-wjBeXUQBuvz6CmGlb5XncJ9cHE7tozU6eoorycfSTQCzqr5uE57LWTlKclU42w7MgS2ya5V2kLnncr0ZqrZ2Vw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-editor-decoupled": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-43.3.1.tgz", + "integrity": "sha512-aw2iZ+WCcCu9sUAnsHhsXZWLeVPyiLhZfpZDuEWjPlvsrCfT0RfSuwMcfx7l9PREA09VR8+6MTstm61EG8dmWQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-editor-inline": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-43.3.1.tgz", + "integrity": "sha512-3iZiWl2aM1bCnS52NeBoAqCVowABhWrBlns27JEGKZ+LNPZroMie7uKuMX3YQGYE2awFnsyP6XofoJtu6CcKCA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-editor-multi-root": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-multi-root/-/ckeditor5-editor-multi-root-43.3.1.tgz", + "integrity": "sha512-HDgfTuotrHW91AZ+x+lumwo1tngRRZ87dnHT8kjSRFWAeXPSd2Kw986++Oj9K080+idZaYLF+IutAOqvCT32sw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-engine": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-43.3.1.tgz", + "integrity": "sha512-Fkv3ibQLDPVHFH0z4/+gA5wrkPVWOen+Cjv/NecNBeAszZUo+F2j9RwvQ1zHwtGb0RWj3+BWOPgo8jhSe7tFgA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-utils": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-enter": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-43.3.1.tgz", + "integrity": "sha512-xaHnU2RbfYi8ilfN260pB3YDvJ9lE4SfiFQusyRdWkeBo5gDAGBbQY+qCC/hmxkr/yftNZfK+d7Ow93xXtqEwg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-essentials": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-43.3.1.tgz", + "integrity": "sha512-bZtzXhmBz8XF9J4eUxOjURmw0HJPKIqo18a6vNxg07W8z3ouHMb9ke//4z4FF9N/1dbtA7a2+jIACO6WvXrX4A==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-clipboard": "43.3.1", + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-enter": "43.3.1", + "@ckeditor/ckeditor5-select-all": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-undo": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-find-and-replace": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-find-and-replace/-/ckeditor5-find-and-replace-43.3.1.tgz", + "integrity": "sha512-U9dyK8yQgxGTUphRbqdUJbvfi5v7zzijCo3Kj51NxyWwOFh7SGReQxHDGn44DmSRold6lg4F1sbXeFdwu1o+WA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-font": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-43.3.1.tgz", + "integrity": "sha512-NOeBtScqMuBLVWFPuW0snleh7rMFkNb006yzDIG6JApnF3Vxi0JLQXub/lPHPgw5srqJ3z159DWT++exoyz/mQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-heading": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-43.3.1.tgz", + "integrity": "sha512-cc8H027Y2OwvYDGMTbBSzE+oZaiLMZtlUnkgiolMw/OQ59ysONYi+KqyMzBMTuaXrkP3CLM57ZbsVGASQ3IQmQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-paragraph": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-highlight": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-43.3.1.tgz", + "integrity": "sha512-XVJq1YP4IAaWQBAyY1xlKOfzkpnclUH8zTUPaW3TZUGK5t6W/vFT+KAzYfUp7PdBb+PP8/O47FwKTvIQBkbqFw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-horizontal-line": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-43.3.1.tgz", + "integrity": "sha512-zkKe0S9gBXwveBUzUuCBPWyrzHQor/zcMCCX9YQk1StUxtRRsURNvWOoFeoG+Vf5jMGSA2gpnBgIo70WrX4A3A==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-widget": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-html-embed": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-43.3.1.tgz", + "integrity": "sha512-VqIhhPwMgAzmPqjvQUQYaFmCFglkg203W+LSVCwrvgVZ9mVtKbkhwCHBJnLhG7qatar7Gg93bObfAFdAjsaR2A==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "@ckeditor/ckeditor5-widget": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-html-support": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-support/-/ckeditor5-html-support-43.3.1.tgz", + "integrity": "sha512-cnQ+kCPYH5GiSe5S+13Fr0vuS7DzT4Onx11fvOkssUujtAJ1e/C7hNf5Ehd+SOAgr5IzevutA/+OeR2KHGjIag==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-enter": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "@ckeditor/ckeditor5-widget": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-image": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-43.3.1.tgz", + "integrity": "sha512-QgHxZtWpclzQ5SUrh1oMsGFCvjykxge5IKe96iKUyAVrhyQp60RhW8DdAElHnPUg3wwILMYE7cKMphknCxcVkQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-clipboard": "43.3.1", + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-undo": "43.3.1", + "@ckeditor/ckeditor5-upload": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "@ckeditor/ckeditor5-widget": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-indent": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-43.3.1.tgz", + "integrity": "sha512-CPU50tumKH7rJ6f9QEB/LHSyzKul9xP/43F1IesvOBWnOkAxQ2QI51oORT5WdKn4B0Z56ojAm48Q/ZUtsef+3w==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-language": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-language/-/ckeditor5-language-43.3.1.tgz", + "integrity": "sha512-M7npJRhLoZksnvjZ0fS+6hbAN4RebgZCE2bT9b3Z8Df2Alfy0GJEwJL5aQsYpr+78QFeytTpqzjxXLNLjOyEqA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-link": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-43.3.1.tgz", + "integrity": "sha512-duTA7harmvZPZ2LbJ8tHnOrhx5lGk6AGavbDzK2xuicMncivm+amrkl/b771uA3Rr6gclHY77ZPcOuVaK+dp/g==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-clipboard": "43.3.1", + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "@ckeditor/ckeditor5-widget": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-list": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-43.3.1.tgz", + "integrity": "sha512-PuR6uJ/SKvaXIgqTO3MUnX+00/xB/TalStiVqZqqG0xlYg47/eb6hul+4fmTPV7ahlJaon6Y3nO49TsPbbhApQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-clipboard": "43.3.1", + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-enter": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-markdown-gfm": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-markdown-gfm/-/ckeditor5-markdown-gfm-43.3.1.tgz", + "integrity": "sha512-aVP2FqQP7okSAorQoItcYRbOd0J2O1ubGjtvGGzl3uC5TuKAtlWYWcBfiVTHKxCCtxywPRiEgBxwoGuB5mlwhA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-clipboard": "43.3.1", + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "ckeditor5": "43.3.1", + "marked": "4.0.12", + "turndown": "7.2.0", + "turndown-plugin-gfm": "1.0.2" + } + }, + "node_modules/@ckeditor/ckeditor5-media-embed": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-43.3.1.tgz", + "integrity": "sha512-3xMIaH/NTNEKv+lu1cRIIPGgDJgYI1DB+5NMXNVL3UGQkXdqW7PtgFDsOnhQwTAbyKpy+fHDngLb3eZuRdDkKw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-clipboard": "43.3.1", + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-undo": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "@ckeditor/ckeditor5-widget": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-mention": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-43.3.1.tgz", + "integrity": "sha512-yrOdynVNOS72RjTjhFHzv3Ofbm0eTBKFhuibxdKFfHtTR0QIqSVB5jU+aW1+Jq5LG73E+9eYtip5paSjkqJMWQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-minimap": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-minimap/-/ckeditor5-minimap-43.3.1.tgz", + "integrity": "sha512-2b0b4mZtRIHAvN/MFAVeqiGt58TZI7ixLcgJo0MHNesYlIk6v13opDWhQ9oefNe8OwJMkD3fAHMlAcg+fUqA9g==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-page-break": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-page-break/-/ckeditor5-page-break-43.3.1.tgz", + "integrity": "sha512-6AI2GGJveEm/2GESUY01wSPM7AeqHqVuX4Hon20uCAXHYCQkDubOHJ0yV3oFXl7iHeO6Ue2DdlSLayIUXCLoEQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-widget": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-paragraph": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-43.3.1.tgz", + "integrity": "sha512-16ry56X+uXuZEzGZwLS8zpX2DtWN/CHHu5pSz0r2VDZ1zUGLsq/MXutotZfzMMjgdED3x4mJRQE+WgiyRrlKDg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-paste-from-office": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-43.3.1.tgz", + "integrity": "sha512-LLf1KB11jeYLDpQPq0d2QVPxQxp9kEibPAF4rGD4stPpRx9d+DbwmE59Y5wVASKvYJo+yNpR9CGWsE4ZgjwTWw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-clipboard": "43.3.1", + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-react": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-react/-/ckeditor5-react-8.0.0.tgz", + "integrity": "sha512-CyepIX0E7Gsf+imgyV/jtoIDbyqXZ8PRSAACBBVxBOHB+KBYDE/vT6HOU+M5ntAimvt887r1qaTowRR6F1QHlw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "prop-types": "^15.7.2" + }, + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "ckeditor5": ">=42.0.0 || ^0.0.0-nightly", + "react": "^16.13.1 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/@ckeditor/ckeditor5-remove-format": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-43.3.1.tgz", + "integrity": "sha512-m7zvvYzHN/HExT0NoILXauVFI/AKQyuzPqqCI/VO1Ft5mLswXGuK6vmO1U10SmGz85etYZjEipKuouf2Anyqxg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-restricted-editing": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-restricted-editing/-/ckeditor5-restricted-editing-43.3.1.tgz", + "integrity": "sha512-L6sA6UrUPy4Q3AzF8yQGsgEadO1IcZv53Ijevk9KuD7dwLF4f9x4ukUFLlGRpoYHPAW/+RpADp2PPegjKHo9QQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-select-all": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-43.3.1.tgz", + "integrity": "sha512-oYQ8uF6hmlX7OefpJ0FflvKddAkEffg3fKMT2FAINwqxhX+O7h9RQZ79AiOkTab7HUTIkbhM5AlhFJIXiX0Z7Q==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-show-blocks": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-show-blocks/-/ckeditor5-show-blocks-43.3.1.tgz", + "integrity": "sha512-o+IhZnjMmoF2qd4l1GqQqroeIEA29QAIOYfvrdMKZGrzVGmjbvwyNkbJRyZlAYhZqX8tLDPaPGn0tl+onhWtzw==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-source-editing": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-source-editing/-/ckeditor5-source-editing-43.3.1.tgz", + "integrity": "sha512-Pq7WthQAiKa3A3q82bHqNRjQ/xlOpSX9kZHLm+CDH8XACxZbBF6Unz4JPR9zJRuQxkoFs314DM/PG6pPZQgXXA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-theme-lark": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-special-characters": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-special-characters/-/ckeditor5-special-characters-43.3.1.tgz", + "integrity": "sha512-3iwrtISndl5hc+/LuSXht69xqkEv95zg8Qxv+ovREA3pvtgt5u9O0t7ELcmUeTTEs/hJkF2FDplIYQj5zIvO+g==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-style": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-style/-/ckeditor5-style-43.3.1.tgz", + "integrity": "sha512-2+ATPa5y4ZUkak5xFTTDeUPhuCAYB4OPNt/QjMvrQjpEwXoWDJ4f8GqR9oFFsqEGMm65GrUp/xIQW8WRH43Kng==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-table": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-43.3.1.tgz", + "integrity": "sha512-Qr3GkKELnG1EY7Bu9dGQBkGTqhVnygeHKDCTEG9m218shYsI5L6jFftGUzWmJzMpm3hNFkyYv+1YWaIoqfRzIQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-clipboard": "43.3.1", + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "@ckeditor/ckeditor5-widget": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-theme-lark": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-43.3.1.tgz", + "integrity": "sha512-kAgeGx66jT31FFYwAoc43oX5ehQtiYE57OJWlPTXrDXxyq0Y+LYFW2/bp4UVYdZK+OKv9dp1Do3VQfxJoGzFjg==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-ui": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-typing": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-43.3.1.tgz", + "integrity": "sha512-sK45GlrOHqWOphVnzDKe3kofVJGhSRk34UQJnyXgMN+35QJqypnJeBYBnnHWL8+nK0S4zk9oQO3PuiRH6gg/WQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-ui": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-43.3.1.tgz", + "integrity": "sha512-dbR4FK6mCkI89h4Joyf1PZt0Xsq0N+sZg05Z6BpYz6GS9U35C7J9bHxN469dvaIc8bJws4eYJ5x+St3LcvlduQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "color-convert": "2.0.1", + "color-parse": "1.4.2", + "lodash-es": "4.17.21", + "vanilla-colorful": "0.7.2" + } + }, + "node_modules/@ckeditor/ckeditor5-undo": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-43.3.1.tgz", + "integrity": "sha512-UxrWPlHzL/DKuxp4R5mlQvy995Ozehh5hQxY5yvL285Dzv6PY5pk627Wv/qS8AyfLMyVNiFO9bDWBIcT9igQRA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-upload": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-43.3.1.tgz", + "integrity": "sha512-uOEhCgqgiK4V/CnbnuwHU/NUOG4ioQE5KUUtVmRG2xjQKg5C1uIT2dig+wnKw8vOdwVTMD2hVt7/OC/whQuheQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1" + } + }, + "node_modules/@ckeditor/ckeditor5-utils": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-43.3.1.tgz", + "integrity": "sha512-4CyM3AP+DcfuPuw+zceI3UTh3HcusnvFVeRPPw6j3Qe29/jadZYsdvkdo9KsDaiwgx0ctooKCuY9SfAcd/CZNQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-ui": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-watchdog": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-43.3.1.tgz", + "integrity": "sha512-d9gh0QIrrImIe2SFLo/IBLdpgC9REVkvUTv//qLbUaM2ffBboMnpJYPAB/hgl8ev4lkDvCrivlGjc/80COfGTQ==", + "license": "GPL-2.0-or-later", + "dependencies": { + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-widget": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-43.3.1.tgz", + "integrity": "sha512-0naXUVC6BFLnuj3lu5aTfRxmqV6py9+zqGHdJJZ0x8uSg9qcfUCLEQvA59bqzNteRya/lZeZhYKj8IcGnbB1oA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-enter": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@ckeditor/ckeditor5-word-count": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-word-count/-/ckeditor5-word-count-43.3.1.tgz", + "integrity": "sha512-W0Ic7y4/ePVqW22pHuXv5HRAbaDJFO13rUqyTZqU2H2ExZdMbJN6eT/UVhnO1XvKs/+jdKGO3LGWXt9QmmtkhA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "ckeditor5": "43.3.1", + "lodash-es": "4.17.21" + } + }, + "node_modules/@commitlint/cli": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-17.8.1.tgz", + "integrity": "sha512-ay+WbzQesE0Rv4EQKfNbSMiJJ12KdKTDzIt0tcK4k11FdsWmtwP0Kp1NWMOUswfIWo6Eb7p7Ln721Nx9FLNBjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/format": "^17.8.1", + "@commitlint/lint": "^17.8.1", + "@commitlint/load": "^17.8.1", + "@commitlint/read": "^17.8.1", + "@commitlint/types": "^17.8.1", + "execa": "^5.0.0", + "lodash.isfunction": "^3.0.9", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-17.8.1.tgz", + "integrity": "sha512-NxCOHx1kgneig3VLauWJcDWS40DVjg7nKOpBEEK9E5fjJpQqLCilcnKkIIjdBH98kEO1q3NpE5NSrZ2kl/QGJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "conventional-changelog-conventionalcommits": "^6.1.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.8.1.tgz", + "integrity": "sha512-UUgUC+sNiiMwkyiuIFR7JG2cfd9t/7MV8VB4TZ+q02ZFkHoduUS4tJGsCBWvBOGD9Btev6IecPMvlWUfJorkEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^17.8.1", + "ajv": "^8.11.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/ensure": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-17.8.1.tgz", + "integrity": "sha512-xjafwKxid8s1K23NFpL8JNo6JnY/ysetKo8kegVM7c8vs+kWLP8VrQq+NbhgVlmCojhEDbzQKp4eRXSjVOGsow==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^17.8.1", + "lodash.camelcase": "^4.3.0", + "lodash.kebabcase": "^4.1.1", + "lodash.snakecase": "^4.1.1", + "lodash.startcase": "^4.4.0", + "lodash.upperfirst": "^4.3.1" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.8.1.tgz", + "integrity": "sha512-JHVupQeSdNI6xzA9SqMF+p/JjrHTcrJdI02PwesQIDCIGUrv04hicJgCcws5nzaoZbROapPs0s6zeVHoxpMwFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/format": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-17.8.1.tgz", + "integrity": "sha512-f3oMTyZ84M9ht7fb93wbCKmWxO5/kKSbwuYvS867duVomoOsgrgljkGGIztmT/srZnaiGbaK8+Wf8Ik2tSr5eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^17.8.1", + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-17.8.1.tgz", + "integrity": "sha512-UshMi4Ltb4ZlNn4F7WtSEugFDZmctzFpmbqvpyxD3la510J+PLcnyhf9chs7EryaRFJMdAKwsEKfNK0jL/QM4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^17.8.1", + "semver": "7.5.4" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/lint": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-17.8.1.tgz", + "integrity": "sha512-aQUlwIR1/VMv2D4GXSk7PfL5hIaFSfy6hSHV94O8Y27T5q+DlDEgd/cZ4KmVI+MWKzFfCTiTuWqjfRSfdRllCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/is-ignored": "^17.8.1", + "@commitlint/parse": "^17.8.1", + "@commitlint/rules": "^17.8.1", + "@commitlint/types": "^17.8.1" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/load": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.8.1.tgz", + "integrity": "sha512-iF4CL7KDFstP1kpVUkT8K2Wl17h2yx9VaR1ztTc8vzByWWcbO/WaKwxsnCOqow9tVAlzPfo1ywk9m2oJ9ucMqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^17.8.1", + "@commitlint/execute-rule": "^17.8.1", + "@commitlint/resolve-extends": "^17.8.1", + "@commitlint/types": "^17.8.1", + "@types/node": "20.5.1", + "chalk": "^4.1.0", + "cosmiconfig": "^8.0.0", + "cosmiconfig-typescript-loader": "^4.0.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "lodash.uniq": "^4.5.0", + "resolve-from": "^5.0.0", + "ts-node": "^10.8.1", + "typescript": "^4.6.4 || ^5.2.2" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/message": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-17.8.1.tgz", + "integrity": "sha512-6bYL1GUQsD6bLhTH3QQty8pVFoETfFQlMn2Nzmz3AOLqRVfNNtXBaSY0dhZ0dM6A2MEq4+2d7L/2LP8TjqGRkA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/parse": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-17.8.1.tgz", + "integrity": "sha512-/wLUickTo0rNpQgWwLPavTm7WbwkZoBy3X8PpkUmlSmQJyWQTj0m6bDjiykMaDt41qcUbfeFfaCvXfiR4EGnfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/types": "^17.8.1", + "conventional-changelog-angular": "^6.0.0", + "conventional-commits-parser": "^4.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/read": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-17.8.1.tgz", + "integrity": "sha512-Fd55Oaz9irzBESPCdMd8vWWgxsW3OWR99wOntBDHgf9h7Y6OOHjWEdS9Xzen1GFndqgyoaFplQS5y7KZe0kO2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/top-level": "^17.8.1", + "@commitlint/types": "^17.8.1", + "fs-extra": "^11.0.0", + "git-raw-commits": "^2.0.11", + "minimist": "^1.2.6" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.8.1.tgz", + "integrity": "sha512-W/ryRoQ0TSVXqJrx5SGkaYuAaE/BUontL1j1HsKckvM6e5ZaG0M9126zcwL6peKSuIetJi7E87PRQF8O86EW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/config-validator": "^17.8.1", + "@commitlint/types": "^17.8.1", + "import-fresh": "^3.0.0", + "lodash.mergewith": "^4.6.2", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/rules": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-17.8.1.tgz", + "integrity": "sha512-2b7OdVbN7MTAt9U0vKOYKCDsOvESVXxQmrvuVUZ0rGFMCrCPJWWP1GJ7f0lAypbDAhaGb8zqtdOr47192LBrIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@commitlint/ensure": "^17.8.1", + "@commitlint/message": "^17.8.1", + "@commitlint/to-lines": "^17.8.1", + "@commitlint/types": "^17.8.1", + "execa": "^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-17.8.1.tgz", + "integrity": "sha512-LE0jb8CuR/mj6xJyrIk8VLz03OEzXFgLdivBytoooKO5xLt5yalc8Ma5guTWobw998sbR3ogDd+2jed03CFmJA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/top-level": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-17.8.1.tgz", + "integrity": "sha512-l6+Z6rrNf5p333SHfEte6r+WkOxGlWK4bLuZKbtf/2TXRN+qhrvn1XE63VhD8Oe9oIHQ7F7W1nG2k/TJFhx2yA==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@commitlint/types": { + "version": "17.8.1", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.8.1.tgz", + "integrity": "sha512-PXDQXkAmiMEG162Bqdh9ChML/GJZo6vU+7F03ALKDK8zYc6SuAr47LjG7hGYRqUOz+WK0dU7bQ0xzuqFMdxzeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0" + }, + "engines": { + "node": ">=v14" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@csstools/selector-resolve-nested": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@csstools/selector-resolve-nested/-/selector-resolve-nested-1.1.0.tgz", + "integrity": "sha512-uWvSaeRcHyeNenKg8tp17EVDRkpflmdyvbE0DHo6D/GdBb6PDnCYYU6gRpXhtICMGMcahQmj2zGxwFM/WC8hCg==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.13" + } + }, + "node_modules/@csstools/selector-specificity": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.1.1.tgz", + "integrity": "sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss-selector-parser": "^6.0.13" + } + }, + "node_modules/@ctrl/tinycolor": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-3.6.1.tgz", + "integrity": "sha512-SITSV6aIXsuVNV3f3O0f2n/cgyEDWoSqtZMYiAmcsYHydcKrOz3gUxB/iXd/Qf08+IZX4KpgNbvUdMBmWz+kcA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/@develar/schema-utils": { + "version": "2.6.5", + "resolved": "https://registry.npmjs.org/@develar/schema-utils/-/schema-utils-2.6.5.tgz", + "integrity": "sha512-0cp4PsWQ/9avqTVMCtZ+GirikIA36ikvjtHweU4/j8yLtgObI0+JUPhYFScgwlteveGB1rt3Cm8UhN04XayDig==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.0", + "ajv-keywords": "^3.4.1" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/@develar/schema-utils/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@develar/schema-utils/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/@develar/schema-utils/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@electron/get": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@electron/get/-/get-2.0.3.tgz", + "integrity": "sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==", + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "env-paths": "^2.2.0", + "fs-extra": "^8.1.0", + "got": "^11.8.5", + "progress": "^2.0.3", + "semver": "^6.2.0", + "sumchecker": "^3.0.1" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "global-agent": "^3.0.0" + } + }, + "node_modules/@electron/get/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "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/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@electron/get/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@electron/get/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@electron/universal": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@electron/universal/-/universal-1.2.1.tgz", + "integrity": "sha512-7323HyMh7KBAl/nPDppdLsC87G6RwRU02dy5FPeGB1eS7rUePh55+WNWiDPLhFQqqVPHzh77M69uhmoT8XnwMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@malept/cross-spawn-promise": "^1.1.0", + "asar": "^3.1.0", + "debug": "^4.3.1", + "dir-compare": "^2.4.0", + "fs-extra": "^9.0.1", + "minimatch": "^3.0.4", + "plist": "^3.0.4" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/@electron/universal/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, + "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/@emotion/hash": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", + "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", + "license": "MIT" + }, + "node_modules/@emotion/unitless": { + "version": "0.7.5", + "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz", + "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==", + "license": "MIT" + }, + "node_modules/@esbuild/android-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", + "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", + "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", + "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", + "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", + "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", + "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", + "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", + "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", + "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", + "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", + "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", + "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", + "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", + "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", + "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", + "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", + "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", + "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", + "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", + "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", + "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", + "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=12" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.10.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.10.1.tgz", + "integrity": "sha512-cuadcxVFE8sDK6iWJbs8Sn0av2Nrh2QSGQhVlBW9AaAHqHwjWsZHT8LJ4hFGPh7ASBV2deFdM7H/DPjulmh8rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.8.0.tgz", + "integrity": "sha512-0CIZ5itps/8x7BG8dEIhs53BvCUH2PCoogtakwRTut+Arm58sJooJ0AuZhLw2HJYIR5cMLNPBSS728sPho2khQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.12" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.11.tgz", + "integrity": "sha512-qkMCxSR24v2vGkhYDo/UzxfJN3D4syqSjyuTFz6C7XcpU1pASPRieNI0Kj5VP3/503mOfYiGY891ugBX1GlABQ==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.6.0", + "@floating-ui/utils": "^0.2.8" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.12.tgz", + "integrity": "sha512-HpCo8tmWzLVad5s2d19EhAz5zqrrQ6s69qd6moPMQvkOuSwDT1YgRfWSVuc4ennqrgv3OHppiOGMQ7oC13yIww==", + "license": "MIT" + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@livekit/components-core": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/@livekit/components-core/-/components-core-0.11.10.tgz", + "integrity": "sha512-PvFlKq1W64b9GfFjG7L4/o7ulAl5yFFpDTvG+JHQiXkaPaecMPt/qPbs6zdvUlC7om1TGMuW/pIN7o585Xz9Fg==", + "license": "Apache-2.0", + "dependencies": { + "@floating-ui/dom": "1.6.11", + "loglevel": "1.9.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "livekit-client": "^2.5.7", + "tslib": "^2.6.2" + } + }, + "node_modules/@livekit/components-react": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/@livekit/components-react/-/components-react-2.6.9.tgz", + "integrity": "sha512-j43i/Dm8dlI2jxv5wv0s+69QPVqVEjg0y2tyznfs/7RDcaIZsIIzNijPu1kLditerzvzQdRsOgFQ3UWONcTkGA==", + "license": "Apache-2.0", + "dependencies": { + "@livekit/components-core": "0.11.10", + "clsx": "2.1.1", + "usehooks-ts": "3.1.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@livekit/krisp-noise-filter": "^0.2.12", + "livekit-client": "^2.5.7", + "react": ">=18", + "react-dom": ">=18", + "tslib": "^2.6.2" + }, + "peerDependenciesMeta": { + "@livekit/krisp-noise-filter": { + "optional": true + } + } + }, + "node_modules/@livekit/components-react/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@livekit/components-styles": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@livekit/components-styles/-/components-styles-1.1.4.tgz", + "integrity": "sha512-QCupn7tQ/dy/WZclrfsgtDe8peiGYS6Ied1IGkKOysaXo04l90t62SIUTKyxgd0dNDhUDC0p34qCggGZs/44lQ==", + "license": "Apache-2.0", + "engines": { + "node": ">=18" + } + }, + "node_modules/@livekit/mutex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@livekit/mutex/-/mutex-1.0.0.tgz", + "integrity": "sha512-aiUhoThBNF9UyGTxEURFzJLhhPLIVTnQiEVMjRhPnfHNKLfo2JY9xovHKIus7B78UD5hsP6DlgpmAsjrz4U0Iw==", + "license": "Apache-2.0" + }, + "node_modules/@livekit/protocol": { + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/@livekit/protocol/-/protocol-1.24.0.tgz", + "integrity": "sha512-9dCsqnkMn7lvbI4NGh18zhLDsrXyUcpS++TEFgEk5Xv1WM3R2kT3EzqgL1P/mr3jaabM6rJ8wZA/KJLuQNpF5w==", + "license": "Apache-2.0", + "dependencies": { + "@bufbuild/protobuf": "^1.10.0" + } + }, + "node_modules/@malept/cross-spawn-promise": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@malept/cross-spawn-promise/-/cross-spawn-promise-1.1.1.tgz", + "integrity": "sha512-RTBGWL5FWQcg9orDOCcp4LvItNzUPcyEU9bwaeJX0rJ1IQxzucC48Y0/sQLp/g6t99IQgAlGIaesJS+gTn7tVQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/malept" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/subscription/pkg/npm-.malept-cross-spawn-promise?utm_medium=referral&utm_source=npm_fund" + } + ], + "license": "Apache-2.0", + "dependencies": { + "cross-spawn": "^7.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@malept/flatpak-bundler": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@malept/flatpak-bundler/-/flatpak-bundler-0.4.0.tgz", + "integrity": "sha512-9QOtNffcOF/c1seMCDnjckb3R9WHcG34tky+FHpNKKCW0wc/scYLwMtO+ptyGUfMW0/b/n4qRiALlaFHc9Oj7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.1.1", + "fs-extra": "^9.0.0", + "lodash": "^4.17.15", + "tmp-promise": "^3.0.2" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@malept/flatpak-bundler/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, + "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/@mixmark-io/domino": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", + "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==", + "license": "BSD-2-Clause" + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@openim/electron-client-sdk": { + "version": "3.8.3-patch.15.1", + "resolved": "https://registry.npmjs.org/@openim/electron-client-sdk/-/electron-client-sdk-3.8.3-patch.15.1.tgz", + "integrity": "sha512-a2l8f+aN6sMOQaWqyl/TZ2LqySpwsuf6+MIr7QzhQrYX8BR/RZY5U411VGBm1eal9gP6ZcUHWg/sYItY8y1gCQ==", + "license": "AGPL-3.0-only", + "dependencies": { + "koffi": "2.8.0" + }, + "engines": { + "node": ">=18.0" + }, + "peerDependencies": { + "@openim/wasm-client-sdk": ">=3.8.3-patch.15.1 <3.9.0", + "electron": ">=12.0.0" + } + }, + "node_modules/@openim/wasm-client-sdk": { + "version": "3.8.3-patch.15.1", + "resolved": "https://registry.npmjs.org/@openim/wasm-client-sdk/-/wasm-client-sdk-3.8.3-patch.15.1.tgz", + "integrity": "sha512-X34t69RxIALLppmdg4/HJaWQCFdA9JhbedOMW7zoAV81g87+8ZP3RgWsqbyBxBGfQIkf/rjfhpeApbeWf4Oa/g==", + "license": "AGPL-3.0-only", + "engines": { + "node": ">=12.0" + } + }, + "node_modules/@parcel/watcher": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.6.0.tgz", + "integrity": "sha512-7FNeNl8NCE7aINx7WXiKQrPYZWC/hvrTsmk6zmxbI7LTXE7hVek/n8AfVgpe2y82zl3w0HvCHN0bVKMBoJcC0w==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "dependencies": { + "detect-libc": "^2.0.3", + "is-glob": "^4.0.3", + "node-addon-api": "^7.0.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "@parcel/watcher-android-arm64": "2.6.0", + "@parcel/watcher-darwin-arm64": "2.6.0", + "@parcel/watcher-darwin-x64": "2.6.0", + "@parcel/watcher-freebsd-x64": "2.6.0", + "@parcel/watcher-linux-arm-glibc": "2.6.0", + "@parcel/watcher-linux-arm-musl": "2.6.0", + "@parcel/watcher-linux-arm64-glibc": "2.6.0", + "@parcel/watcher-linux-arm64-musl": "2.6.0", + "@parcel/watcher-linux-x64-glibc": "2.6.0", + "@parcel/watcher-linux-x64-musl": "2.6.0", + "@parcel/watcher-win32-arm64": "2.6.0", + "@parcel/watcher-win32-x64": "2.6.0" + } + }, + "node_modules/@parcel/watcher-android-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.6.0.tgz", + "integrity": "sha512-trgpLSCKRC/huFjXX/Smh+0sWe4+YtKfktIToiMl59ghz7z+qkH6kMvNnUbLyRs9N11t8l4svSCs1+5B3rOAhA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.6.0.tgz", + "integrity": "sha512-Y3QV0gl7Q1zbfueunkWIERICbEojQFCgpyG7YqOGNFLsckXyI1xu9mAIUpKY9QBYzBtSkN8dBPwd3yiAO9ovMw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-darwin-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.6.0.tgz", + "integrity": "sha512-Ohv6OpzhUfKYD7Beb8kDvG0jbIxORCYY1JRdZnaBtnjjkJxgD7ZVL0nw2sCYd0yTMKTvz3nnTnOF3cDifK+kvw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-freebsd-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.6.0.tgz", + "integrity": "sha512-5HmXvDgs8VK+74jF9y9/2FE3/OnlcKmc56tjmSrEuZjpSZOGL+fvAu+HKJBdPs9uwoP2hE6TlSUpXZ/C5jUFmQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.6.0.tgz", + "integrity": "sha512-Ps/hui3A+vMbjdqlqAowK2ZL8+BO8dBjxeWXj6npTBs3jx4wWmbPpaLuqwrQrSqIVMCnpWo238bJ1U37GhQOYg==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-musl/-/watcher-linux-arm-musl-2.6.0.tgz", + "integrity": "sha512-9c6AUHgHoG+IY88MRIHupztQiQnrbqHYQjkM2btA+Bf/wQnQMuiD0Wfk1EVv3TlNT3x41uU71rn6E4xh/+zvkw==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.6.0.tgz", + "integrity": "sha512-yHRqS2owEXe6Hic9z6Mh1ECsCd+ODVOGvZDyciqRd21+v+o+DnXMOrw50DSpIG2sb8GPEaPPmfeCAWKPJdq46g==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-arm64-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.6.0.tgz", + "integrity": "sha512-WhB2e/V7rqdHHWZusBSPuy5Ei8S6lSz6FE5TKKQz5h3a0O+C+mhY7vxU9b/stqvMb8beLnPY82ZrFTLKs+SrKA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-glibc": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.6.0.tgz", + "integrity": "sha512-ulGE6x6Oz6iAwg75T8YQSoguBWasniIbX+QWpaYPcCnDOpdWX3k+4xbEYPZVLxOuoJI+svJJPD3sEj8G7lrQ3A==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-linux-x64-musl": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.6.0.tgz", + "integrity": "sha512-tkBYKt7YQrjIJWYDnto2YgO8MRkjlMTSNoRHzsXinBqbLdeOM3L32wPZJvIZxqaLMfSlS/4sUjH/6STVP/XDLw==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-arm64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.6.0.tgz", + "integrity": "sha512-gIZAP23jaHjGWasY/TY6yL7NHFClf0Ga7FN+iINvk+KN94rhm94lYZhFsbYFNcA04/onvGD9kKmiJLJB2HbNwQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher-win32-x64": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.6.0.tgz", + "integrity": "sha512-cA+/pXV2YkfxlIcXOQ5fSWqAzzPyD78/x5qbK/I0vUkrlYHA8TIz+MXjAbGouguKVSI4bOmkTSJ1/poVSsgt+A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/@parcel/watcher/node_modules/node-addon-api": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", + "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@parcel/watcher/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/@playwright/test": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.62.1.tgz", + "integrity": "sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.62.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/@rc-component/color-picker": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@rc-component/color-picker/-/color-picker-1.4.1.tgz", + "integrity": "sha512-vh5EWqnsayZa/JwUznqDaPJz39jznx/YDbyBuVJntv735tKXKwEUZZb2jYEldOg+NKWZwtALjGMrNeGBmqFoEw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@ctrl/tinycolor": "^3.6.0", + "classnames": "^2.2.6", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/context": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@rc-component/context/-/context-1.4.0.tgz", + "integrity": "sha512-kFcNxg9oLRMoL3qki0OMxK+7g5mypjgaaJp/pkOis/6rVxma9nJBF/8kCIuTYHUQNr0ii7MxqE33wirPZLJQ2w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/mini-decimal": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@rc-component/mini-decimal/-/mini-decimal-1.1.4.tgz", + "integrity": "sha512-xiuXcaCwyOWpD8a8scdExFl+bntNphAW8XeenL1ig2en0AAZY0Pcp4pC0dI22qJ+NvxKn9RoNIoRdqYU3BLH4w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0" + }, + "engines": { + "node": ">=8.x" + } + }, + "node_modules/@rc-component/mutate-observer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rc-component/mutate-observer/-/mutate-observer-1.1.0.tgz", + "integrity": "sha512-QjrOsDXQusNwGZPf4/qRQasg7UFEj06XiCJ8iuiq/Io7CrHrgVi6Uuetw60WAMG1799v+aM8kyc+1L/GBbHSlw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/portal": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@rc-component/portal/-/portal-1.1.2.tgz", + "integrity": "sha512-6f813C0IsasTZms08kfA8kPAGxbbkYToa8ALaiDIGGECU4i9hj8Plgbx0sNJDrey3EtHO30hmdaxtT0138xZcg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/tour": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@rc-component/tour/-/tour-1.10.0.tgz", + "integrity": "sha512-voV0BKaTJbewB9LLgAHQ7tAGG7rgDkKQkZo82xw2gIk542hY+o7zwoqdN16oHhIKk7eG/xi+mdXrONT62Dt57A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "@rc-component/portal": "^1.0.0-9", + "@rc-component/trigger": "^1.3.6", + "classnames": "^2.3.2", + "rc-util": "^5.24.4" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@rc-component/trigger": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/@rc-component/trigger/-/trigger-1.18.3.tgz", + "integrity": "sha512-Ksr25pXreYe1gX6ayZ1jLrOrl9OAUHUqnuhEx6MeHnNa1zVM5Y2Aj3Q35UrER0ns8D2cJYtmJtVli+i+4eKrvA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2", + "@rc-component/portal": "^1.1.0", + "classnames": "^2.3.2", + "rc-motion": "^2.0.0", + "rc-resize-observer": "^1.3.1", + "rc-util": "^5.38.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/@remix-run/router": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.3.tgz", + "integrity": "sha512-4An71tdz9X8+3sI4Qqqd2LWd9vS39J7sqd9EU4Scw7TJE/qB10Flv/UuqbPVgfQV9XoK8Np6jNquZitnZq5i+Q==", + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "license": "MIT", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@tootallnate/once": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.1.tgz", + "integrity": "sha512-HqmEUIGRJ5fSXchkVgR5F7qn48bDBzv0kWj/Kfu5e6uci4UlEeng4331LnBkWffb++Ei3FOVLxo8JJWMFBDMeQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz", + "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "dev": true, + "license": "MIT" + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "license": "MIT", + "dependencies": { + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" + } + }, + "node_modules/@types/debug": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz", + "integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ms": "*" + } + }, + "node_modules/@types/fs-extra": { + "version": "9.0.13", + "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-9.0.13.tgz", + "integrity": "sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/minimatch": "*", + "@types/node": "*" + } + }, + "node_modules/@types/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==", + "license": "MIT" + }, + "node_modules/@types/js-cookie": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/js-cookie/-/js-cookie-3.0.6.tgz", + "integrity": "sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/md5": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.3.6.tgz", + "integrity": "sha512-WD69gNXtRBnpknfZcb4TRQ0XJQbUPZcai/Qdhmka3sxUR3Et8NrXoeAoknG/LghYHTf4ve795rInVYHBTQdNVA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/minimatch": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", + "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/ms": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", + "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.5.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.1.tgz", + "integrity": "sha512-4tT2UrL5LBqDwoed9wZ6N3umC4Yhz3W3FloMmiiG4JwmUJWpie0c7lcnUNd4gtMKuDEO4wRVS8B6Xa0uMRsMKg==", + "license": "MIT" + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/plist": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/@types/plist/-/plist-3.0.5.tgz", + "integrity": "sha512-E6OCaRmAe4WDmWNsL/9RMqdkkzDCY1etutkflWk4c+AcjDU07Pcz1fQwTX0TQz+Pxqn9i4L1TU3UFpjnrcDgxA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*", + "xmlbuilder": ">=11.0.1" + } + }, + "node_modules/@types/prop-types": { + "version": "15.7.15", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", + "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.31", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.31.tgz", + "integrity": "sha512-vfEqpXTvwT91yhmwdfouStN2hSKwTvyRs8qpLfADyrq/kxDw0hZM7Wk9Ug1FELj8hIby+S/+kQCSRFF32nv2Qw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "18.3.7", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", + "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^18.0.0" + } + }, + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/semver": { + "version": "7.8.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.8.0.tgz", + "integrity": "sha512-1mAINjtQCXXeLkJ9ehXkwOcBpqtLxiVtKhpUf83DdRNdQKV0iXZpaHYqRr7nj+wvxuJzoAmAwXI+sCNMv1CzLQ==", + "license": "MIT" + }, + "node_modules/@types/uuid": { + "version": "9.0.8", + "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", + "integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/verror": { + "version": "1.10.11", + "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", + "integrity": "sha512-RlDm9K7+o5stv0Co8i8ZRGxDbrTxhJtgjqjFyVh/tXQyl/rYtTKlnTvZ88oSTeYREWurwx20Js4kTuKCsFkUtg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/@types/yargs": { + "version": "17.0.35", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz", + "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.3", + "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", + "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/yauzl": { + "version": "2.10.3", + "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", + "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", + "license": "MIT", + "optional": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "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" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.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.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "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/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "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": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.3.tgz", + "integrity": "sha512-60YRaenCQcVjYEKOcG824+DRGGIQ3VKErcBoAEDJZz5bKIs2ZG+X/H9Nk+Q6EVkwJk5QNApxbrc5QtBSwtrXAg==", + "dev": true, + "license": "ISC" + }, + "node_modules/@vitejs/plugin-legacy": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-legacy/-/plugin-legacy-4.1.1.tgz", + "integrity": "sha512-um3gbVouD2Q/g19C0qpDfHwveXDCAHzs8OC3e9g6aXpKoD1H14himgs7wkMnhAynBJy7QqUoZNAXDuqN8zLR2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.22.9", + "@babel/preset-env": "^7.22.9", + "browserslist": "^4.21.9", + "core-js": "^3.31.1", + "magic-string": "^0.30.1", + "regenerator-runtime": "^0.13.11", + "systemjs": "^6.14.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "peerDependencies": { + "terser": "^5.4.0", + "vite": "^4.0.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-3.1.0.tgz", + "integrity": "sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.12", + "@babel/plugin-transform-react-jsx-self": "^7.18.6", + "@babel/plugin-transform-react-jsx-source": "^7.19.6", + "magic-string": "^0.27.0", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "peerDependencies": { + "vite": "^4.1.0-beta.0" + } + }, + "node_modules/@vitejs/plugin-react/node_modules/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@xmldom/xmldom": { + "version": "0.9.10", + "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.9.10.tgz", + "integrity": "sha512-A9gOqLdi6cV4ibazAjcQufGj0B1y/vDqYrcuP6d/6x8P27gRS8643Dj9o1dEKtB6O7fwxb2FgBmJS2mX7gpvdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.6" + } + }, + "node_modules/@xobotyi/scrollbar-width": { + "version": "1.9.5", + "resolved": "https://registry.npmjs.org/@xobotyi/scrollbar-width/-/scrollbar-width-1.9.5.tgz", + "integrity": "sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==", + "license": "MIT" + }, + "node_modules/@yarnpkg/lockfile": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz", + "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/7zip-bin": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/7zip-bin/-/7zip-bin-5.1.1.tgz", + "integrity": "sha512-sAP4LldeWNz0lNzmTird3uWfFDWWTeg6V/MsmyyLR9X1idwKBWIgt/ZvinqQldJm3LecKEs1emkbquO6PCiLVQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.5", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz", + "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==", + "dev": true, + "license": "MIT", + "dependencies": { + "acorn": "^8.11.0" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adm-zip": { + "version": "0.5.18", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.18.tgz", + "integrity": "sha512-ufJnssQGbxzLNS1Ho9bCtX4rQKCCvoVuDLHoJyc3F9dOGDB4BkWs2Ci0kv53lqocAEQ/Cbi+I2XCsNYGqVYqng==", + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, + "node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/ahooks": { + "version": "3.9.7", + "resolved": "https://registry.npmjs.org/ahooks/-/ahooks-3.9.7.tgz", + "integrity": "sha512-S0lvzhbdlhK36RFBkGv+RbOM/dbbweym+BIHM/bwwuWVSVN5TuVErHPMWo4w0t1NDYg5KPp2iEf7Y7E5LASYiw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0", + "@types/js-cookie": "^3.0.6", + "dayjs": "^1.9.1", + "intersection-observer": "^0.12.0", + "js-cookie": "^3.0.5", + "lodash": "^4.17.21", + "react-fast-compare": "^3.2.2", + "resize-observer-polyfill": "^1.5.1", + "screenfull": "^5.0.0", + "tslib": "^2.4.1" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "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, + "license": "MIT", + "dependencies": { + "type-fest": "^1.0.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/antd": { + "version": "5.10.0", + "resolved": "https://registry.npmjs.org/antd/-/antd-5.10.0.tgz", + "integrity": "sha512-qeyfMhcDK2QeuKaC/OCjNCPrJb+3vrBHvVK2swRHsxJvKFSpRerMCShOn/I3CXogrVJazPMluGhy0FQlcHQ4pw==", + "license": "MIT", + "dependencies": { + "@ant-design/colors": "^7.0.0", + "@ant-design/cssinjs": "^1.17.0", + "@ant-design/icons": "^5.2.6", + "@ant-design/react-slick": "~1.0.2", + "@babel/runtime": "^7.18.3", + "@ctrl/tinycolor": "^3.6.1", + "@rc-component/color-picker": "~1.4.1", + "@rc-component/mutate-observer": "^1.1.0", + "@rc-component/tour": "~1.10.0", + "@rc-component/trigger": "^1.17.0", + "classnames": "^2.2.6", + "copy-to-clipboard": "^3.2.0", + "dayjs": "^1.11.1", + "qrcode.react": "^3.1.0", + "rc-cascader": "~3.18.1", + "rc-checkbox": "~3.1.0", + "rc-collapse": "~3.7.1", + "rc-dialog": "~9.3.3", + "rc-drawer": "~6.5.2", + "rc-dropdown": "~4.1.0", + "rc-field-form": "~1.38.2", + "rc-image": "~7.3.1", + "rc-input": "~1.2.1", + "rc-input-number": "~8.1.0", + "rc-mentions": "~2.8.0", + "rc-menu": "~9.12.2", + "rc-motion": "^2.9.0", + "rc-notification": "~5.2.0", + "rc-pagination": "~3.6.1", + "rc-picker": "~3.14.5", + "rc-progress": "~3.5.1", + "rc-rate": "~2.12.0", + "rc-resize-observer": "^1.3.1", + "rc-segmented": "~2.2.2", + "rc-select": "~14.9.0", + "rc-slider": "~10.3.0", + "rc-steps": "~6.0.1", + "rc-switch": "~4.1.0", + "rc-table": "~7.34.4", + "rc-tabs": "~12.12.1", + "rc-textarea": "~1.4.0", + "rc-tooltip": "~6.1.0", + "rc-tree": "~5.7.12", + "rc-tree-select": "~5.13.0", + "rc-upload": "~4.3.5", + "rc-util": "^5.37.0", + "scroll-into-view-if-needed": "^3.0.3", + "throttle-debounce": "^5.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/ant-design" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true, + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-builder-bin": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/app-builder-bin/-/app-builder-bin-4.0.0.tgz", + "integrity": "sha512-xwdG0FJPQMe0M0UA4Tz0zEB8rBJTRA5a476ZawAqiBkMv16GRK5xpXThOjMaEOFnZ6zabejjG4J3da0SXG63KA==", + "dev": true, + "license": "MIT" + }, + "node_modules/app-builder-lib": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/app-builder-lib/-/app-builder-lib-23.6.0.tgz", + "integrity": "sha512-dQYDuqm/rmy8GSCE6Xl/3ShJg6Ab4bZJMT8KaTKGzT436gl1DN4REP3FCWfXoh75qGTJ+u+WsdnnpO9Jl8nyMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@develar/schema-utils": "~2.6.5", + "@electron/universal": "1.2.1", + "@malept/flatpak-bundler": "^0.4.0", + "7zip-bin": "~5.1.1", + "async-exit-hook": "^2.0.1", + "bluebird-lst": "^1.0.9", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", + "chromium-pickle-js": "^0.2.0", + "debug": "^4.3.4", + "ejs": "^3.1.7", + "electron-osx-sign": "^0.6.0", + "electron-publish": "23.6.0", + "form-data": "^4.0.0", + "fs-extra": "^10.1.0", + "hosted-git-info": "^4.1.0", + "is-ci": "^3.0.0", + "isbinaryfile": "^4.0.10", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "minimatch": "^3.1.2", + "read-config-file": "6.2.0", + "sanitize-filename": "^1.6.3", + "semver": "^7.3.7", + "tar": "^6.1.11", + "temp-file": "^3.4.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/app-builder-lib/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true, + "license": "MIT" + }, + "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==", + "license": "Python-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==", + "dev": true, + "license": "MIT" + }, + "node_modules/array-includes": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-tree-filter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-tree-filter/-/array-tree-filter-2.1.0.tgz", + "integrity": "sha512-4ROwICNlNw/Hqa9v+rk5h22KjmzB1JGTMVKP2AKJBOCgb0yL0ASf0+YvCcLNNwquOHNX48jkeZIJ3a+oOQqKcw==", + "license": "MIT" + }, + "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/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/asar": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", + "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==", + "deprecated": "Please use @electron/asar moving forward. There is no API change, just a package name change", + "dev": true, + "license": "MIT", + "dependencies": { + "chromium-pickle-js": "^0.2.0", + "commander": "^5.0.0", + "glob": "^7.1.6", + "minimatch": "^3.0.4" + }, + "bin": { + "asar": "bin/asar.js" + }, + "engines": { + "node": ">=10.12.0" + }, + "optionalDependencies": { + "@types/glob": "^7.1.1" + } + }, + "node_modules/assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-exit-hook": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/async-exit-hook/-/async-exit-hook-2.0.1.tgz", + "integrity": "sha512-NW2cX8m1Q7KPA7a5M2ULQeZ2wR5qI5PAbw5L0UOMxdioVk9PMZ0h1TmyZEkPYrCvYjDlFICusOu1dlEKAAeXBw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/async-validator": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", + "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", + "license": "MIT" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/atomically": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/atomically/-/atomically-1.7.0.tgz", + "integrity": "sha512-Xcz9l0z7y9yQ9rdDaxlmaI4uJHf/T8g9hOEzJcsEqX2SjCj4J20uK7+ldkDHMbpJDK76wF7xEIgxc/vSlsfw5w==", + "license": "MIT", + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/autoprefixer": { + "version": "10.5.4", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.4.tgz", + "integrity": "sha512-MaU0U/za7N3r6brxD4YB/l4NSrFzLPlANv6wEuQVaIPlD3L4W9rFcQPbL/EilY9BHhHvhfcz3gInDLrEtWT4EA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.6", + "caniuse-lite": "^1.0.30001806", + "fraction.js": "^5.3.4", + "picocolors": "^1.1.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", + "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.16.0", + "form-data": "^4.0.6", + "https-proxy-agent": "^5.0.1", + "proxy-from-env": "^2.1.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.17", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz", + "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-define-polyfill-provider": "^0.6.8", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz", + "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8", + "core-js-compat": "^3.48.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.8", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz", + "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.8" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.11.13", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.11.13.tgz", + "integrity": "sha512-k9HNuUVMlqVjQ9UHzfPjIqiDbWw7WqT1AoT7GL8VwvF3r0ZfArtgiSPAlmupyNquNgOJHTuH4CKYf8ttMTWBTQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/big-integer": { + "version": "1.6.52", + "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", + "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", + "license": "Unlicense", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", + "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/bluebird-lst": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/bluebird-lst/-/bluebird-lst-1.0.9.tgz", + "integrity": "sha512-7B1Rtx82hjnSD4PGLAjVWeYH3tHAcVUmChh85a3lltKQm6FresXh9ErQo6oAv6CqxttczC3/kEg8SY5NluPuUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.5" + } + }, + "node_modules/blurhash": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz", + "integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==", + "license": "MIT" + }, + "node_modules/boolean": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", + "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/broadcast-channel": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", + "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.7.2", + "detect-node": "^2.1.0", + "js-sha3": "0.8.0", + "microseconds": "0.2.0", + "nano-time": "1.0.0", + "oblivious-set": "1.0.0", + "rimraf": "3.0.2", + "unload": "2.2.0" + } + }, + "node_modules/browserslist": { + "version": "4.28.8", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.8.tgz", + "integrity": "sha512-V2NpofLblG64mfOtSgDhOJESZEGogzDMBv/q+W6oc4LXWP/q75eOXoOaaOu1EOadB9U4Bwx/e0yzbvwKH8zalA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.11.12", + "caniuse-lite": "^1.0.30001809", + "electron-to-chromium": "^1.5.402", + "node-releases": "^2.0.53", + "update-browserslist-db": "^1.3.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "optional": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "node_modules/buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true, + "license": "MIT" + }, + "node_modules/buffer-crc32": { + "version": "0.2.13", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", + "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", + "license": "MIT", + "engines": { + "node": "*" + } + }, + "node_modules/buffer-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-equal/-/buffer-equal-1.0.0.tgz", + "integrity": "sha512-tcBWO2Dl4e7Asr9hTGcpVrCe+F7DubpmqWCTbj4FHLmjqO2hIaC383acQubWtRJhdceqs5uBHs6Es+Sk//RKiQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/builder-util": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/builder-util/-/builder-util-23.6.0.tgz", + "integrity": "sha512-QiQHweYsh8o+U/KNCZFSvISRnvRctb8m/2rB2I1JdByzvNKxPeFLlHFRPQRXab6aYeXc18j9LpsDLJ3sGQmWTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/debug": "^4.1.6", + "@types/fs-extra": "^9.0.11", + "7zip-bin": "~5.1.1", + "app-builder-bin": "4.0.0", + "bluebird-lst": "^1.0.9", + "builder-util-runtime": "9.1.1", + "chalk": "^4.1.1", + "cross-spawn": "^7.0.3", + "debug": "^4.3.4", + "fs-extra": "^10.0.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-ci": "^3.0.0", + "js-yaml": "^4.1.0", + "source-map-support": "^0.5.19", + "stat-mode": "^1.0.0", + "temp-file": "^3.4.0" + } + }, + "node_modules/builder-util-runtime": { + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/builder-util-runtime/-/builder-util-runtime-9.1.1.tgz", + "integrity": "sha512-azRhYLEoDvRDR8Dhis4JatELC/jUvYjm4cVSj7n9dauGTOM2eeNn9KS0z6YA6oDsjI1xphjNbY6PZZeHPzzqaw==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "sax": "^1.2.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/builder-util/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cacheable-lookup": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", + "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", + "license": "MIT", + "engines": { + "node": ">=10.6.0" + } + }, + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "license": "MIT", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cacheable-request/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==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/call-bind": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz", + "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "get-intrinsic": "^1.3.0", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "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", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/camelcase-keys/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001809", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001809.tgz", + "integrity": "sha512-xxWVywk6a6Arlk+hymeycyn/VgqEfLDxupvhH/xiY5SJ/18kmi9o6MiO320DCUzypORHLtvh0I4i04tUhCNHNQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/charenc": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", + "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/chokidar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-5.0.0.tgz", + "integrity": "sha512-TQMmc3w+5AxjpL8iIiwebF73dRDF4fBIieAqGn9RGCWaEVwQ6Fb2cGe31Yns0RRIzii5goJ1Y7xbMwo1TxMplw==", + "dev": true, + "license": "MIT", + "dependencies": { + "readdirp": "^5.0.0" + }, + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "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/chromium-pickle-js": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/ci-info": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", + "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/sibiraj-s" + } + ], + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ckeditor5": { + "version": "43.3.1", + "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-43.3.1.tgz", + "integrity": "sha512-ZZ6nIdlr9rCCp21o9d5/mVUeVPwpQKEVxkeq1MU/Jax1w8U6rnMiQWxB954Ky/HNjhZ1v1ll2+VRzb7XA+1emA==", + "license": "GPL-2.0-or-later", + "dependencies": { + "@ckeditor/ckeditor5-adapter-ckfinder": "43.3.1", + "@ckeditor/ckeditor5-alignment": "43.3.1", + "@ckeditor/ckeditor5-autoformat": "43.3.1", + "@ckeditor/ckeditor5-autosave": "43.3.1", + "@ckeditor/ckeditor5-basic-styles": "43.3.1", + "@ckeditor/ckeditor5-block-quote": "43.3.1", + "@ckeditor/ckeditor5-ckbox": "43.3.1", + "@ckeditor/ckeditor5-ckfinder": "43.3.1", + "@ckeditor/ckeditor5-clipboard": "43.3.1", + "@ckeditor/ckeditor5-cloud-services": "43.3.1", + "@ckeditor/ckeditor5-code-block": "43.3.1", + "@ckeditor/ckeditor5-core": "43.3.1", + "@ckeditor/ckeditor5-easy-image": "43.3.1", + "@ckeditor/ckeditor5-editor-balloon": "43.3.1", + "@ckeditor/ckeditor5-editor-classic": "43.3.1", + "@ckeditor/ckeditor5-editor-decoupled": "43.3.1", + "@ckeditor/ckeditor5-editor-inline": "43.3.1", + "@ckeditor/ckeditor5-editor-multi-root": "43.3.1", + "@ckeditor/ckeditor5-engine": "43.3.1", + "@ckeditor/ckeditor5-enter": "43.3.1", + "@ckeditor/ckeditor5-essentials": "43.3.1", + "@ckeditor/ckeditor5-find-and-replace": "43.3.1", + "@ckeditor/ckeditor5-font": "43.3.1", + "@ckeditor/ckeditor5-heading": "43.3.1", + "@ckeditor/ckeditor5-highlight": "43.3.1", + "@ckeditor/ckeditor5-horizontal-line": "43.3.1", + "@ckeditor/ckeditor5-html-embed": "43.3.1", + "@ckeditor/ckeditor5-html-support": "43.3.1", + "@ckeditor/ckeditor5-image": "43.3.1", + "@ckeditor/ckeditor5-indent": "43.3.1", + "@ckeditor/ckeditor5-language": "43.3.1", + "@ckeditor/ckeditor5-link": "43.3.1", + "@ckeditor/ckeditor5-list": "43.3.1", + "@ckeditor/ckeditor5-markdown-gfm": "43.3.1", + "@ckeditor/ckeditor5-media-embed": "43.3.1", + "@ckeditor/ckeditor5-mention": "43.3.1", + "@ckeditor/ckeditor5-minimap": "43.3.1", + "@ckeditor/ckeditor5-page-break": "43.3.1", + "@ckeditor/ckeditor5-paragraph": "43.3.1", + "@ckeditor/ckeditor5-paste-from-office": "43.3.1", + "@ckeditor/ckeditor5-remove-format": "43.3.1", + "@ckeditor/ckeditor5-restricted-editing": "43.3.1", + "@ckeditor/ckeditor5-select-all": "43.3.1", + "@ckeditor/ckeditor5-show-blocks": "43.3.1", + "@ckeditor/ckeditor5-source-editing": "43.3.1", + "@ckeditor/ckeditor5-special-characters": "43.3.1", + "@ckeditor/ckeditor5-style": "43.3.1", + "@ckeditor/ckeditor5-table": "43.3.1", + "@ckeditor/ckeditor5-theme-lark": "43.3.1", + "@ckeditor/ckeditor5-typing": "43.3.1", + "@ckeditor/ckeditor5-ui": "43.3.1", + "@ckeditor/ckeditor5-undo": "43.3.1", + "@ckeditor/ckeditor5-upload": "43.3.1", + "@ckeditor/ckeditor5-utils": "43.3.1", + "@ckeditor/ckeditor5-watchdog": "43.3.1", + "@ckeditor/ckeditor5-widget": "43.3.1", + "@ckeditor/ckeditor5-word-count": "43.3.1" + } + }, + "node_modules/classnames": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz", + "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow==", + "license": "MIT" + }, + "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": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-truncate": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", + "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "slice-ansi": "^3.0.0", + "string-width": "^4.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "license": "MIT", + "dependencies": { + "mimic-response": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "node_modules/color-parse": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.4.2.tgz", + "integrity": "sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==", + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/colors": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.0.3.tgz", + "integrity": "sha512-pFGrxThWcWQ2MsAz6RtgeWe4NK2kUE1WfsrvvlctdII745EW9I0yflqhe7++M5LEc7bV2c/9/5zc8sFcpL0Drw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.1.90" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "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" + } + }, + "node_modules/compare-version": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/compare-version/-/compare-version-0.1.2.tgz", + "integrity": "sha512-pJDh5/4wrEnXX/VWRZvruAGHkzKdr46z11OlTPN+VrATlWWhSKewNCJ1futCO5C7eJB3nPMFZA1LeYtcFboZ2A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/compute-scroll-into-view": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.1.tgz", + "integrity": "sha512-VRhuHOLoKYOy4UbilLbUzbYg93XLjv2PncJC50EuTWPA3gaja1UjBsUP/D/9/juV3vQFr6XBEzn9KCAHdUvOHw==", + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/conf": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/conf/-/conf-10.2.0.tgz", + "integrity": "sha512-8fLl9F04EJqjSqH+QjITQfJF8BrOVaYr1jewVgSRAEWePfxT0sku4w2hrGQ60BC/TNLGQ2pgxNlTbWQmMPFvXg==", + "license": "MIT", + "dependencies": { + "ajv": "^8.6.3", + "ajv-formats": "^2.1.1", + "atomically": "^1.7.0", + "debounce-fn": "^4.0.0", + "dot-prop": "^6.0.1", + "env-paths": "^2.2.1", + "json-schema-typed": "^7.0.3", + "onetime": "^5.1.2", + "pkg-up": "^3.1.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/conf/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==", + "license": "MIT", + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-6.0.0.tgz", + "integrity": "sha512-6qLgrBF4gueoC7AFVHu51nHL9pF9FRjXrH+ceVf7WmAfH3gs+gEYOkvxhjMPjZu57I4AGUGoNTY8V7Hrgf1uqg==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-6.1.0.tgz", + "integrity": "sha512-3cS3GEtR78zTfMzk0AizXKKIdN4OvSh7ibNz6/DPbhWWQu7LqE/8+/GqSodV+sywUR2gpJAdP/1JFf4XtN7Zpw==", + "dev": true, + "license": "ISC", + "dependencies": { + "compare-func": "^2.0.0" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/conventional-commits-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-4.0.0.tgz", + "integrity": "sha512-WRv5j1FsVM5FISJkoYMR6tPk07fkKT0UodruX4je86V4owk451yjXAKzKAPOs9l7y59E2viHUS9eQ+dfUA9NSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.3.5", + "meow": "^8.1.2", + "split2": "^3.2.2" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/copy-to-clipboard": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz", + "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==", + "license": "MIT", + "dependencies": { + "toggle-selection": "^1.0.6" + } + }, + "node_modules/core-js": { + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.50.0.tgz", + "integrity": "sha512-BRWgOLKkFeCgRudR6zrs8p9XJZcE14grzKMMssoYrk6krtuEZ7MTKPIY5RzOnqsEKIR9kst7wNzphttraT+Yqw==", + "hasInstallScript": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-js-compat": { + "version": "3.50.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.50.0.tgz", + "integrity": "sha512-XGpFGbMLHwSt74YLTKho7Ib242qi6O8MSX+sRokV4oz7iKXvQWGYZthjIhjRGMxjzVkAubBO512dKGYcefmX3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.7" + }, + "engines": { + "node": ">=6.4.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.4.0.tgz", + "integrity": "sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=v14.21.3" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=7", + "ts-node": ">=10", + "typescript": ">=4" + } + }, + "node_modules/crc": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/crc/-/crc-3.8.0.tgz", + "integrity": "sha512-iX3mfgcTMIq3ZKLIsVFAbv7+Mc10kxabAGQb8HvjA1o3T1PIYprbakQ65d3I+2HGHt6nSKkM9PYjgoJO2KcFBQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "buffer": "^5.1.0" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypt": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", + "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==", + "license": "BSD-3-Clause", + "engines": { + "node": "*" + } + }, + "node_modules/css-in-js-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/css-in-js-utils/-/css-in-js-utils-3.1.0.tgz", + "integrity": "sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==", + "license": "MIT", + "dependencies": { + "hyphenate-style-name": "^1.0.3" + } + }, + "node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "license": "MIT", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "license": "MIT", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "license": "MIT" + }, + "node_modules/d": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz", + "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==", + "license": "ISC", + "dependencies": { + "es5-ext": "^0.10.64", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/danmu.js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/danmu.js/-/danmu.js-1.2.1.tgz", + "integrity": "sha512-evDEImUBo94c846fC92K//Dzll8jXnZ3zKmYlQHwMzmvw6IW2IyjWL3Ew2SqEAzuqauFnDkwJEgZauu3uW/p1Q==", + "license": "MIT", + "dependencies": { + "event-emitter": "^0.3.5" + } + }, + "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/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/date-fns": { + "version": "2.30.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", + "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0" + }, + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/dayjs": { + "version": "1.11.21", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.21.tgz", + "integrity": "sha512-98IT+HOahAisibz/yjKbzuOBwYcjJ7BCLPzARyHiyEBmRz4fatF+KPJszEHXsGYjUG234aH/cOjW1wwTbKUZlA==", + "license": "MIT" + }, + "node_modules/debounce-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/debounce-fn/-/debounce-fn-4.0.0.tgz", + "integrity": "sha512-8pYCQiL9Xdcg0UPSD3d+0KMlOjp+KGU5EPwYddgzQ7DATsg4fuUDjQtsYLmWjnk2obnNHgV3vE2Y4jejSOJVBQ==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "license": "MIT", + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "license": "MIT", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "license": "MIT" + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "license": "Apache-2.0", + "optional": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-node": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", + "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", + "license": "MIT" + }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/diff": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz", + "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dir-compare": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/dir-compare/-/dir-compare-2.4.0.tgz", + "integrity": "sha512-l9hmu8x/rjVC9Z2zmGzkhOEowZvW7pmYws5CWHutg8u1JgvsKWMx7Q/UODeu4djLZ4FgW5besw5yvMQnBHzuCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-equal": "1.0.0", + "colors": "1.0.3", + "commander": "2.9.0", + "minimatch": "3.0.4" + }, + "bin": { + "dircompare": "src/cli/dircompare.js" + } + }, + "node_modules/dir-compare/node_modules/commander": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.9.0.tgz", + "integrity": "sha512-bmkUukX8wAOjHdN26xj5c4ctEV22TQ7dQYhSmuckKhToXrkUn0iIaolHdIxYYqD55nhpSPA9zPQ1yP57GdXP2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-readlink": ">= 1.0.0" + }, + "engines": { + "node": ">= 0.6.x" + } + }, + "node_modules/dir-compare/node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true, + "license": "MIT" + }, + "node_modules/dmg-builder": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/dmg-builder/-/dmg-builder-23.6.0.tgz", + "integrity": "sha512-jFZvY1JohyHarIAlTbfQOk+HnceGjjAdFjVn3n8xlDWKsYNqbO4muca6qXEZTfGXeQMG7TYim6CeS5XKSfSsGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "app-builder-lib": "23.6.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", + "fs-extra": "^10.0.0", + "iconv-lite": "^0.6.2", + "js-yaml": "^4.1.0" + }, + "optionalDependencies": { + "dmg-license": "^1.0.11" + } + }, + "node_modules/dmg-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/dmg-license": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/dmg-license/-/dmg-license-1.0.11.tgz", + "integrity": "sha512-ZdzmqwKmECOWJpqefloC5OJy1+WZBBse5+MR88z9g9Zn4VY+WYUkAyojmhzJckH5YbbZGcYIuGAkY5/Ys5OM2Q==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "@types/plist": "^3.0.1", + "@types/verror": "^1.10.3", + "ajv": "^6.10.0", + "crc": "^3.8.0", + "iconv-corefoundation": "^1.1.7", + "plist": "^3.0.4", + "smart-buffer": "^4.0.2", + "verror": "^1.10.0" + }, + "bin": { + "dmg-license": "bin/dmg-license.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dmg-license/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/dmg-license/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotenv": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-9.0.2.tgz", + "integrity": "sha512-I9OvvrHp4pIARv4+x9iuewrWycX6CcZtoAu1XrzPxc5UygMJXJZYmBsynku8IkrJwgypE5DGNjDPmPRhDCptUg==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=10" + } + }, + "node_modules/dotenv-expand": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz", + "integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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, + "license": "MIT" + }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron": { + "version": "22.3.27", + "resolved": "https://registry.npmjs.org/electron/-/electron-22.3.27.tgz", + "integrity": "sha512-7Rht21vHqj4ZFRnKuZdFqZFsvMBCmDqmjetiMqPtF+TmTBiGne1mnstVXOA/SRGhN2Qy5gY5bznJKpiqogjM8A==", + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "@electron/get": "^2.0.0", + "@types/node": "^16.11.26", + "extract-zip": "^2.0.1" + }, + "bin": { + "electron": "cli.js" + }, + "engines": { + "node": ">= 12.20.55" + } + }, + "node_modules/electron-builder": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/electron-builder/-/electron-builder-23.6.0.tgz", + "integrity": "sha512-y8D4zO+HXGCNxFBV/JlyhFnoQ0Y0K7/sFH+XwIbj47pqaW8S6PGYQbjoObolKBR1ddQFPt4rwp4CnwMJrW3HAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs": "^17.0.1", + "app-builder-lib": "23.6.0", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", + "chalk": "^4.1.1", + "dmg-builder": "23.6.0", + "fs-extra": "^10.0.0", + "is-ci": "^3.0.0", + "lazy-val": "^1.0.5", + "read-config-file": "6.2.0", + "simple-update-notifier": "^1.0.7", + "yargs": "^17.5.1" + }, + "bin": { + "electron-builder": "cli.js", + "install-app-deps": "install-app-deps.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/electron-builder/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-log": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/electron-log/-/electron-log-5.4.4.tgz", + "integrity": "sha512-istWgaXjBfURBSS8LWVW9C3jsc6+ac+tY1lXrQEOTp0lVj+a4OlO1Tmqb36GgnEUDv92DGC9VI1HNXwJinWpgA==", + "license": "MIT", + "engines": { + "node": ">= 14" + } + }, + "node_modules/electron-osx-sign": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/electron-osx-sign/-/electron-osx-sign-0.6.0.tgz", + "integrity": "sha512-+hiIEb2Xxk6eDKJ2FFlpofCnemCbjbT5jz+BKGpVBrRNT3kWTGs4DfNX6IzGwgi33hUcXF+kFs9JW+r6Wc1LRg==", + "deprecated": "Please use @electron/osx-sign moving forward. Be aware the API is slightly different", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "bluebird": "^3.5.0", + "compare-version": "^0.1.2", + "debug": "^2.6.8", + "isbinaryfile": "^3.0.2", + "minimist": "^1.2.0", + "plist": "^3.0.1" + }, + "bin": { + "electron-osx-flat": "bin/electron-osx-flat.js", + "electron-osx-sign": "bin/electron-osx-sign.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/electron-osx-sign/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/electron-osx-sign/node_modules/isbinaryfile": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-3.0.3.tgz", + "integrity": "sha512-8cJBL5tTd2OS0dM4jz07wQd5g0dCCqIhUxPIGtZfa5L6hWlvV5MHTITy/DBAsF+Oe2LS1X3krBUhNwaGUWpWxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-alloc": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/electron-osx-sign/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-publish": { + "version": "23.6.0", + "resolved": "https://registry.npmjs.org/electron-publish/-/electron-publish-23.6.0.tgz", + "integrity": "sha512-jPj3y+eIZQJF/+t5SLvsI5eS4mazCbNYqatv5JihbqOstIM13k0d1Z3vAWntvtt13Itl61SO6seicWdioOU5dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/fs-extra": "^9.0.11", + "builder-util": "23.6.0", + "builder-util-runtime": "9.1.1", + "chalk": "^4.1.1", + "fs-extra": "^10.0.0", + "lazy-val": "^1.0.5", + "mime": "^2.5.2" + } + }, + "node_modules/electron-publish/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron-screenshots": { + "version": "0.5.28", + "resolved": "https://registry.npmjs.org/electron-screenshots/-/electron-screenshots-0.5.28.tgz", + "integrity": "sha512-caOdogBx6huxfc+x9HG4dGpDwwtpijnY0i9i1S29N2o/Bo6HKHBvAGphP8sq3Ulk5hX5kSDoLKqpxQMWUAOZ+A==", + "license": "MIT", + "dependencies": { + "debug": "^4.3.4", + "fs-extra": "^11.1.1", + "node-screenshots": "^0.2.1", + "react-screenshots": "^0.5.22" + }, + "peerDependencies": { + "electron": ">=14" + } + }, + "node_modules/electron-store": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/electron-store/-/electron-store-8.2.0.tgz", + "integrity": "sha512-ukLL5Bevdil6oieAOXz3CMy+OgaItMiVBg701MNlG6W5RaC0AHN7rvlqTCmeb6O7jP0Qa1KKYTE0xV0xbhF4Hw==", + "license": "MIT", + "dependencies": { + "conf": "^10.2.0", + "type-fest": "^2.17.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.402", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.402.tgz", + "integrity": "sha512-/oOpMaPT6Yg+6/1XQhyIPlzgj7Ye9zf+nNM2Uh6OcE2G2oNptWazFa+qB2Pdqqbsc9KnIDzgAntoYN0dbwOXwA==", + "dev": true, + "license": "ISC" + }, + "node_modules/electron-updater": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/electron-updater/-/electron-updater-5.3.0.tgz", + "integrity": "sha512-iKEr7yQBcvnQUPnSDYGSWC9t0eF2YbZWeYYYZzYxdl+HiRejXFENjYMnYjoOm2zxyD6Cr2JTHZhp9pqxiXuCOw==", + "license": "MIT", + "dependencies": { + "@types/semver": "^7.3.6", + "builder-util-runtime": "9.1.1", + "fs-extra": "^10.0.0", + "js-yaml": "^4.1.0", + "lazy-val": "^1.0.5", + "lodash.escaperegexp": "^4.1.2", + "lodash.isequal": "^4.5.0", + "semver": "^7.3.5", + "typed-emitter": "^2.1.0" + } + }, + "node_modules/electron-updater/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/electron/node_modules/@types/node": { + "version": "16.18.126", + "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz", + "integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw==", + "license": "MIT" + }, + "node_modules/emoji-picker-element": { + "version": "1.21.3", + "resolved": "https://registry.npmjs.org/emoji-picker-element/-/emoji-picker-element-1.21.3.tgz", + "integrity": "sha512-o1wQmPX0+8dmp/v4BfHVSMD2x32ZmCQd5LMHpHTw1M9ltDW99P+IIPbveI7nPxwGw74TW9E6jds6Kitf14UCOg==", + "license": "Apache-2.0" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/end-of-stream": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz", + "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } + }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/error-ex": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz", + "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/es-abstract": { + "version": "1.24.2", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.2.tgz", + "integrity": "sha512-2FpH9Q5i2RRwyEP1AylXe6nYLR5OhaJTZwmlcP0dL/+JCbgg7yyEo/sEK6HeGZRf3dFpWwThaRHVApXSkW3xeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-abstract-get": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-abstract-get/-/es-abstract-get-1.0.0.tgz", + "integrity": "sha512-6PMWXpdhshVvFp+FoWYs1EvG1Nj0tvk0dZM+XcK0xMEM1czRVcP6ohqPWHy6qPagSpC8j4+p89WXlT+xXJs/fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.2", + "is-callable": "^1.2.7", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.4.0.tgz", + "integrity": "sha512-c/A0P0oxkACDc+cKWw8evLXK83oBKgn0qPOqCYT4x9uolpCIJAcYvJC9QYKNDRPsTeGyCrQ326jrvgZWdCdK5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.1.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.3.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.5", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", + "integrity": "sha512-HWcBoN6NileqtSydK2FqHbS/LoDd2pqrnQHLyJzBj4kOp/ky2MWMN694xOfkK8/SnUsW2DH7EfyVlydKCsm1Zw==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.4.tgz", + "integrity": "sha512-yPDz7wqpg1/mmHLmS3tcfTfbw5f1eryXvyghYBffGdERwe+mV7ZcWzTR8LR17Kvqt3qfPurjlonmnq3MKXIOXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-abstract-get": "^1.0.0", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "is-callable": "^1.2.7", + "is-date-object": "^1.1.0", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es5-ext": { + "version": "0.10.64", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz", + "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==", + "hasInstallScript": true, + "license": "ISC", + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "esniff": "^2.0.1", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-error": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", + "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", + "license": "MIT", + "optional": true + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz", + "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.2", + "ext": "^1.7.0" + }, + "engines": { + "node": ">=0.12" + } + }, + "node_modules/esbuild": { + "version": "0.18.20", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", + "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/android-arm": "0.18.20", + "@esbuild/android-arm64": "0.18.20", + "@esbuild/android-x64": "0.18.20", + "@esbuild/darwin-arm64": "0.18.20", + "@esbuild/darwin-x64": "0.18.20", + "@esbuild/freebsd-arm64": "0.18.20", + "@esbuild/freebsd-x64": "0.18.20", + "@esbuild/linux-arm": "0.18.20", + "@esbuild/linux-arm64": "0.18.20", + "@esbuild/linux-ia32": "0.18.20", + "@esbuild/linux-loong64": "0.18.20", + "@esbuild/linux-mips64el": "0.18.20", + "@esbuild/linux-ppc64": "0.18.20", + "@esbuild/linux-riscv64": "0.18.20", + "@esbuild/linux-s390x": "0.18.20", + "@esbuild/linux-x64": "0.18.20", + "@esbuild/netbsd-x64": "0.18.20", + "@esbuild/openbsd-x64": "0.18.20", + "@esbuild/sunos-x64": "0.18.20", + "@esbuild/win32-arm64": "0.18.20", + "@esbuild/win32-ia32": "0.18.20", + "@esbuild/win32-x64": "0.18.20" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.2.tgz", + "integrity": "sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.5.tgz", + "integrity": "sha512-9Ni+xgemM2IWLq6aXEpP2+V/V30GeA/46Ar629vcMqVPodFFWC9skHu/D1phvuqtS8bJCFnNf01/qcmqYEwNfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz", + "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.9", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.7", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.7.tgz", + "integrity": "sha512-tqt+NBWwyaMgw3zDsnygx4CByWjQEJHOPMdslYhppaQSJUtL/D4JO9CcBBlhPoI8lz9oJIDXkwXfhF4aWqP8xQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.2", + "node-exports-info": "^1.6.0", + "object-keys": "^1.1.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-plugin-react/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/eslint-plugin-simple-import-sort": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-10.0.0.tgz", + "integrity": "sha512-AeTvO9UCMSNzIHRkg8S6c3RPy5YEwKWSQPx3DYghLedo2ZQxowPFLGDN1AZ2evfg6r6mjBSZSLxLFsWSu3acsw==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=5.0.0" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.15.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz", + "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/esniff": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz", + "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==", + "license": "ISC", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.62", + "event-emitter": "^0.3.5", + "type": "^2.7.2" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==", + "license": "MIT", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/eventemitter3": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", + "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", + "dev": true, + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/ext": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz", + "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==", + "license": "ISC", + "dependencies": { + "type": "^2.7.2" + } + }, + "node_modules/extract-zip": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", + "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", + "license": "BSD-2-Clause", + "dependencies": { + "debug": "^4.1.1", + "get-stream": "^5.1.0", + "yauzl": "^2.10.0" + }, + "bin": { + "extract-zip": "cli.js" + }, + "engines": { + "node": ">= 10.17.0" + }, + "optionalDependencies": { + "@types/yauzl": "^2.9.1" + } + }, + "node_modules/extract-zip/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==", + "license": "MIT", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/extsprintf": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.4.1.tgz", + "integrity": "sha512-Wrk35e8ydCKDj/ArClo1VrPVmN8zph5V4AtHwIuHhvMXsKf73UT3BOD+azBIW+3wOJ4FhEH7zyaJCFvChjYvMA==", + "dev": true, + "engines": [ + "node >=0.6.0" + ], + "license": "MIT", + "optional": true + }, + "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==", + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-shallow-equal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fast-shallow-equal/-/fast-shallow-equal-1.0.0.tgz", + "integrity": "sha512-HPtaa38cPgWvaCFmRNhlc6NG7pv6NUHqjPgVAkWGoB9mQMwYB27/K0CvOM5Czy+qpT3e8XJ6Q4aPAnzpNpzNaw==" + }, + "node_modules/fast-uri": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", + "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/fastest-stable-stringify": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/fastest-stable-stringify/-/fastest-stable-stringify-2.0.2.tgz", + "integrity": "sha512-bijHueCGd0LqqNK9b5oCMHc0MluJAx0cwqASgbWMvkO01lCYgIhacVRLcaDz3QnyYIRNJRDwMb41VuT6pHJ91Q==", + "license": "MIT" + }, + "node_modules/fastq": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz", + "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fd-slicer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", + "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", + "license": "MIT", + "dependencies": { + "pend": "~1.2.0" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/filelist": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.6.tgz", + "integrity": "sha512-5giy2PkLYY1cP39p17Ech+2xlpTRL9HLspOfEgm0L6CwBXBTgsK5ou0JtzYuepxkaQ/tvhCFIJ5uXo0OrM2DxA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/node_modules/minimatch": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", + "integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-yarn-workspace-root": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz", + "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "micromatch": "^4.0.2" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.4.tgz", + "integrity": "sha512-5+ybhBZANEJxaH3X5evAFatUxLfEHSr7n6kYJ+1Qd0mUqr4eu9gIf6GDbWHf8RJijHrjjO8G+la14SlL2SeS1Q==", + "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.16.0", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz", + "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "license": "MIT", + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/form-data": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.6.tgz", + "integrity": "sha512-vKatAh4SlVfgbv+YtmhiRjhEMJsYpsG1Y2rMQtR+SVSbytsSD1YGzDIcrAJmdFec88u/+VoGmxnl+80gL1tRCQ==", + "license": "MIT", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "es-set-tostringtag": "^2.1.0", + "hasown": "^2.0.4", + "mime-types": "^2.1.35" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fraction.js": { + "version": "5.3.4", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", + "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "*" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fs-extra": { + "version": "11.4.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.4.0.tgz", + "integrity": "sha512-EQsFzMUJkCKGr1ePqlYADkIUmHW1s3ZXr5Yqy6wbGrfUCphpl2maM/kyOIRA2HpP3AaFQTZXD4ldjek+nccddA==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "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" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-minipass/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fs-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, + "license": "ISC" + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.2.0.tgz", + "integrity": "sha512-jObKIik1P2QjPHP5nz5BaOtUlfgS0fWo8IUByNXkM+o+02sJOi94em77GwJKQSJ3gfPHdgzLNrHc1uokV4P/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2", + "hasown": "^2.0.4", + "is-callable": "^1.2.7", + "is-document.all": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/git-raw-commits": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", + "integrity": "sha512-VnctFhw+xfj8Va1xtfEqCUD2XDrbAPSJx+hSrE5K7fGdjZruW7XV+QOrN7LF/RJyvspRiD2I0asWsxFp0ya26A==", + "deprecated": "Deprecated and no longer maintained. Use @conventional-changelog/git-client instead.", + "dev": true, + "license": "MIT", + "dependencies": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/global-agent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "license": "BSD-3-Clause", + "optional": true, + "dependencies": { + "boolean": "^3.0.1", + "es6-error": "^4.1.1", + "matcher": "^3.0.0", + "roarr": "^2.15.3", + "semver": "^7.3.2", + "serialize-error": "^7.0.1" + }, + "engines": { + "node": ">=10.0" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globals/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "license": "MIT", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "license": "ISC" + }, + "node_modules/graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha512-8tLu60LgxF6XpdbK8OW3FA+IfTNBn1ZHGHKF4KQbEeSkajYw5PlYJcKluntgegDPTg8UkHjpet1T82vk6TQ68w==", + "dev": true, + "license": "MIT" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/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" + } + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.4.tgz", + "integrity": "sha512-T2UbfbBEF32wiepXIsMlTW9+dDYC6wMh/t/vYA4tuOMKqWz/n3vr1NFSxQiyP+zk2mXsoMA/i/7qV6LKut1t1A==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/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" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/hosted-git-info/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/html-parse-stringify": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.1.0.tgz", + "integrity": "sha512-E0oAXcELOtsXe+BmpJ2EZyedbldPpriV5vICzEuo6xjC/D1lDukOI7KrpfQGF2Qc4wWEy0nk3bFORS2K5ZAhFQ==", + "license": "MIT", + "dependencies": { + "void-elements": "3.1.0" + } + }, + "node_modules/http-cache-semantics": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", + "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", + "license": "BSD-2-Clause" + }, + "node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/http2-wrapper": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", + "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", + "license": "MIT", + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.0.0" + }, + "engines": { + "node": ">=10.19.0" + } + }, + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "license": "MIT", + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/husky": { + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", + "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", + "dev": true, + "license": "MIT", + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/hyphenate-style-name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/hyphenate-style-name/-/hyphenate-style-name-1.1.0.tgz", + "integrity": "sha512-WDC/ui2VVRrz3jOVi+XtjqkDjiVjTtFaAGiW37k6b+ohyQ5wYDOGkvCZa8+H0nx3gyvv0+BST9xuOgIyGQ00gw==", + "license": "BSD-3-Clause" + }, + "node_modules/i18next": { + "version": "22.5.1", + "resolved": "https://registry.npmjs.org/i18next/-/i18next-22.5.1.tgz", + "integrity": "sha512-8TGPgM3pAD+VRsMtUMNknRz3kzqwp/gPALrWMsDnmC1mKqJwpWyooQRLMcbTwq8z8YwSmuj+ZYvc+xCuEpkssA==", + "funding": [ + { + "type": "individual", + "url": "https://locize.com" + }, + { + "type": "individual", + "url": "https://locize.com/i18next.html" + }, + { + "type": "individual", + "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" + } + ], + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.6" + } + }, + "node_modules/i18next-browser-languagedetector": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/i18next-browser-languagedetector/-/i18next-browser-languagedetector-7.2.2.tgz", + "integrity": "sha512-6b7r75uIJDWCcCflmbof+sJ94k9UQO4X0YR62oUfqGI/GjCLVzlCwu8TFdRZIqVLzWbzNcmkmhfqKEr4TLz4HQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.2" + } + }, + "node_modules/i18next-fs-backend": { + "version": "2.6.7", + "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.6.7.tgz", + "integrity": "sha512-nN2TIycyR/d+OVuLm1ugPyOlMprqPRnQ7QktBgn44F3H8l7TeTH4ffHJ7nUsd4QVJfetWW7/VZ3s+4g7FoAZUA==", + "license": "MIT" + }, + "node_modules/iconv-corefoundation": { + "version": "1.1.7", + "resolved": "https://registry.npmjs.org/iconv-corefoundation/-/iconv-corefoundation-1.1.7.tgz", + "integrity": "sha512-T10qvkw0zz4wnm560lOEg0PovVqUXuOFhhHAkixw8/sycy7TJt7v/RrkEKEQnAw2viPSJu6iAkErxnzR0g8PpQ==", + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "dependencies": { + "cli-truncate": "^2.1.0", + "node-addon-api": "^1.6.3" + }, + "engines": { + "node": "^8.11.2 || >=10" + } + }, + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "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==", + "license": "MIT" + }, + "node_modules/immutable": { + "version": "5.1.9", + "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.1.9.tgz", + "integrity": "sha512-m8nVez3rwrgmWxtLMt1ZYXB2Lv7OKYn/disyxAlSDYAlKSlFoPPfIAmAM/M5xqL4m4C/wAPw7S2/CNaUii1Hxg==", + "dev": true, + "license": "MIT" + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-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/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/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/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, + "node_modules/inline-style-prefixer": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/inline-style-prefixer/-/inline-style-prefixer-7.0.1.tgz", + "integrity": "sha512-lhYo5qNTQp3EvSSp3sRvXMbVQTLrvGV6DycRMJ5dm2BLMiJ30wpXKdDdgX+GmJZ5uQMucwRKHamXSst3Sj/Giw==", + "license": "MIT", + "dependencies": { + "css-in-js-utils": "^3.1.0" + } + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/intersection-observer": { + "version": "0.12.2", + "resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.2.tgz", + "integrity": "sha512-7m1vEcPCxXYI8HqnL8CKI6siDyD+eIWSwgB3DZA+ZTogxk9I4CDnj4wilt9x/+/QbHI4YG5YZNmC6458/e9Ktg==", + "deprecated": "The Intersection Observer polyfill is no longer needed and can safely be removed. Intersection Observer has been Baseline since 2019.", + "license": "Apache-2.0" + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "license": "MIT" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-ci": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/is-ci/-/is-ci-3.0.1.tgz", + "integrity": "sha512-ZYvCgrefwqoQ6yTyYUbQu64HsITZ3NfKX1lzaEYdkTDcfKzzCI/wthRRYKkdjHKFVgNiXKAKm65Zo1pk2as/QQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ci-info": "^3.2.0" + }, + "bin": { + "is-ci": "bin.js" + } + }, + "node_modules/is-core-module": { + "version": "2.16.2", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz", + "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-document.all": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-document.all/-/is-document.all-1.0.0.tgz", + "integrity": "sha512-+XSoyS05OdBbhFuELhgTCpFNHkpBOJqtsZfUFFpe5QTw+9Sjbh8zitxhQkYAo6wV7e1Vb8cAPvpCk9jGam/82g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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": "sha512-xFuJpne9oFz5qDaodwmmG08e3CawH/2ZV8Qqza1Ko7Sk8POWbkRdwIoAWVhqvq0XeUzANEhKo2n0IXUGBm7A/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/isbinaryfile": { + "version": "4.0.10", + "resolved": "https://registry.npmjs.org/isbinaryfile/-/isbinaryfile-4.0.10.tgz", + "integrity": "sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/gjtorikian/" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "dev": true, + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, + "node_modules/js-cookie": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.8.tgz", + "integrity": "sha512-yeJd4aNAdYZQjaon2bpD/Gb0B/omw7HQOsynXXcOiWVCacbBcPlgn8S/d1X6blFSaHao7ozqtW7NZW19xpCtIw==", + "license": "MIT" + }, + "node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "license": "MIT" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/json-schema-typed": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/json-schema-typed/-/json-schema-typed-7.0.3.tgz", + "integrity": "sha512-7DE8mpG+/fVw+dTpjbxnx47TaMnDfOI1jwft9g1VybltZCduyRQPJPvc+zzKY9WPHxhPWczyFuYa6I8Mw4iU5A==", + "license": "BSD-2-Clause" + }, + "node_modules/json-stable-stringify": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz", + "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "isarray": "^2.0.5", + "jsonify": "^0.0.1", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", + "license": "ISC", + "optional": true + }, + "node_modules/json2mq": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/json2mq/-/json2mq-0.2.0.tgz", + "integrity": "sha512-SzoRg7ux5DWTII9J2qkrZrqV1gt+rTaoufMxEzXbS26Uid0NwaJd123HcoB80TgubEppxxIGdNxCx50fEoEWQA==", + "license": "MIT", + "dependencies": { + "string-convert": "^0.2.0" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz", + "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==", + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonify": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", + "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", + "dev": true, + "license": "Public Domain", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==", + "dev": true, + "engines": [ + "node >= 0.2.0" + ], + "license": "MIT" + }, + "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==", + "dev": true, + "license": "(MIT OR Apache-2.0)", + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/klaw-sync": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz", + "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11" + } + }, + "node_modules/koffi": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/koffi/-/koffi-2.8.0.tgz", + "integrity": "sha512-EXhiH9Ya4f+o4+24+uV4vFAMyPEskARVUaY8VHbIYWqkQVPTDyYJCBNfxp0Kxw6WdhaMwXeR8xIUyz8R2H8Rew==", + "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/lazy-val": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/lazy-val/-/lazy-val-1.0.5.tgz", + "integrity": "sha512-0/BnGCCfyUMkBpeDgWihanIAF9JmZhHBgUhEqzvf+adhNGLoP6TaiI5oF8oyb3I45P+PcnrqihSf01M0l0G5+Q==", + "license": "MIT" + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lie": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/lie/-/lie-3.1.1.tgz", + "integrity": "sha512-RiNhHysUjhrDQntfYSfY4MU24coXXdEOgw9WGcKHNeEwffDYbF//u87M1EWaMGzuFoSbqW0C9C6lEEhDOAswfw==", + "license": "MIT", + "dependencies": { + "immediate": "~3.0.5" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lint-staged": { + "version": "13.3.0", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-13.3.0.tgz", + "integrity": "sha512-mPRtrYnipYYv1FEE134ufbWpeggNTo+O/UPzngoaKzbzHAthvR55am+8GfHTnqNRQVRRrYQLGW9ZyUoD7DsBHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "5.3.0", + "commander": "11.0.0", + "debug": "4.3.4", + "execa": "7.2.0", + "lilconfig": "2.1.0", + "listr2": "6.6.1", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.1" + }, + "bin": { + "lint-staged": "bin/lint-staged.js" + }, + "engines": { + "node": "^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://opencollective.com/lint-staged" + } + }, + "node_modules/lint-staged/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/commander": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.0.0.tgz", + "integrity": "sha512-9HMlXtt/BNoYr8ooyjjNRdIilOTkVJXB+GhxMTtOKwk0R4j4lS4NpjuqmRxroBfnfTSHQIHQB7wryHhXarNjmQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + } + }, + "node_modules/lint-staged/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, + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/lint-staged/node_modules/execa": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-7.2.0.tgz", + "integrity": "sha512-UduyVP7TLB5IcAQl+OzLyLcS/l32W/GLg+AhHJ+ow40FOk2U3SAllPwR44v4vmdFwIWqpdwxxpQbF1n5ta9seA==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.1", + "human-signals": "^4.3.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^3.0.7", + "strip-final-newline": "^3.0.0" + }, + "engines": { + "node": "^14.18.0 || ^16.14.0 || >=18.0.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/lint-staged/node_modules/human-signals": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-4.3.1.tgz", + "integrity": "sha512-nZXjEF2nbo7lIw3mgYjItAfgQXog3OjJogSbKa2CQIIvSGWcKgeJnQlNXip6NglNzYH45nSRiEVimMvYL8DDqQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=14.18.0" + } + }, + "node_modules/lint-staged/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/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": { + "braces": "^3.0.2", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/lint-staged/node_modules/mimic-fn": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/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/lint-staged/node_modules/npm-run-path": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/onetime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lint-staged/node_modules/strip-final-newline": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2": { + "version": "6.6.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-6.6.1.tgz", + "integrity": "sha512-+rAXGHh0fkEWdXBmX+L6mmfmXmXvDGEKzkjxO+8mP3+nI/r/CWznVBvsibXdxda9Zz0OW2e2ikphN3OwCT/jSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cli-truncate": "^3.1.0", + "colorette": "^2.0.20", + "eventemitter3": "^5.0.1", + "log-update": "^5.0.1", + "rfdc": "^1.3.0", + "wrap-ansi": "^8.1.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "peerDependencies": { + "enquirer": ">= 2.3.0 < 3" + }, + "peerDependenciesMeta": { + "enquirer": { + "optional": true + } + } + }, + "node_modules/listr2/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/listr2/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/listr2/node_modules/cli-truncate": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-3.1.0.tgz", + "integrity": "sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "slice-ansi": "^5.0.0", + "string-width": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/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, + "license": "MIT" + }, + "node_modules/listr2/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/listr2/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/listr2/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, + "license": "MIT", + "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/listr2/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/livekit-client": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/livekit-client/-/livekit-client-2.7.0.tgz", + "integrity": "sha512-4vjfSReFNAUD+2oLUz9qFRWztJaI/+AexpOmCgizNsPYpvvqgAvEGxapnhuAug9uP7JVYaKPXaTCq90MWZoDHg==", + "license": "Apache-2.0", + "dependencies": { + "@livekit/mutex": "1.0.0", + "@livekit/protocol": "1.24.0", + "events": "^3.3.0", + "loglevel": "^1.8.0", + "sdp-transform": "^2.14.1", + "ts-debounce": "^4.0.0", + "tslib": "2.7.0", + "typed-emitter": "^2.1.0", + "webrtc-adapter": "^9.0.0" + } + }, + "node_modules/livekit-client/node_modules/tslib": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.7.0.tgz", + "integrity": "sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==", + "license": "0BSD" + }, + "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==", + "license": "Apache-2.0", + "dependencies": { + "lie": "3.1.1" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "license": "MIT" + }, + "node_modules/lodash-es": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", + "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", + "license": "MIT" + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "license": "MIT" + }, + "node_modules/lodash.escaperegexp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.escaperegexp/-/lodash.escaperegexp-4.1.2.tgz", + "integrity": "sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==", + "license": "MIT" + }, + "node_modules/lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==", + "deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead.", + "license": "MIT" + }, + "node_modules/lodash.isfunction": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz", + "integrity": "sha512-AirXNj15uRIMMPihnkInB4i3NHeb4iBtNg9WRWuK2o31S+ePwwNmDPaTL3o7dTJ+VXNZim7rFs4rxN4YU1oUJw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.kebabcase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz", + "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.mergewith": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", + "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.snakecase": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz", + "integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.startcase": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.startcase/-/lodash.startcase-4.4.0.tgz", + "integrity": "sha512-+WKqsK294HMSc2jEbNgpHpd0JfIBhp7rEV4aqXWqFr6AlXov+SlcgB1Fv01y2kGe3Gc8nMW7VA0SrGuSkRfIEg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.upperfirst": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/lodash.upperfirst/-/lodash.upperfirst-4.3.1.tgz", + "integrity": "sha512-sReKOYJIJf74dhJONhU4e0/shzi1trVbSWDOhKYE5XV2O+H7Sb2Dihwuc7xWxVl+DgFPyTqIN3zMfT9cq5iWDg==", + "dev": true, + "license": "MIT" + }, + "node_modules/log-update": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-5.0.1.tgz", + "integrity": "sha512-5UtUDQ/6edw4ofyljDNcOVJQ4c7OjDro4h3y8e1GQL5iYElYclVHJ3zeWchylvMaKnDbDilC8irOVyexnA/Slw==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^5.0.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^5.0.0", + "strip-ansi": "^7.0.1", + "wrap-ansi": "^8.0.1" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/log-update/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/log-update/node_modules/is-fullwidth-code-point": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", + "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-update/node_modules/slice-ansi": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", + "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.0.0", + "is-fullwidth-code-point": "^4.0.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" + } + }, + "node_modules/log-update/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/loglevel": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", + "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6.0" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/loglevel" + } + }, + "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==", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.30.21", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", + "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true, + "license": "ISC" + }, + "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" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/marked": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", + "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/match-sorter": { + "version": "6.3.4", + "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.4.tgz", + "integrity": "sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.23.8", + "remove-accents": "0.5.0" + } + }, + "node_modules/matcher": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", + "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "license": "MIT", + "optional": true, + "dependencies": { + "escape-string-regexp": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/md5": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz", + "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==", + "license": "BSD-3-Clause", + "dependencies": { + "charenc": "0.0.2", + "crypt": "0.0.2", + "is-buffer": "~1.1.6" + } + }, + "node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", + "license": "CC0-1.0" + }, + "node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "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.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/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==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/microseconds": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", + "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==", + "license": "MIT" + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/mimic-response": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", + "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/minipass": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", + "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=8" + } + }, + "node_modules/minizlib": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", + "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "minipass": "^3.0.0", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/minizlib/node_modules/minipass": { + "version": "3.3.6", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", + "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "ISC" + }, + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" + }, + "node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, + "node_modules/nano-css": { + "version": "5.6.2", + "resolved": "https://registry.npmjs.org/nano-css/-/nano-css-5.6.2.tgz", + "integrity": "sha512-+6bHaC8dSDGALM1HJjOHVXpuastdu2xFoZlC77Jh4cg+33Zcgm+Gxd+1xsnpZK14eyHObSp82+ll5y3SX75liw==", + "license": "Unlicense", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15", + "css-tree": "^1.1.2", + "csstype": "^3.1.2", + "fastest-stable-stringify": "^2.0.2", + "inline-style-prefixer": "^7.0.1", + "rtl-css-js": "^1.16.1", + "stacktrace-js": "^2.0.2", + "stylis": "^4.3.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/nano-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", + "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", + "license": "ISC", + "dependencies": { + "big-integer": "^1.6.16" + } + }, + "node_modules/nanoid": { + "version": "3.3.18", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.18.tgz", + "integrity": "sha512-DTg4MJbGMWkfi6VZFdNt2/caMbQy4Ou+Op/hJQvGEWcnVfoA1QA+xzRKAzw9jD6+GVOOeYr/mIcuDSdug6F6+w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true, + "license": "MIT" + }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==", + "license": "ISC" + }, + "node_modules/node-addon-api": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", + "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/node-exports-info": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/node-exports-info/-/node-exports-info-1.6.2.tgz", + "integrity": "sha512-kXs9Go0cah0qHVV2v389IXQLdLCeE1xfFtjOAF+iobu0OIoG1pje8At2vMHyaPMiPMnG/LWP50twML21eMcAag==", + "dev": true, + "license": "MIT", + "dependencies": { + "array.prototype.flatmap": "^1.3.3", + "es-errors": "^1.3.0", + "object.entries": "^1.1.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/node-exports-info/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/node-releases": { + "version": "2.0.53", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.53.tgz", + "integrity": "sha512-D9UOmYG3UH1V+ENW56t5QXBwJw1YEY18ruVeus89Rw+SyIgjPkCO84bRzO3uNIYosJbNwiabWVn48o3uJLjxFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/node-screenshots": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-screenshots/-/node-screenshots-0.2.8.tgz", + "integrity": "sha512-7O2ab89hkUgiXkrYj9iYCbJjY1iFJqIyZt0vuVtHFKlnajeFoyW+hur4CPxwwrnCUK0ahr0WLWQ5A6rCzF8rWQ==", + "license": "Apache-2.0", + "engines": { + "node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0" + }, + "optionalDependencies": { + "node-screenshots-darwin-arm64": "0.2.8", + "node-screenshots-darwin-x64": "0.2.8", + "node-screenshots-linux-arm64-gnu": "0.2.8", + "node-screenshots-linux-loong64-gnu": "0.2.8", + "node-screenshots-linux-x64-gnu": "0.2.8", + "node-screenshots-linux-x64-musl": "0.2.8", + "node-screenshots-win32-arm64-msvc": "0.2.8", + "node-screenshots-win32-ia32-msvc": "0.2.8", + "node-screenshots-win32-x64-msvc": "0.2.8" + } + }, + "node_modules/node-screenshots-darwin-arm64": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-screenshots-darwin-arm64/-/node-screenshots-darwin-arm64-0.2.8.tgz", + "integrity": "sha512-CEJE47gG2ceTc1fQRE3T/8lBwCGFJ+0iJiP+CQgCUAll4kKd32DQ7lCANqUseo96/xi6HuDOlrjLkAp7x2TzFw==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0" + } + }, + "node_modules/node-screenshots-darwin-x64": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-screenshots-darwin-x64/-/node-screenshots-darwin-x64-0.2.8.tgz", + "integrity": "sha512-3WIw4QaEP3pIUtSYh2NThwmzQl00H1bTPwPS7sYRLihAzB3NA/FOnIqRmvtadI0KEnnRGX4apdZgIhfXtgbNZA==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0" + } + }, + "node_modules/node-screenshots-linux-arm64-gnu": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-screenshots-linux-arm64-gnu/-/node-screenshots-linux-arm64-gnu-0.2.8.tgz", + "integrity": "sha512-aXJKtekSzQLJX6hh/VT5gilyloiN3DE4oE5xu9z7nLcTPyfC089dqVoERXJxnT+aqSQzx0KkI2te8BZNkjaMtQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0" + } + }, + "node_modules/node-screenshots-linux-loong64-gnu": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-screenshots-linux-loong64-gnu/-/node-screenshots-linux-loong64-gnu-0.2.8.tgz", + "integrity": "sha512-+982Yn7L7XID/FhYR6W6S2IVTLiueOBcHs/BP1Te5W6MtwlIIRg593zFh5HPQp7G+IaHqEXQzQj6D7kjJhXzsQ==", + "cpu": [ + "loong64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0" + } + }, + "node_modules/node-screenshots-linux-x64-gnu": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-screenshots-linux-x64-gnu/-/node-screenshots-linux-x64-gnu-0.2.8.tgz", + "integrity": "sha512-xF0hLfPMm9NEF4WtiQnbCyCUxU15M25lFkBzK4WS1CGOcxM7e30tvvwyYfmrMp3OtW/hESQFtiTb4cjKcOdaSA==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0" + } + }, + "node_modules/node-screenshots-linux-x64-musl": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-screenshots-linux-x64-musl/-/node-screenshots-linux-x64-musl-0.2.8.tgz", + "integrity": "sha512-mu/sVwDMt2yQM5ql2rtyQm+mq6Im2ycQLzQxXFXVJOB+k5A+Hk9h65J+G+Iy3rn1uNrYVDjgUQGvIkgpkIonCg==", + "cpu": [ + "x64" + ], + "libc": [ + "musl" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0" + } + }, + "node_modules/node-screenshots-win32-arm64-msvc": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-screenshots-win32-arm64-msvc/-/node-screenshots-win32-arm64-msvc-0.2.8.tgz", + "integrity": "sha512-g7nnuoJO2yjO8Ovr+Uz9e+LYJMlYc5eqoGPQq7U7NK1LVc2DpyCJ18VT8WdP2f098lfHvE12D3X7Es8NLFjiPg==", + "cpu": [ + "arm64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0" + } + }, + "node_modules/node-screenshots-win32-ia32-msvc": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-screenshots-win32-ia32-msvc/-/node-screenshots-win32-ia32-msvc-0.2.8.tgz", + "integrity": "sha512-Qsh4Ggs7MzO2XuDPFMRcRxRuiUGxxtHEFuqAfLFL1DiOfBIhLpukZ8JUHlEBdzjPxMFFRJw/4nOm0tnyHP/fiQ==", + "cpu": [ + "ia32" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0" + } + }, + "node_modules/node-screenshots-win32-x64-msvc": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/node-screenshots-win32-x64-msvc/-/node-screenshots-win32-x64-msvc-0.2.8.tgz", + "integrity": "sha512-DdFORB74FghM1L6UtE1TltIR2H0CCCmfQEa8gp2CTSdtBr2b0TKL7ZlbEV6x/wVKRFT59w7Kd6BULdeMmp0X2w==", + "cpu": [ + "x64" + ], + "license": "Apache-2.0", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.22.0 < 13 || >= 14.17.0 < 15 || >= 15.12.0 < 16 || >= 16.0.0" + } + }, + "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", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/notbundle": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/notbundle/-/notbundle-0.4.0.tgz", + "integrity": "sha512-fstkCyAyt5nqHch1GESWqkW9i/D2p80SacBEAoPNoRS0U6qBT6ZSUp2BayS+dbEWTHqheSzwxQwEEK/jpPObHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^3.5.3", + "fast-glob": "^3.2.12" + }, + "peerDependencies": { + "@swc/core": "*" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + } + } + }, + "node_modules/notbundle/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/notbundle/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" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/notbundle/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "devOptional": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz", + "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/oblivious-set": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", + "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==", + "license": "MIT" + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "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==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/own-keys": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.2.tgz", + "integrity": "sha512-19YVAg7T+WTrxggPukVq7DjTv6+PJ867TmhCvBsYwmbFCsZd344rq2Ld1p0wo8f8Qrrhgp82c6FJRqdXWtSEhg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/patch-package": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz", + "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@yarnpkg/lockfile": "^1.1.0", + "chalk": "^4.1.2", + "ci-info": "^3.7.0", + "cross-spawn": "^7.0.3", + "find-yarn-workspace-root": "^2.0.0", + "fs-extra": "^10.0.0", + "json-stable-stringify": "^1.0.2", + "klaw-sync": "^6.0.0", + "minimist": "^1.2.6", + "open": "^7.4.2", + "semver": "^7.5.3", + "slash": "^2.0.0", + "tmp": "^0.2.4", + "yaml": "^2.2.2" + }, + "bin": { + "patch-package": "index.js" + }, + "engines": { + "node": ">=14", + "npm": ">5" + } + }, + "node_modules/patch-package/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/patch-package/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/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true, + "license": "MIT" + }, + "node_modules/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/pend": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", + "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", + "license": "MIT" + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pidtree": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz", + "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==", + "dev": true, + "license": "MIT", + "bin": { + "pidtree": "bin/pidtree.js" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/pirates": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", + "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-up": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz", + "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==", + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/pkg-up/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==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/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==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-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==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-up/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==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/pkg-up/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/playwright": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.62.1.tgz", + "integrity": "sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.62.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=20" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.62.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.62.1.tgz", + "integrity": "sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=20" + } + }, + "node_modules/plist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/plist/-/plist-3.1.1.tgz", + "integrity": "sha512-ZIfcLJC+7E7FBFnDxm9MPmt7D+DidyQ26lewieO75AdhA2ayMtsJSES0iWzqJQbcVRSrTufQoy0DR94xHue0oA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xmldom/xmldom": "^0.9.10", + "base64-js": "^1.5.1", + "xmlbuilder": "^15.1.1" + }, + "engines": { + "node": ">=10.4.0" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/postcss": { + "version": "8.5.26", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.26.tgz", + "integrity": "sha512-u82N74LFzG8ca+dD8puPnplTXoGH4fTPpVGuIbt36G3qvNlkvfD0lEAZSxaly3KX8TS/L1A1gsCEmvKmBcVbkQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.17", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "license": "MIT", + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", + "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/postcss-nesting": { + "version": "12.1.5", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-12.1.5.tgz", + "integrity": "sha512-N1NgI1PDCiAGWPTYrwqm8wpjv0bgDmkYHH72pNsqTCv9CObxjxftdYu6AKtGN+pnJa7FQjMm3v4sp8QJbFsYdQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "dependencies": { + "@csstools/selector-resolve-nested": "^1.1.0", + "@csstools/selector-specificity": "^3.1.1", + "postcss-selector-parser": "^6.1.0" + }, + "engines": { + "node": "^14 || ^16 || >=18" + }, + "peerDependencies": { + "postcss": "^8.4" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.4.tgz", + "integrity": "sha512-bIoJLOmjCO1S9XdY/DcnR5hJxvrDir1PbGChrzXG3vw0/FOliy/fA3dmdhQ441kah4gKv+TwckGzex6wNS5cnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.1.tgz", + "integrity": "sha512-SxToR7P8Y2lWmv/kTzVLC1t/GDI2WGjMwNhLLE9qtH8Q13C+aEmuRlzDst4Up4s0Wc8sF2M+J57iB3cMLqftfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/prettier-plugin-tailwindcss": { + "version": "0.2.8", + "resolved": "https://registry.npmjs.org/prettier-plugin-tailwindcss/-/prettier-plugin-tailwindcss-0.2.8.tgz", + "integrity": "sha512-KgPcEnJeIijlMjsA6WwYgRs5rh3/q76oInqtMXBA/EMcamrcYJpyhtRhyX1ayT9hnHlHTuO8sIifHF10WuSDKg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.17.0" + }, + "peerDependencies": { + "@ianvs/prettier-plugin-sort-imports": "*", + "@prettier/plugin-pug": "*", + "@shopify/prettier-plugin-liquid": "*", + "@shufo/prettier-plugin-blade": "*", + "@trivago/prettier-plugin-sort-imports": "*", + "prettier": ">=2.2.0", + "prettier-plugin-astro": "*", + "prettier-plugin-css-order": "*", + "prettier-plugin-import-sort": "*", + "prettier-plugin-jsdoc": "*", + "prettier-plugin-organize-attributes": "*", + "prettier-plugin-organize-imports": "*", + "prettier-plugin-style-order": "*", + "prettier-plugin-svelte": "*", + "prettier-plugin-twig-melody": "*" + }, + "peerDependenciesMeta": { + "@ianvs/prettier-plugin-sort-imports": { + "optional": true + }, + "@prettier/plugin-pug": { + "optional": true + }, + "@shopify/prettier-plugin-liquid": { + "optional": true + }, + "@shufo/prettier-plugin-blade": { + "optional": true + }, + "@trivago/prettier-plugin-sort-imports": { + "optional": true + }, + "prettier-plugin-astro": { + "optional": true + }, + "prettier-plugin-css-order": { + "optional": true + }, + "prettier-plugin-import-sort": { + "optional": true + }, + "prettier-plugin-jsdoc": { + "optional": true + }, + "prettier-plugin-organize-attributes": { + "optional": true + }, + "prettier-plugin-organize-imports": { + "optional": true + }, + "prettier-plugin-style-order": { + "optional": true + }, + "prettier-plugin-svelte": { + "optional": true + }, + "prettier-plugin-twig-melody": { + "optional": true + } + } + }, + "node_modules/progress": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", + "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/proxy-from-env": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz", + "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/pump": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz", + "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.1.0", + "once": "^1.3.1" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/qrcode.react": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/qrcode.react/-/qrcode.react-3.2.0.tgz", + "integrity": "sha512-YietHHltOHA4+l5na1srdaMx4sVSOjV9tamHs+mwiLWAMr6QVACRUw1Neax5CptFILcNoITctJY0Ipyn5enQ8g==", + "license": "ISC", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/quick-lru": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", + "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/rc-cascader": { + "version": "3.18.1", + "resolved": "https://registry.npmjs.org/rc-cascader/-/rc-cascader-3.18.1.tgz", + "integrity": "sha512-M7Xr5Fs/E87ZGustfObtBYQjsvBCET0UX2JYXB2GmOP+2fsZgjaRGXK+CJBmmWXQ6o4OFinpBQBXG4wJOQ5MEg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.12.5", + "array-tree-filter": "^2.1.0", + "classnames": "^2.3.1", + "rc-select": "~14.9.0", + "rc-tree": "~5.7.0", + "rc-util": "^5.35.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-checkbox": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/rc-checkbox/-/rc-checkbox-3.1.0.tgz", + "integrity": "sha512-PAwpJFnBa3Ei+5pyqMMXdcKYKNBMS+TvSDiLdDnARnMJHC8ESxwPfm4Ao1gJiKtWLdmGfigascnCpwrHFgoOBQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.3.2", + "rc-util": "^5.25.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-collapse": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/rc-collapse/-/rc-collapse-3.7.3.tgz", + "integrity": "sha512-60FJcdTRn0X5sELF18TANwtVi7FtModq649H11mYF1jh83DniMoM4MqY627sEKRCTm4+WXfGDcB7hY5oW6xhyw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.3.4", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dialog": { + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/rc-dialog/-/rc-dialog-9.3.4.tgz", + "integrity": "sha512-975X3018GhR+EjZFbxA2Z57SX5rnu0G0/OxFgMMvZK4/hQWEm3MHaNvP4wXpxYDoJsp+xUvVW+GB9CMMCm81jA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.0.0-8", + "classnames": "^2.2.6", + "rc-motion": "^2.3.0", + "rc-util": "^5.21.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-drawer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/rc-drawer/-/rc-drawer-6.5.2.tgz", + "integrity": "sha512-QckxAnQNdhh4vtmKN0ZwDf3iakO83W9eZcSKWYYTDv4qcD2fHhRAZJJ/OE6v2ZlQ2kSqCJX5gYssF4HJFvsEPQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/portal": "^1.1.1", + "classnames": "^2.2.6", + "rc-motion": "^2.6.1", + "rc-util": "^5.36.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-dropdown": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-dropdown/-/rc-dropdown-4.1.0.tgz", + "integrity": "sha512-VZjMunpBdlVzYpEdJSaV7WM7O0jf8uyDjirxXLZRNZ+tAC+NzD3PXPEtliFwGzVwBBdCmGuSqiS9DWcOLxQ9tw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "@rc-component/trigger": "^1.7.0", + "classnames": "^2.2.6", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.11.0", + "react-dom": ">=16.11.0" + } + }, + "node_modules/rc-field-form": { + "version": "1.38.2", + "resolved": "https://registry.npmjs.org/rc-field-form/-/rc-field-form-1.38.2.tgz", + "integrity": "sha512-O83Oi1qPyEv31Sg+Jwvsj6pXc8uQI2BtIAkURr5lvEYHVggXJhdU/nynK8wY1gbw0qR48k731sN5ON4egRCROA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.0", + "async-validator": "^4.1.0", + "rc-util": "^5.32.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-image": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/rc-image/-/rc-image-7.3.2.tgz", + "integrity": "sha512-ICEF6SWv9YKhDXxy1vrXcmf0TVvEcQWIww5Yg+f+mn7e4oGX7FNP4+FExwMjNO5UHBEuWrigbGhlCgI6yZZ1jg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/portal": "^1.0.2", + "classnames": "^2.2.6", + "rc-dialog": "~9.3.4", + "rc-motion": "^2.6.2", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-input": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/rc-input/-/rc-input-1.2.1.tgz", + "integrity": "sha512-nQRmBvEFoGi+SNRDavccZ8ueyhFgmxkWqIt4aDyuNJgUZF12HJKIwDhAafUM7N+g7PyuW9FH3pf3zPHzdiCWbA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.18.1" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-input-number": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/rc-input-number/-/rc-input-number-8.1.0.tgz", + "integrity": "sha512-bdHgduOxuN0lrhzgPmoKbhRD4GLIzVcddVz972/JHPHr7oLwPX5xDb9w4bXhuMzyT2VzQy7nggRCfH3yAl09oA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/mini-decimal": "^1.0.1", + "classnames": "^2.2.5", + "rc-input": "~1.2.1", + "rc-util": "^5.28.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-mentions": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/rc-mentions/-/rc-mentions-2.8.0.tgz", + "integrity": "sha512-LBMkO6bSGhEvS1CvMK978qGN82tI+mzk7l/uTiQJH+UDiwpvq+pxK4DxU5b6Q1T5LW6bn2pSua9RaZKZrDoBOw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.22.5", + "@rc-component/trigger": "^1.5.0", + "classnames": "^2.2.6", + "rc-input": "~1.2.1", + "rc-menu": "~9.12.0", + "rc-textarea": "~1.4.0", + "rc-util": "^5.34.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-menu": { + "version": "9.12.4", + "resolved": "https://registry.npmjs.org/rc-menu/-/rc-menu-9.12.4.tgz", + "integrity": "sha512-t2NcvPLV1mFJzw4F21ojOoRVofK2rWhpKPx69q2raUsiHPDP6DDevsBILEYdsIegqBeSXoWs2bf6CueBKg3BFg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^1.17.0", + "classnames": "2.x", + "rc-motion": "^2.4.3", + "rc-overflow": "^1.3.1", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-motion": { + "version": "2.9.5", + "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.5.tgz", + "integrity": "sha512-w+XTUrfh7ArbYEd2582uDrEhmBHwK1ZENJiSJVb7uRxdE7qJSYjbO2eksRXmndqyKqKoYPc9ClpPh5242mV1vA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-util": "^5.44.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-notification": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rc-notification/-/rc-notification-5.2.0.tgz", + "integrity": "sha512-HwUSypEW4mfOpiakJ7dm6TAKf+3zuSR2xm0I0XMes493rtA3n4EVMvQyldrp23hUwCE3RFj8oncyU1E8iNC4ag==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.9.0", + "rc-util": "^5.20.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-overflow": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/rc-overflow/-/rc-overflow-1.5.0.tgz", + "integrity": "sha512-Lm/v9h0LymeUYJf0x39OveU52InkdRXqnn2aYXfWmo8WdOonIKB2kfau+GF0fWq6jPgtdO9yMqveGcK6aIhJmg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.37.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-pagination": { + "version": "3.6.1", + "resolved": "https://registry.npmjs.org/rc-pagination/-/rc-pagination-3.6.1.tgz", + "integrity": "sha512-R/sUnKKXx1Nm4kZfUKS3YKa7yEPF1ZkVB/AynQaHt+nMER7h9wPTfliDJFdYo+RM/nk2JD4Yc5QpUq8fIQHeug==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-util": "^5.32.2" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-picker": { + "version": "3.14.7", + "resolved": "https://registry.npmjs.org/rc-picker/-/rc-picker-3.14.7.tgz", + "integrity": "sha512-+craFcClAOwu4R7lSlaiTAZRY4cWPgtE0+yji9stQkQR28C7WGTrZcyiq5AD7xfhXNV+82QmoJ8Aqg3duDYF6A==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^1.5.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "date-fns": ">= 2.x", + "dayjs": ">= 1.x", + "luxon": ">= 3.x", + "moment": ">= 2.x", + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + }, + "peerDependenciesMeta": { + "date-fns": { + "optional": true + }, + "dayjs": { + "optional": true + }, + "luxon": { + "optional": true + }, + "moment": { + "optional": true + } + } + }, + "node_modules/rc-progress": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/rc-progress/-/rc-progress-3.5.1.tgz", + "integrity": "sha512-V6Amx6SbLRwPin/oD+k1vbPrO8+9Qf8zW1T8A7o83HdNafEVvAxPV5YsgtKFP+Ud5HghLj33zKOcEHrcrUGkfw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.6", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-rate": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/rc-rate/-/rc-rate-2.12.0.tgz", + "integrity": "sha512-g092v5iZCdVzbjdn28FzvWebK2IutoVoiTeqoLTj9WM7SjA/gOJIw5/JFZMRyJYYVe1jLAU2UhAfstIpCNRozg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.0.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-resize-observer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/rc-resize-observer/-/rc-resize-observer-1.4.3.tgz", + "integrity": "sha512-YZLjUbyIWox8E9i9C3Tm7ia+W7euPItNWSPX5sCcQTYbnwDb5uNpnLHQCG1f22oZWUhLw4Mv2tFmeWe68CDQRQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.7", + "classnames": "^2.2.1", + "rc-util": "^5.44.1", + "resize-observer-polyfill": "^1.5.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-segmented": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/rc-segmented/-/rc-segmented-2.2.2.tgz", + "integrity": "sha512-Mq52M96QdHMsNdE/042ibT5vkcGcD5jxKp7HgPC2SRofpia99P5fkfHy1pEaajLMF/kj0+2Lkq1UZRvqzo9mSA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.1", + "classnames": "^2.2.1", + "rc-motion": "^2.4.4", + "rc-util": "^5.17.0" + }, + "peerDependencies": { + "react": ">=16.0.0", + "react-dom": ">=16.0.0" + } + }, + "node_modules/rc-select": { + "version": "14.9.2", + "resolved": "https://registry.npmjs.org/rc-select/-/rc-select-14.9.2.tgz", + "integrity": "sha512-VQ15sRFgPURHb8ZcZNSDtb2rAw3+C9xlL0nDziwNHTEW1KvEpZ8y+0v5w24X/Bpl9b3cW1BOyW1F5UqSAq+7Dg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/trigger": "^1.5.0", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-overflow": "^1.3.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.2" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-slider": { + "version": "10.3.1", + "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-10.3.1.tgz", + "integrity": "sha512-XszsZLkbjcG9ogQy/zUC0n2kndoKUAnY/Vnk1Go5Gx+JJQBz0Tl15d5IfSiglwBUZPS9vsUJZkfCmkIZSqWbcA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.5", + "rc-util": "^5.27.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-steps": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/rc-steps/-/rc-steps-6.0.1.tgz", + "integrity": "sha512-lKHL+Sny0SeHkQKKDJlAjV5oZ8DwCdS2hFhAkIjuQt1/pB81M0cA0ErVFdHq9+jmPmFw1vJB2F5NBzFXLJxV+g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.16.7", + "classnames": "^2.2.3", + "rc-util": "^5.16.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-switch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/rc-switch/-/rc-switch-4.1.0.tgz", + "integrity": "sha512-TI8ufP2Az9oEbvyCeVE4+90PDSljGyuwix3fV58p7HV2o4wBnVToEyomJRVyTaZeqNPAp+vqeo4Wnj5u0ZZQBg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.21.0", + "classnames": "^2.2.1", + "rc-util": "^5.30.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-table": { + "version": "7.34.4", + "resolved": "https://registry.npmjs.org/rc-table/-/rc-table-7.34.4.tgz", + "integrity": "sha512-os+i88Y2AO/6dNkOgJkKSHgXYaZZGnuOEEe+nyaq5IRgvAQNhLysUjXt2objtBeFDEZR8TqXrajwBNRUwunmdw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "@rc-component/context": "^1.4.0", + "classnames": "^2.2.5", + "rc-resize-observer": "^1.1.0", + "rc-util": "^5.36.0", + "rc-virtual-list": "^3.11.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tabs": { + "version": "12.12.1", + "resolved": "https://registry.npmjs.org/rc-tabs/-/rc-tabs-12.12.1.tgz", + "integrity": "sha512-e10VBjEkECdPl4XZSs9to81SE+mgclBTM7J8/LMsFqmJoi05Tci91bRnmeeDtrcOCx2PuZdJv57XUlC4d8PEIw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "classnames": "2.x", + "rc-dropdown": "~4.1.0", + "rc-menu": "~9.12.0", + "rc-motion": "^2.6.2", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.34.1" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-textarea": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/rc-textarea/-/rc-textarea-1.4.0.tgz", + "integrity": "sha512-CiqK+uyoJlnfufbC0kwfHJpfElhQacuDSNyNQ/xGnA/QMaJLDbgmqRT8QmX0T0KD/ws/hy6qqRaGJSsrRR5uiQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "^2.2.1", + "rc-input": "~1.2.1", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.27.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tooltip": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-6.1.3.tgz", + "integrity": "sha512-HMSbSs5oieZ7XddtINUddBLSVgsnlaSb3bZrzzGWjXa7/B7nNedmsuz72s7EWFEro9mNa7RyF3gOXKYqvJiTcQ==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.11.2", + "@rc-component/trigger": "^1.18.0", + "classnames": "^2.3.1" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-tree": { + "version": "5.7.12", + "resolved": "https://registry.npmjs.org/rc-tree/-/rc-tree-5.7.12.tgz", + "integrity": "sha512-LXA5nY2hG5koIAlHW5sgXgLpOMz+bFRbnZZ+cCg0tQs4Wv1AmY7EDi1SK7iFXhslYockbqUerQan82jljoaItg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-motion": "^2.0.1", + "rc-util": "^5.16.1", + "rc-virtual-list": "^3.5.1" + }, + "engines": { + "node": ">=10.x" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-tree-select": { + "version": "5.13.0", + "resolved": "https://registry.npmjs.org/rc-tree-select/-/rc-tree-select-5.13.0.tgz", + "integrity": "sha512-g01JU9EdE7j/9KfDKtmvFqJ7ZDNIYDzkpmAXllbTBFoRNhWJBjW1x/dCZLVG+IdZeIz8SKJkgZzCf1CUZrzV/Q==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.10.1", + "classnames": "2.x", + "rc-select": "~14.9.0", + "rc-tree": "~5.7.0", + "rc-util": "^5.16.1" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/rc-upload": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/rc-upload/-/rc-upload-4.3.6.tgz", + "integrity": "sha512-Bt7ESeG5tT3IY82fZcP+s0tQU2xmo1W6P3S8NboUUliquJLQYLkUcsaExi3IlBVr43GQMCjo30RA2o0i70+NjA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "classnames": "^2.2.5", + "rc-util": "^5.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util": { + "version": "5.44.4", + "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.44.4.tgz", + "integrity": "sha512-resueRJzmHG9Q6rI/DfK6Kdv9/Lfls05vzMs1Sk3M2P+3cJa+MakaZyWY8IPfehVuhPJFKrIY1IK4GqbiaiY5w==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.18.3", + "react-is": "^18.2.0" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/rc-util/node_modules/react-is": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", + "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", + "license": "MIT" + }, + "node_modules/rc-virtual-list": { + "version": "3.19.2", + "resolved": "https://registry.npmjs.org/rc-virtual-list/-/rc-virtual-list-3.19.2.tgz", + "integrity": "sha512-Ys6NcjwGkuwkeaWBDqfI3xWuZ7rDiQXlH1o2zLfFzATfEgXcqpk8CkgMfbJD81McqjcJVez25a3kPxCR807evA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.0", + "classnames": "^2.2.6", + "rc-resize-observer": "^1.0.0", + "rc-util": "^5.36.0" + }, + "engines": { + "node": ">=8.x" + }, + "peerDependencies": { + "react": ">=16.9.0", + "react-dom": ">=16.9.0" + } + }, + "node_modules/react": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", + "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", + "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "scheduler": "^0.23.2" + }, + "peerDependencies": { + "react": "^18.3.1" + } + }, + "node_modules/react-draggable": { + "version": "4.7.1", + "resolved": "https://registry.npmjs.org/react-draggable/-/react-draggable-4.7.1.tgz", + "integrity": "sha512-wa3tzfFnYt3yaZLuyU58fl1TNunfWfBekDgWhZA1+gb2jnp42wZ0ymuopR6M5kqDYmm4hKmzGlcKWjZf3Zb6RQ==", + "license": "MIT", + "dependencies": { + "clsx": "^2.1.1", + "prop-types": "^15.8.1" + }, + "peerDependencies": { + "react": ">= 16.3.0", + "react-dom": ">= 16.3.0" + } + }, + "node_modules/react-draggable/node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react-fast-compare": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz", + "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ==", + "license": "MIT" + }, + "node_modules/react-i18next": { + "version": "12.3.1", + "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz", + "integrity": "sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.20.6", + "html-parse-stringify": "^3.0.1" + }, + "peerDependencies": { + "i18next": ">= 19.0.0", + "react": ">= 16.8.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-image-file-resizer": { + "version": "0.4.8", + "resolved": "https://registry.npmjs.org/react-image-file-resizer/-/react-image-file-resizer-0.4.8.tgz", + "integrity": "sha512-Ue7CfKnSlsfJ//SKzxNMz8avDgDSpWQDOnTKOp/GNRFJv4dO9L5YGHNEnj40peWkXXAK2OK0eRIoXhOYpUzUTQ==", + "license": "MIT" + }, + "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==", + "license": "MIT" + }, + "node_modules/react-query": { + "version": "3.39.3", + "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", + "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.5.5", + "broadcast-channel": "^3.4.1", + "match-sorter": "^6.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependenciesMeta": { + "react-dom": { + "optional": true + }, + "react-native": { + "optional": true + } + } + }, + "node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-resizable-panels": { + "version": "2.1.9", + "resolved": "https://registry.npmjs.org/react-resizable-panels/-/react-resizable-panels-2.1.9.tgz", + "integrity": "sha512-z77+X08YDIrgAes4jl8xhnUu1LNIRp4+E7cv4xHmLOxxUPO/ML7PSrE813b90vj7xvQ1lcf7g2uA9GeMZonjhQ==", + "license": "MIT", + "peerDependencies": { + "react": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc", + "react-dom": "^16.14.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 || ^19.0.0-rc" + } + }, + "node_modules/react-router": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.4.tgz", + "integrity": "sha512-SVUsDe+DybHM/WmYKIVYhZh1o5Dcuf16yM6WjG02Q9XVFMZIJyHYhwrr6bFBXZkVP6z69kNkMyBCujt8FaFLJA==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8" + } + }, + "node_modules/react-router-dom": { + "version": "6.30.4", + "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.4.tgz", + "integrity": "sha512-q4HvNl+mmDdkS0g+MqiBZNteQJCuimWoOyHMy4T/RQLAn9Z29+E91QXRaxOujeMl2HTzRSS0KFPd7lxX3PjV0Q==", + "license": "MIT", + "dependencies": { + "@remix-run/router": "1.23.3", + "react-router": "6.30.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-screenshots": { + "version": "0.5.22", + "resolved": "https://registry.npmjs.org/react-screenshots/-/react-screenshots-0.5.22.tgz", + "integrity": "sha512-aooIlb1k6161BTqhhyADlMrlF0n1UdudjuhyvXaCQfwURXZNuUerMxFuOfwNCgSbPAHlxdHCWtYQ6iQT+RaF+w==", + "license": "MIT", + "peerDependencies": { + "react": ">=16.8", + "react-dom": ">=16.8" + } + }, + "node_modules/react-universal-interface": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/react-universal-interface/-/react-universal-interface-0.6.2.tgz", + "integrity": "sha512-dg8yXdcQmvgR13RIlZbTRQOoUrDciFVoSBZILwjE2LFISxZZ8loVJKAkuzswl5js8BHda79bIb2b84ehU8IjXw==", + "peerDependencies": { + "react": "*", + "tslib": "*" + } + }, + "node_modules/react-use": { + "version": "17.6.1", + "resolved": "https://registry.npmjs.org/react-use/-/react-use-17.6.1.tgz", + "integrity": "sha512-uibb3pgzV4LFsYPHyXYGu7dD2+pyk/ZJlPH+AizBR3zolqPWyCleKcWWbUQaKSKfydwgnQ3ymGm1Ab3/saGHCA==", + "license": "Unlicense", + "dependencies": { + "@types/js-cookie": "^3.0.0", + "@xobotyi/scrollbar-width": "^1.9.5", + "copy-to-clipboard": "^3.3.1", + "fast-deep-equal": "^3.1.3", + "fast-shallow-equal": "^1.0.0", + "js-cookie": "^3.0.0", + "nano-css": "^5.6.2", + "react-universal-interface": "^0.6.2", + "resize-observer-polyfill": "^1.5.1", + "screenfull": "^5.1.0", + "set-harmonic-interval": "^1.0.1", + "throttle-debounce": "^3.0.1", + "ts-easing": "^0.2.0", + "tslib": "^2.1.0" + }, + "peerDependencies": { + "react": "*", + "react-dom": "*" + } + }, + "node_modules/react-use/node_modules/throttle-debounce": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-3.0.1.tgz", + "integrity": "sha512-dTEWWNu6JmeVXY0ZYoPuH5cRIwc0MeGbJwah9KUNYSJwommQpCzTySTpEe8Gs1J23aeWEuAobe4Ag7EHVt/LOg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/react-virtuoso": { + "version": "4.3.8", + "resolved": "https://registry.npmjs.org/react-virtuoso/-/react-virtuoso-4.3.8.tgz", + "integrity": "sha512-hoZj8Dl1R9fYqtUwA5LjCii1djO4ZNtoYkYsR52ZjdJzdXh2hec1IQ2O+1MZNjLTb4v8ff3hbt34StiHTVDdlg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "react": ">=16 || >=17 || >= 18", + "react-dom": ">=16 || >=17 || >= 18" + } + }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-config-file": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/read-config-file/-/read-config-file-6.2.0.tgz", + "integrity": "sha512-gx7Pgr5I56JtYz+WuqEbQHj/xWo+5Vwua2jhb1VwM4Wid5PqYmZ4i00ZB0YEGIfkVBsCv9UrjgyqCiQfS/Oosg==", + "dev": true, + "license": "MIT", + "dependencies": { + "dotenv": "^9.0.2", + "dotenv-expand": "^5.1.0", + "js-yaml": "^4.1.0", + "json5": "^2.2.0", + "lazy-val": "^1.0.4" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "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/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": "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/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-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" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-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" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "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==", + "dev": true, + "license": "ISC" + }, + "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==", + "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/read-pkg/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "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 OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/readdirp": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-5.1.1.tgz", + "integrity": "sha512-Kko+Y5XQ6fM+Ce3dq3m9YGxnacYZYl9cA1wZjaF3Vbry2L3i1qVg8+CAgNPsXRArPMUMCaOR7oa9Nqntc43JKA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 20.19.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "dev": true, + "license": "MIT" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.13.2", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.2.tgz", + "integrity": "sha512-NgRBy2Nx/bE+9F27nVHnqcN5HjyLmecqsqx2PJHu3/IEtADD4WuxuXIVExD5PoSDFVrl78dOonfcOe5O+5nbzQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/remove-accents": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", + "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==", + "license": "MIT" + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==", + "license": "MIT" + }, + "node_modules/resolve": { + "version": "1.22.12", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz", + "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-alpn": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", + "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", + "license": "MIT" + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "license": "MIT", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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": { + "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/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rfdc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/roarr": { + "version": "2.15.4", + "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", + "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", + "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" + } + }, + "node_modules/rollup": { + "version": "3.30.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.30.0.tgz", + "integrity": "sha512-kQvGasUgN+AlWGliFn2POSajRQEsULVYFGTvOZmK06d7vCD+YhZztt70kGk3qaeAXeWYL5eO7zx+rAubBc55eA==", + "dev": true, + "license": "MIT", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rtl-css-js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/rtl-css-js/-/rtl-css-js-1.16.1.tgz", + "integrity": "sha512-lRQgou1mu19e+Ya0LsTvKrVJ5TYUbqCVPAiImX3UfLTenarvPUl1QFdvu5Z3PYmHT9RCcwIfbjRQBntExyj3Zg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.1.2" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "license": "Apache-2.0", + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.4.tgz", + "integrity": "sha512-wtZlHyOje6OZTGqAoaDKxFkgRtkF9CnHAVnCHKfuj200wAgL+bSJhdsCD2l0Qx/2ekEXjPWcyKkfGb5CPboslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "get-intrinsic": "^1.3.0", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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" + } + ], + "license": "MIT" + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true, + "license": "MIT" + }, + "node_modules/sanitize-filename": { + "version": "1.6.4", + "resolved": "https://registry.npmjs.org/sanitize-filename/-/sanitize-filename-1.6.4.tgz", + "integrity": "sha512-9ZyI08PsvdQl2r/bBIGubpVdR3RR9sY6RDiWFPreA21C/EFlQhmgo20UZlNjZMMZNubusLhAQozkA0Od5J21Eg==", + "dev": true, + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/sass": { + "version": "1.102.0", + "resolved": "https://registry.npmjs.org/sass/-/sass-1.102.0.tgz", + "integrity": "sha512-NSOyTnaQF7rTAEOtI2fwb386vL+akyiQLBZu8Na7hXCb+umJy0GAqlcMIaqACZ6Z1VgTBS4K9PG6B3IdjHGJsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chokidar": "^5.0.0", + "immutable": "^5.1.5", + "source-map-js": ">=0.6.2 <2.0.0" + }, + "bin": { + "sass": "sass.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "optionalDependencies": { + "@parcel/watcher": "^2.4.1" + } + }, + "node_modules/sax": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.1.tgz", + "integrity": "sha512-42tBVwLWnaQvW5zc4HbZrTuWccECCZfBi92FDuwtqxasH+JbPB3/FOKb1m222K42R4WxuxzzMsTswfzgtSu64Q==", + "license": "BlueOak-1.0.0", + "engines": { + "node": ">=11.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/screenfull": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/screenfull/-/screenfull-5.2.0.tgz", + "integrity": "sha512-9BakfsO2aUQN2K9Fdbj87RJIEZ82Q9IGim7FqM5OsebfoFC6ZHXgDq/KvniuLTPdeM8wY2o6Dj3WQ7KeQCj3cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/scroll-into-view-if-needed": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/scroll-into-view-if-needed/-/scroll-into-view-if-needed-3.1.0.tgz", + "integrity": "sha512-49oNpRjWRvnU8NyGVmUaYG4jtTkNonFZI86MmGRDqBphEK2EXT9gdEUoQPZhuBM8yWHxCWbobltqYO5M4XrUvQ==", + "license": "MIT", + "dependencies": { + "compute-scroll-into-view": "^3.0.2" + } + }, + "node_modules/sdp": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/sdp/-/sdp-3.2.2.tgz", + "integrity": "sha512-xZocWwfyp4hkbN4hLWxMjmv2Q8aNa9MhmOZ7L9aCZPT+dZsgRr6wZRrSYE3HTdyk/2pZKPSgqI7ns7Een1xMSA==", + "license": "MIT" + }, + "node_modules/sdp-transform": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/sdp-transform/-/sdp-transform-2.15.0.tgz", + "integrity": "sha512-KrOH82c/W+GYQ0LHqtr3caRpM3ITglq3ljGUIb8LTki7ByacJZ9z+piSGiwZDsRyhQbYBOBJgr2k6X4BZXi3Kw==", + "license": "MIT", + "bin": { + "sdp-verify": "checker.js" + } + }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver-compare": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", + "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "license": "MIT", + "optional": true + }, + "node_modules/semver/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==", + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/semver/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "license": "ISC" + }, + "node_modules/serialize-error": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", + "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "license": "MIT", + "optional": true, + "dependencies": { + "type-fest": "^0.13.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serialize-error/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==", + "license": "(MIT OR CC0-1.0)", + "optional": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-harmonic-interval": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/set-harmonic-interval/-/set-harmonic-interval-1.0.1.tgz", + "integrity": "sha512-AhICkFV84tBP1aWqPwLZqFvAwqEoVA9kxNMniGEUvzOlm4vLmOFLiTT3UZ6bziJTy4bOVpzWGTfSCbmaayGx8g==", + "license": "Unlicense", + "engines": { + "node": ">=6.9" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/side-channel": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.1.tgz", + "integrity": "sha512-6x6dK6zJdpTzF4sQeNYxwtvBzf6Eg4GtlesS94HOvTudUeyK2WXAaIfmDgsyslYrRBeFIlsi54AYsFGUuhmvrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4", + "side-channel-list": "^1.0.1", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz", + "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/simple-update-notifier": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-1.1.0.tgz", + "integrity": "sha512-VpsrsJSUcJEseSbMHkrsrAVSdvVS5I96Qo1QAQ4FxQ9wXFcB+pjj7FB7/us9+GcgfW4ziHtYMc1J0PLczb55mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "~7.0.0" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", + "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/slash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", + "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", + "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "astral-regex": "^2.0.0", + "is-fullwidth-code-point": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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, + "license": "MIT", + "optional": true, + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz", + "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.23", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz", + "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==", + "dev": true, + "license": "CC0-1.0" + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "license": "ISC", + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "license": "BSD-3-Clause", + "optional": true + }, + "node_modules/stack-generator": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/stack-generator/-/stack-generator-2.0.10.tgz", + "integrity": "sha512-mwnua/hkqM6pF4k8SnmZ2zfETsRUpWXREfA/goT8SLCV4iOFa4bzOX2nDipWAZFPTjLvQB82f5yaodMVhK0yJQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/stacktrace-gps": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/stacktrace-gps/-/stacktrace-gps-3.1.2.tgz", + "integrity": "sha512-GcUgbO4Jsqqg6RxfyTHFiPxdPqF+3LFmQhm7MgCuYQOYuWyqxo5pwRPz5d/u6/WYJdEnWfK4r+jGbyD8TSggXQ==", + "license": "MIT", + "dependencies": { + "source-map": "0.5.6", + "stackframe": "^1.3.4" + } + }, + "node_modules/stacktrace-gps/node_modules/source-map": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.6.tgz", + "integrity": "sha512-MjZkVp0NHr5+TPihLcadqnlVoGIoWo4IBHptutGh9wI3ttUYvCG26HkSuDi+K6lsZ25syXJXcctwgyVCt//xqA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/stacktrace-js": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/stacktrace-js/-/stacktrace-js-2.0.2.tgz", + "integrity": "sha512-Je5vBeY4S1r/RnLydLl0TBTi3F2qdfWmYsGvtfZgEI+SCprPppaIhQf5nGcal4gI4cGpCV/duLcAzT1np6sQqg==", + "license": "MIT", + "dependencies": { + "error-stack-parser": "^2.0.6", + "stack-generator": "^2.0.5", + "stacktrace-gps": "^3.0.4" + } + }, + "node_modules/stat-mode": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-1.0.0.tgz", + "integrity": "sha512-jH9EhtKIjuXZ2cWxmXS8ZP80XyC3iasQxMDV8jzhNJpfDb7VbQLVW4Wvsxz9QZvzV+G4YoSfBUVKDOyxLzi/sg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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/string-argv": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz", + "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.19" + } + }, + "node_modules/string-convert": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/string-convert/-/string-convert-0.2.1.tgz", + "integrity": "sha512-u/1tdPl4yQnPBjnVrmdLo9gtuLvELKsAoRapekWggdiQNvvvum+jYF329d84NAa660KQw7pB2n36KrIKVoXa3A==", + "license": "MIT" + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.11", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.11.tgz", + "integrity": "sha512-PwvK7BU+CMTJGYQCTZb5RWXIML92lftJLhQz1tBzgKiqGxJaMlBAa48POXaNAC2s4y8jr3EFqrkF9+44neS46w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.2", + "es-object-atoms": "^1.1.2", + "has-property-descriptors": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.10.tgz", + "integrity": "sha512-2+3aDAOmPTmuFwjDnmJG2ctEkQKVki7vOSqaxkv42Mowj1V6PnvuwFCRrR5lChUux1TBskPjfkeTOhqczDMxTw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-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, + "license": "MIT", + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/stylis": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.4.0.tgz", + "integrity": "sha512-5Z9ZpRzfuH6l/UAvCPAPUo3665Nk2wLaZU3x+TLHKVzIz33+sbJqbtrYoC3KD4/uVOr2Zp+L0LySezP9OHV9yA==", + "license": "MIT" + }, + "node_modules/sucrase": { + "version": "3.35.1", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", + "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "tinyglobby": "^0.2.11", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/sudo-prompt": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", + "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/sumchecker": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sumchecker/-/sumchecker-3.0.1.tgz", + "integrity": "sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.0" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/systemjs": { + "version": "6.15.1", + "resolved": "https://registry.npmjs.org/systemjs/-/systemjs-6.15.1.tgz", + "integrity": "sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tailwindcss": { + "version": "3.4.19", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz", + "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.6.0", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.2", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.7", + "lilconfig": "^3.1.3", + "micromatch": "^4.0.8", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.1.1", + "postcss": "^8.4.47", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", + "postcss-nested": "^6.2.0", + "postcss-selector-parser": "^6.1.2", + "resolve": "^1.22.8", + "sucrase": "^3.35.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/tailwindcss/node_modules/chokidar/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" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/tailwindcss/node_modules/lilconfig": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", + "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/tailwindcss/node_modules/postcss-load-config": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "lilconfig": "^3.1.1" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "jiti": ">=1.21.0", + "postcss": ">=8.0.9", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + }, + "postcss": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/tailwindcss/node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/tailwindcss/node_modules/yaml": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.9.0.tgz", + "integrity": "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA==", + "extraneous": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/tar": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", + "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", + "deprecated": "Old versions of tar are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "dev": true, + "license": "ISC", + "dependencies": { + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "minipass": "^5.0.0", + "minizlib": "^2.1.1", + "mkdirp": "^1.0.3", + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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, + "license": "ISC" + }, + "node_modules/temp-file": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/temp-file/-/temp-file-3.4.0.tgz", + "integrity": "sha512-C5tjlC/HCtVUOi3KWVokd4vHVViOmGjtLwIh4MuzPo/nMYTV/p1urt3RnMz2IWXDdKEGJH3k5+KPxtqRsUYGtg==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-exit-hook": "^2.0.1", + "fs-extra": "^10.0.0" + } + }, + "node_modules/temp-file/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/terser": { + "version": "5.49.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.49.2.tgz", + "integrity": "sha512-rGbJiKeQ4WDe3EXlDAIaQcwftVfv2Q8o1awFNfvXolJYKkb1AuZY1RTOmqx4LJXZENbWZA7eIsYGHuEzHsi1nQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/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, + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "license": "MIT", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/throttle-debounce": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-5.0.2.tgz", + "integrity": "sha512-B71/4oyj61iNH0KeCamLuE2rmKuTO5byTOSVwECM5FA7TiAiAW+UqTKZ9ERueC4qvgSttUhdmq1mXC3kJqGX7A==", + "license": "MIT", + "engines": { + "node": ">=12.22" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "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/tinyglobby": { + "version": "0.2.17", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.17.tgz", + "integrity": "sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.4" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/tinyglobby/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/tinyglobby/node_modules/picomatch": { + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.5.tgz", + "integrity": "sha512-RvwwcruNjI1ncT5xRakeyS9Lf8lcItv34KD+aif+VH9kduAyfYBipGh12274xtenIPZ119/R9BdTBa8gAwSh0A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/tmp": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.7.tgz", + "integrity": "sha512-e0votIpp4Uo2AJYSzVHV6xCcawuiez3DzqDAbrTc3YxBkplN6e+dM13ZeIcZnDg/QpSuU2zfZ3rzwY8ukEnaXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.14" + } + }, + "node_modules/tmp-promise": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-3.0.3.tgz", + "integrity": "sha512-RwM7MoPojPxsOBYnyd2hy0bxtIlVrihNs9pj5SUvY8Zz1sQcQG2tG1hSr8PDxfgEB8RNKDhqbIlroIarSNDNsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tmp": "^0.2.0" + } + }, + "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/toggle-selection": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz", + "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==", + "license": "MIT" + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/truncate-utf8-bytes/-/truncate-utf8-bytes-1.0.2.tgz", + "integrity": "sha512-95Pu1QXQvruGEhv62XCMO3Mm90GscOCClvrIUwCM0PYOXK3kaF3l3sIHxx71ThJfcbM2O5Au6SO3AWCSEfW4mQ==", + "dev": true, + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/ts-debounce": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/ts-debounce/-/ts-debounce-4.0.0.tgz", + "integrity": "sha512-+1iDGY6NmOGidq7i7xZGA4cm8DAa6fqdYcvO5Z6yBevH++Bdo9Qt/mN0TzHUgcCcKv1gmh9+W5dHqz8pMWbCbg==", + "license": "MIT" + }, + "node_modules/ts-easing": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/ts-easing/-/ts-easing-0.2.0.tgz", + "integrity": "sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==", + "license": "Unlicense" + }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/ts-node/node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true, + "license": "MIT" + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "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/tsutils/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, + "license": "0BSD" + }, + "node_modules/turndown": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz", + "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==", + "license": "MIT", + "dependencies": { + "@mixmark-io/domino": "^2.2.0" + } + }, + "node_modules/turndown-plugin-gfm": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz", + "integrity": "sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==", + "license": "MIT" + }, + "node_modules/twemoji": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/twemoji/-/twemoji-14.0.1.tgz", + "integrity": "sha512-eoqhea0sUhmC10iTacksyp1v9O4BP1jKmVqtK+Nztw40/dzawSHkXL3/xCpyh+mukmEvJ0Gw9VLvwZfQ9HKXDw==", + "license": "MIT", + "dependencies": { + "fs-extra": "^8.0.1", + "jsonfile": "^5.0.0", + "twemoji-parser": "14.0.0", + "universalify": "^0.1.2" + } + }, + "node_modules/twemoji-parser": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/twemoji-parser/-/twemoji-parser-14.0.0.tgz", + "integrity": "sha512-9DUOTGLOWs0pFWnh1p6NF+C3CkQ96PWmEFwhOVmT3WbecRC+68AIqpsnJXygfkFcp4aXbOp8Dwbhh/HQgvoRxA==", + "license": "MIT" + }, + "node_modules/twemoji/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/twemoji/node_modules/fs-extra/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/twemoji/node_modules/jsonfile": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz", + "integrity": "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==", + "license": "MIT", + "dependencies": { + "universalify": "^0.1.2" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/twemoji/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/type": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz", + "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==", + "license": "ISC" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-fest": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz", + "integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.8.tgz", + "integrity": "sha512-phPGCwqr2+Qo0fwniCE8e4pKnGu/yFb5nD5Y8bf0EEeiI5GklnACYA9GFy/DrAeRrKHXvHn+1SUsOWgJp6RO+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.9", + "for-each": "^0.3.5", + "gopd": "^1.2.0", + "is-typed-array": "^1.1.15", + "possible-typed-array-names": "^1.1.0", + "reflect.getprototypeof": "^1.0.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/typed-emitter/-/typed-emitter-2.1.0.tgz", + "integrity": "sha512-g/KzbYKbH5C2vPkaXGu8DJlHrGKHLsM25Zg9WuC9pMGfuvT+X25tZQWo5fK1BjBm8+UrVE9LDCvaY0CQk+fXDA==", + "license": "MIT", + "optionalDependencies": { + "rxjs": "*" + } + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unload": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", + "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", + "license": "Apache-2.0", + "dependencies": { + "@babel/runtime": "^7.6.2", + "detect-node": "^2.0.4" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.3.0.tgz", + "integrity": "sha512-x/M6q3w4Ybp91CNaS4S69UnliqR3BzRpOT6LWbksjth0S/+jhfaPJsWjt/TewpT8j9eLIojUf5jr29WextHroA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/usehooks-ts": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/usehooks-ts/-/usehooks-ts-3.1.0.tgz", + "integrity": "sha512-bBIa7yUyPhE1BCc0GmR96VU/15l/9gP1Ch5mYdLcFBaFGQsdmXkvjV0TtOqW1yUd6VjIwDunm+flSciCQXujiw==", + "license": "MIT", + "dependencies": { + "lodash.debounce": "^4.0.8" + }, + "engines": { + "node": ">=16.15.0" + }, + "peerDependencies": { + "react": "^16.8.0 || ^17 || ^18" + } + }, + "node_modules/utf8-byte-length": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", + "integrity": "sha512-Xn0w3MtiQ6zoz2vFyUVruaCL53O/DwUvkEeOvj+uulMm0BkUGYWmBYVyElqZaSLhY6ZD0ulfU3aBra2aVT4xfA==", + "dev": true, + "license": "(WTFPL OR MIT)" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true, + "license": "MIT" + }, + "node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "dev": true, + "license": "MIT" + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/vanilla-colorful": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz", + "integrity": "sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg==", + "license": "MIT" + }, + "node_modules/verror": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", + "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/vite": { + "version": "4.5.14", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.14.tgz", + "integrity": "sha512-+v57oAaoYNnO3hIu5Z/tJRZjq5aHM2zDve9YZ8HngVHbhk66RStobhb1sqPMIPEleV6cNKYK4eGrAbE9Ulbl2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.18.10", + "postcss": "^8.4.27", + "rollup": "^3.27.1" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + }, + "peerDependencies": { + "@types/node": ">= 14", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-electron-plugin": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/vite-electron-plugin/-/vite-electron-plugin-0.8.3.tgz", + "integrity": "sha512-3F0xdYO0oIOTNUduV1Lows6P+tq2dtnjN0d/AwCnzbL8MynSzDX9HQpilur7C2VP6zRA3Gu/Uxdhg/IKZP3blA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "^3.2.12", + "notbundle": "~0.4.0", + "vite-plugin-electron": "~0.14.1" + }, + "peerDependencies": { + "acorn": "*", + "esbuild": "*" + }, + "peerDependenciesMeta": { + "acorn": { + "optional": true + }, + "esbuild": { + "optional": true + } + } + }, + "node_modules/vite-electron-plugin/node_modules/vite-plugin-electron": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/vite-plugin-electron/-/vite-plugin-electron-0.14.1.tgz", + "integrity": "sha512-QGQ2nJ4wjMf1FaDSkdoC/UskQGiYGcAToATJqJXvqrL4Jmt0CFaZqoDjh1xLicUWEo/X7urHYjhKTqwEeP7F7g==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "vite-plugin-electron-renderer": "*" + }, + "peerDependenciesMeta": { + "vite-plugin-electron-renderer": { + "optional": true + } + } + }, + "node_modules/vite-plugin-electron": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/vite-plugin-electron/-/vite-plugin-electron-0.11.2.tgz", + "integrity": "sha512-umQRmSuA80JVxKB3PfO55o8mFTrW+sEtu7kZ5TYKAnkuYpKw7qgxl4f/65gp8x5BGHJjYh/iIRIE26x3Xqc4mQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/void-elements": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz", + "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/webrtc-adapter": { + "version": "9.0.6", + "resolved": "https://registry.npmjs.org/webrtc-adapter/-/webrtc-adapter-9.0.6.tgz", + "integrity": "sha512-CHbl2ZQbxx164IgWRgzJno4hWtM4tFbRam1QfI3Yxhs3w/DvqluVxVWeXs3oL5/fbGkSNLKo0Ty5MgUWceNhog==", + "license": "BSD-3-Clause", + "dependencies": { + "sdp": "^3.2.0" + }, + "engines": { + "node": ">=6.0.0", + "npm": ">=3.10.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.22", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.22.tgz", + "integrity": "sha512-fvO4ExWMFsqyhG3AiPAObMuY1lxaqgYcxbc49CNdWDDECOJNgQyvsOWVwbZc+qf3rzRtxojBK+CMEv0Ld5CYpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "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/wrap-ansi/node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/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, + "license": "MIT" + }, + "node_modules/wrap-ansi/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, + "license": "MIT", + "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/wrap-ansi/node_modules/strip-ansi": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", + "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.2.2" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "license": "ISC" + }, + "node_modules/xgplayer": { + "version": "3.0.26", + "resolved": "https://registry.npmjs.org/xgplayer/-/xgplayer-3.0.26.tgz", + "integrity": "sha512-F/urLGIrxCa1DI+wtkPyT0TcRS6Wejbo+OZKOTlSVvg0+SGyN3TfSXddNcu6LL876ZTWzlEwhS4C5nKSUV5FZw==", + "license": "MIT", + "dependencies": { + "danmu.js": ">=1.2.1", + "delegate": "^3.2.0", + "eventemitter3": "^4.0.7", + "xgplayer-subtitles": "3.0.26" + }, + "peerDependencies": { + "core-js": ">=3.12.1" + } + }, + "node_modules/xgplayer-subtitles": { + "version": "3.0.26", + "resolved": "https://registry.npmjs.org/xgplayer-subtitles/-/xgplayer-subtitles-3.0.26.tgz", + "integrity": "sha512-HiHlw3E8emEQCv0xFYHdmNUFgyzyWGBnSNmyI/fkuuvRBb+4IbsCfxg6PF3r1TNCfzOuNzA/OaMbtXBSH8n/Bw==", + "license": "MIT", + "dependencies": { + "eventemitter3": "^4.0.7" + }, + "peerDependencies": { + "core-js": ">=3.12.1" + } + }, + "node_modules/xgplayer-subtitles/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/xgplayer/node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==", + "license": "MIT" + }, + "node_modules/xmlbuilder": { + "version": "15.1.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz", + "integrity": "sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.1.tgz", + "integrity": "sha512-2eHWfjaoXgTBC2jNM1LRef62VQa0umtvRiDSk6HSzW7RvS5YtkabJrwYLLEKWBc8a5U2PTSCs+dJjUTJdlHsWQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 14" + } + }, + "node_modules/yargs": { + "version": "17.7.3", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.3.tgz", + "integrity": "sha512-GZtjxm/J/4TSxuL3FNYjCmLktBTnIw/rVmKSIyKeYAZpmJB2ig9VauCC5xsa82GNKVKDAqpOn3KVzNt0zmrU0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "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/yargs/node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zustand": { + "version": "4.5.7", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.5.7.tgz", + "integrity": "sha512-CHOUy7mu3lbD6o6LJLfllpjkzhHXSBlX8B9+qPddUsIfeF5S/UZ5q0kmCsnRqT1UHFQZchNFDDzMbQsuesHWlw==", + "license": "MIT", + "dependencies": { + "use-sync-external-store": "^1.2.2" + }, + "engines": { + "node": ">=12.7.0" + }, + "peerDependencies": { + "@types/react": ">=16.8", + "immer": ">=9.0.6", + "react": ">=16.8" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + } + } + } + } +} diff --git a/pc-client/package.json b/pc-client/package.json new file mode 100644 index 0000000..d5888c4 --- /dev/null +++ b/pc-client/package.json @@ -0,0 +1,125 @@ +{ + "name": "changlian-pc", + "version": "1.0.0", + "main": "dist-electron/main/index.js", + "description": "OpenIM PC Client.", + "author": "blooming", + "private": true, + "debug": { + "env": { + "VITE_DEV_SERVER_URL": "http://127.0.0.1:7777/" + } + }, + "scripts": { + "dev": "vite --force --host", + "mock:account": "node scripts/mock-account-server.js", + "build": "vite build", + "preview": "vite preview", + "pree2e": "vite build --mode=test", + "e2e": "playwright test", + "format": "prettier --write .", + "lint": "eslint --ext .js,.jsx,.ts,.tsx src", + "lint:fix": "eslint --ext .js,.jsx,.ts,.tsx --fix --quiet src", + "prepare": "husky install", + "postinstall": "patch-package" + }, + "devDependencies": { + "@commitlint/cli": "^17.4.4", + "@commitlint/config-conventional": "^17.4.4", + "@playwright/test": "^1.31.0", + "@types/md5": "^2.3.2", + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "@types/uuid": "^9.0.1", + "@typescript-eslint/eslint-plugin": "^5.53.0", + "@typescript-eslint/parser": "^5.53.0", + "@vitejs/plugin-legacy": "^4.1.0", + "@vitejs/plugin-react": "^3.1.0", + "autoprefixer": "^10.4.13", + "electron": "^22.3.27", + "electron-builder": "^23.6.0", + "eslint": "^8.34.0", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "husky": "^8.0.3", + "lint-staged": "^13.1.2", + "patch-package": "^8.0.0", + "postcss": "^8.4.21", + "postcss-nesting": "^12.0.2", + "prettier": "^2.8.4", + "prettier-plugin-tailwindcss": "^0.2.3", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.58.3", + "tailwindcss": "^3.2.7", + "terser": "^5.19.0", + "typescript": "^4.9.5", + "vite": "^4.1.4", + "vite-electron-plugin": "^0.8.2", + "vite-plugin-electron": "^0.11.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "lint-staged": { + "src/**/*.{tsx,ts}": [ + "prettier --write", + "eslint --fix" + ], + "*.{json,html,css,scss,xml,md}": [ + "prettier --write" + ] + }, + "dependencies": { + "@ant-design/icons": "^5.1.4", + "@ckeditor/ckeditor5-react": "^8.0.0", + "@livekit/components-react": "2.6.9", + "@livekit/components-styles": "1.1.4", + "@openim/electron-client-sdk": "^3.8.3-patch.10", + "@openim/wasm-client-sdk": "^3.8.3-patch.10", + "adm-zip": "^0.5.10", + "ahooks": "^3.7.7", + "antd": "5.10.0", + "axios": "^1.4.0", + "ckeditor5": "^43.0.0", + "clsx": "^1.2.1", + "date-fns": "^2.30.0", + "dayjs": "^1.11.7", + "electron-log": "^5.0.0", + "electron-screenshots": "^0.5.27", + "electron-store": "^8.1.0", + "electron-updater": "^5.3.0", + "emoji-picker-element": "1.21.3", + "i18next": "^22.5.0", + "i18next-browser-languagedetector": "^7.0.2", + "i18next-fs-backend": "^2.2.0", + "livekit-client": "2.7.0", + "localforage": "^1.10.0", + "md5": "^2.3.0", + "mitt": "^3.0.0", + "react-draggable": "^4.4.5", + "react-i18next": "^12.3.1", + "react-image-file-resizer": "^0.4.8", + "react-query": "^3.39.3", + "react-resizable-panels": "^2.0.2", + "react-router-dom": "^6.11.1", + "react-use": "^17.4.0", + "react-virtuoso": "4.3.8", + "sudo-prompt": "^9.2.1", + "twemoji": "14.0.1", + "uuid": "^9.0.1", + "xgplayer": "^3.0.5", + "zustand": "^4.3.3" + }, + "allowScripts": { + "@parcel/watcher@2.6.0": true, + "core-js@3.50.0": true, + "electron@22.3.27": true, + "es5-ext@0.10.64": true, + "esbuild@0.18.20": true, + "koffi@2.8.0": true + } +} diff --git a/pc-client/package_dev.json b/pc-client/package_dev.json new file mode 100644 index 0000000..b1e3510 --- /dev/null +++ b/pc-client/package_dev.json @@ -0,0 +1,111 @@ +{ + "name": "OpenCorp-Base", + "version": "1.0.0", + "main": "dist-electron/main/index.js", + "description": "OpenIM PC Client.", + "author": "blooming", + "private": true, + "debug": { + "env": { + "VITE_DEV_SERVER_URL": "http://127.0.0.1:7777/" + } + }, + "scripts": { + "dev": "vite --force --host", + "build": "vite build", + "preview": "vite preview", + "pree2e": "vite build --mode=test", + "e2e": "playwright test", + "format": "prettier --write .", + "lint": "eslint --ext .js,.jsx,.ts,.tsx src", + "lint:fix": "eslint --ext .js,.jsx,.ts,.tsx --fix --quiet src", + "prepare": "husky install", + "postinstall": "patch-package" + }, + "devDependencies": { + "@commitlint/cli": "^17.4.4", + "@commitlint/config-conventional": "^17.4.4", + "@playwright/test": "^1.31.0", + "@types/md5": "^2.3.2", + "@types/react": "^18.0.28", + "@types/react-dom": "^18.0.11", + "@types/uuid": "^9.0.1", + "@typescript-eslint/eslint-plugin": "^5.53.0", + "@typescript-eslint/parser": "^5.53.0", + "@vitejs/plugin-legacy": "^4.1.0", + "@vitejs/plugin-react": "^3.1.0", + "autoprefixer": "^10.4.13", + "electron": "^22.3.27", + "electron-builder": "^23.6.0", + "eslint": "^8.34.0", + "eslint-config-prettier": "^8.6.0", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.32.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-simple-import-sort": "^10.0.0", + "husky": "^8.0.3", + "lint-staged": "^13.1.2", + "patch-package": "^8.0.0", + "postcss": "^8.4.21", + "postcss-nesting": "^12.0.2", + "prettier": "^2.8.4", + "prettier-plugin-tailwindcss": "^0.2.3", + "react": "^18.2.0", + "react-dom": "^18.2.0", + "sass": "^1.58.3", + "tailwindcss": "^3.2.7", + "terser": "^5.19.0", + "typescript": "^4.9.5", + "vite": "^4.1.4", + "vite-electron-plugin": "^0.8.2", + "vite-plugin-electron": "^0.11.1" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "lint-staged": { + "src/**/*.{tsx,ts}": ["prettier --write", "eslint --fix"], + "*.{json,html,css,scss,xml,md}": ["prettier --write"] + }, + "dependencies": { + "@ant-design/icons": "^5.1.4", + "@ckeditor/ckeditor5-react": "^8.0.0", + "@livekit/components-react": "^2.6.9", + "@livekit/components-styles": "^1.1.4", + "@openim/electron-client-sdk": "^3.8.3-patch.3", + "@openim/wasm-client-sdk": "^3.8.3-patch.3", + "adm-zip": "^0.5.10", + "ahooks": "^3.7.7", + "antd": "5.10.0", + "axios": "^1.4.0", + "ckeditor5": "^43.0.0", + "clsx": "^1.2.1", + "date-fns": "^2.30.0", + "dayjs": "^1.11.7", + "electron-log": "^5.0.0", + "electron-screenshots": "^0.5.23", + "electron-store": "^8.1.0", + "electron-updater": "^5.3.0", + "emoji-picker-element": "1.21.3", + "i18next": "^22.5.0", + "i18next-browser-languagedetector": "^7.0.2", + "i18next-fs-backend": "^2.2.0", + "livekit-client": "2.7.0", + "localforage": "^1.10.0", + "md5": "^2.3.0", + "mitt": "^3.0.0", + "react-draggable": "^4.4.5", + "react-i18next": "^12.3.1", + "react-image-file-resizer": "^0.4.8", + "react-query": "^3.39.3", + "react-resizable-panels": "^2.0.2", + "react-router-dom": "^6.11.1", + "react-use": "^17.4.0", + "react-virtuoso": "4.3.8", + "sudo-prompt": "^9.2.1", + "twemoji": "14.0.1", + "uuid": "^9.0.1", + "xgplayer": "^3.0.5", + "zustand": "^4.3.3" + } +} diff --git a/pc-client/package_electron.json b/pc-client/package_electron.json new file mode 100644 index 0000000..a693bdb --- /dev/null +++ b/pc-client/package_electron.json @@ -0,0 +1,48 @@ +{ + "name": "OpenCorp-Base", + "version": "3.8.3", + "main": "dist-electron/main/index.js", + "description": "OpenIM PC Client.", + "author": "blooming", + "private": true, + "debug": { + "env": { + "VITE_DEV_SERVER_URL": "http://127.0.0.1:7777/" + } + }, + "scripts": { + "dev": "vite --host", + "build": "vite build", + "preview": "vite preview", + "build:mac": "vite build && electron-builder --macos --x64", + "build:mac-arm": "vite build && electron-builder --macos --arm64", + "build:win": "vite build && electron-builder --win --x64", + "build:win-arm": "vite build && electron-builder --win --arm64", + "build:linux": "vite build && electron-builder --linux --x64", + "build:linux-arm": "vite build && electron-builder --linux --arm64", + "build:all": "vite build && electron-builder --macos --x64 && electron-builder --macos --arm64 && electron-builder --win --x64 && electron-builder --linux --x64 && electron-builder --linux --arm64", + "pree2e": "vite build --mode=test", + "e2e": "playwright test", + "format": "prettier --write .", + "lint": "eslint --ext .js,.jsx,.ts,.tsx src", + "lint:fix": "eslint --ext .js,.jsx,.ts,.tsx --fix --quiet src", + "prepare": "husky install" + }, + "engines": { + "node": "^14.18.0 || >=16.0.0" + }, + "lint-staged": { + "src/**/*.{tsx,ts}": ["prettier --write", "eslint --fix"], + "*.{json,html,css,scss,xml,md}": ["prettier --write"] + }, + "dependencies": { + "@openim/electron-client-sdk": "^3.8.3-patch.3", + "@openim/wasm-client-sdk": "^3.8.3-patch.3", + "electron-log": "^5.0.0", + "electron-screenshots": "^0.5.23", + "electron-store": "^8.1.0", + "adm-zip": "^0.5.10", + "i18next": "^22.5.0", + "sudo-prompt": "^9.2.1" + } +} diff --git a/pc-client/patches/@ckeditor+ckeditor5-ui+43.0.0.patch b/pc-client/patches/@ckeditor+ckeditor5-ui+43.0.0.patch new file mode 100644 index 0000000..d820bd8 --- /dev/null +++ b/pc-client/patches/@ckeditor+ckeditor5-ui+43.0.0.patch @@ -0,0 +1,42 @@ +diff --git a/node_modules/@ckeditor/ckeditor5-ui/src/editorui/poweredby.js b/node_modules/@ckeditor/ckeditor5-ui/src/editorui/poweredby.js +index 191aba1..324f6d2 100644 +--- a/node_modules/@ckeditor/ckeditor5-ui/src/editorui/poweredby.js ++++ b/node_modules/@ckeditor/ckeditor5-ui/src/editorui/poweredby.js +@@ -112,12 +112,9 @@ export default class PoweredBy extends /* #__PURE__ */ DomEmitterMixin() { + if (!this._balloonView) { + this._createBalloonView(); + } +- this._balloonView.pin(attachOptions); ++ // this._balloonView.pin(attachOptions); + } + } +- /** +- * Hides the "powered by" balloon if already visible. +- */ + _hideBalloon() { + if (this._balloonView) { + this._balloonView.unpin(); +diff --git a/node_modules/@ckeditor/ckeditor5-ui/src/icon/iconview.js b/node_modules/@ckeditor/ckeditor5-ui/src/icon/iconview.js +index dd6d2ed..7af8e61 100644 +--- a/node_modules/@ckeditor/ckeditor5-ui/src/icon/iconview.js ++++ b/node_modules/@ckeditor/ckeditor5-ui/src/icon/iconview.js +@@ -42,17 +42,14 @@ class IconView extends View { + } + }); + } +- /** +- * @inheritDoc +- */ + render() { + super.render(); +- this._updateXMLContent(); ++ // this._updateXMLContent(); + this._colorFillPaths(); + // This is a hack for lack of innerHTML binding. + // See: https://github.com/ckeditor/ckeditor5-ui/issues/99. + this.on('change:content', () => { +- this._updateXMLContent(); ++ // this._updateXMLContent(); + this._colorFillPaths(); + }); + this.on('change:fillColor', () => { diff --git a/pc-client/playwright.config.ts b/pc-client/playwright.config.ts new file mode 100644 index 0000000..d323551 --- /dev/null +++ b/pc-client/playwright.config.ts @@ -0,0 +1,54 @@ +import type { PlaywrightTestConfig } from "@playwright/test"; + +/** + * Read environment variables from file. + * https://github.com/motdotla/dotenv + */ +// require('dotenv').config(); + +/** + * See https://playwright.dev/docs/test-configuration. + */ +const config: PlaywrightTestConfig = { + testDir: "./e2e", + /* Maximum time one test can run for. */ + timeout: 30 * 1000, + expect: { + /** + * Maximum time expect() should wait for the condition to be met. + * For example in `await expect(locator).toHaveText();` + */ + timeout: 5000, + }, + /* Run tests in files in parallel */ + fullyParallel: true, + /* Fail the build on CI if you accidentally left test.only in the source code. */ + forbidOnly: !!process.env.CI, + /* Retry on CI only */ + retries: process.env.CI ? 2 : 0, + /* Opt out of parallel tests on CI. */ + workers: process.env.CI ? 1 : undefined, + /* Reporter to use. See https://playwright.dev/docs/test-reporters */ + reporter: "html", + /* Shared settings for all the projects below. See https://playwright.dev/docs/api/class-testoptions. */ + use: { + /* Maximum time each action such as `click()` can take. Defaults to 0 (no limit). */ + actionTimeout: 0, + /* Base URL to use in actions like `await page.goto('/')`. */ + // baseURL: 'http://localhost:3000', + + /* Collect trace when retrying the failed test. See https://playwright.dev/docs/trace-viewer */ + trace: "on-first-retry", + }, + + /* Folder for test artifacts such as screenshots, videos, traces, etc. */ + // outputDir: 'test-results/', + + /* Run your local dev server before starting the tests */ + // webServer: { + // command: 'npm run start', + // port: 3000, + // }, +}; + +export default config; diff --git a/pc-client/postcss.config.js b/pc-client/postcss.config.js new file mode 100644 index 0000000..34df5ca --- /dev/null +++ b/pc-client/postcss.config.js @@ -0,0 +1,8 @@ +module.exports = { + plugins: { + 'tailwindcss/nesting': 'postcss-nesting', + tailwindcss: {}, + autoprefixer: {} + }, +}; + \ No newline at end of file diff --git a/pc-client/public/emojis.json b/pc-client/public/emojis.json new file mode 100644 index 0000000..74ddb11 --- /dev/null +++ b/pc-client/public/emojis.json @@ -0,0 +1 @@ +[{"annotation":"嘿嘿","name":"GRINNING FACE","hexcode":"1F600","shortcodes":["gleeful"],"tags":["笑脸","脸"],"emoji":"😀","text":"","type":1,"order":1,"group":0,"subgroup":0,"version":1,"emoticon":":D"},{"annotation":"哈哈","name":"SMILING FACE WITH OPEN MOUTH","hexcode":"1F603","shortcodes":["glad","smile"],"tags":["开口笑","笑脸","脸"],"emoji":"😃","text":"","type":1,"order":2,"group":0,"subgroup":0,"version":0.6},{"annotation":"大笑","name":"SMILING FACE WITH OPEN MOUTH AND SMILING EYES","hexcode":"1F604","shortcodes":["happy"],"tags":["哈哈","开心","笑","脸","高兴"],"emoji":"😄","text":"","type":1,"order":3,"group":0,"subgroup":0,"version":0.6},{"annotation":"嘻嘻","name":"GRINNING FACE WITH SMILING EYES","hexcode":"1F601","shortcodes":["blissful","grin"],"tags":["笑脸","脸"],"emoji":"😁","text":"","type":1,"order":4,"group":0,"subgroup":0,"version":0.6},{"annotation":"斜眼笑","name":"SMILING FACE WITH OPEN MOUTH AND TIGHTLY-CLOSED EYES","hexcode":"1F606","shortcodes":["amused","laugh","lol"],"tags":["开心","眯眼","笑","脸","高兴"],"emoji":"😆","text":"","type":1,"order":5,"group":0,"subgroup":0,"version":0.6,"emoticon":"xD"},{"annotation":"苦笑","name":"SMILING FACE WITH OPEN MOUTH AND COLD SWEAT","hexcode":"1F605","shortcodes":["embarassed","sweat_smile"],"tags":["冷汗","汗","脸"],"emoji":"😅","text":"","type":1,"order":6,"group":0,"subgroup":0,"version":0.6},{"annotation":"笑得满地打滚","name":"ROLLING ON THE FLOOR LAUGHING","hexcode":"1F923","shortcodes":["entertained","rofl"],"tags":["地板","打滚","笑","脸"],"emoji":"🤣","text":"","type":1,"order":7,"group":0,"subgroup":0,"version":3,"emoticon":":'D"},{"annotation":"笑哭了","name":"FACE WITH TEARS OF JOY","hexcode":"1F602","shortcodes":["joyful","haha"],"tags":["眼泪","笑","脸"],"emoji":"😂","text":"","type":1,"order":8,"group":0,"subgroup":0,"version":0.6,"emoticon":":')"},{"annotation":"呵呵","name":"SLIGHTLY SMILING FACE","hexcode":"1F642","shortcodes":["pleased","slight_smile"],"tags":["开心","笑","脸"],"emoji":"🙂","text":"","type":1,"order":9,"group":0,"subgroup":0,"version":1,"emoticon":":)"},{"annotation":"倒脸","name":"UPSIDE-DOWN FACE","hexcode":"1F643","shortcodes":["ecstatic","upside_down"],"tags":["脸","颠倒","颠倒的脸"],"emoji":"🙃","text":"","type":1,"order":10,"group":0,"subgroup":0,"version":1},{"annotation":"眨眼","name":"WINKING FACE","hexcode":"1F609","shortcodes":["coy","wink"],"tags":["媚眼","笑"],"emoji":"😉","text":"","type":1,"order":11,"group":0,"subgroup":0,"version":0.6,"emoticon":";)"},{"annotation":"羞涩微笑","name":"SMILING FACE WITH SMILING EYES","hexcode":"1F60A","shortcodes":["blush"],"tags":["害羞","微笑","羞涩","脸","脸红"],"emoji":"😊","text":"","type":1,"order":12,"group":0,"subgroup":0,"version":0.6,"emoticon":":>"},{"annotation":"微笑天使","name":"SMILING FACE WITH HALO","hexcode":"1F607","shortcodes":["innocent","halo"],"tags":["光环","天使","天真","幻想","微笑","脸"],"emoji":"😇","text":"","type":1,"order":13,"group":0,"subgroup":0,"version":1,"emoticon":"o:)"},{"annotation":"喜笑颜开","name":"SMILING FACE WITH SMILING EYES AND THREE HEARTS","hexcode":"1F970","shortcodes":["love"],"tags":["心","爱慕","迷恋","陷入爱河"],"emoji":"🥰","text":"","type":1,"order":14,"group":0,"subgroup":1,"version":11},{"annotation":"花痴","name":"SMILING FACE WITH HEART-SHAPED EYES","hexcode":"1F60D","shortcodes":["lovestruck"],"tags":["爱","红心","脸"],"emoji":"😍","text":"","type":1,"order":15,"group":0,"subgroup":1,"version":0.6},{"annotation":"好崇拜哦","name":"GRINNING FACE WITH STAR EYES","hexcode":"1F929","shortcodes":["starstruck"],"tags":["咧嘴笑","脸","露齿笑"],"emoji":"🤩","text":"","type":1,"order":16,"group":0,"subgroup":1,"version":5},{"annotation":"飞吻","name":"FACE THROWING A KISS","hexcode":"1F618","shortcodes":["flirty"],"tags":["亲亲","眨眼","脸"],"emoji":"😘","text":"","type":1,"order":17,"group":0,"subgroup":1,"version":0.6,"emoticon":":x"},{"annotation":"亲亲","name":"KISSING FACE","hexcode":"1F617","shortcodes":["kiss"],"tags":["吻","脸"],"emoji":"😗","text":"","type":1,"order":18,"group":0,"subgroup":1,"version":1},{"annotation":"微笑","name":"WHITE SMILING FACE","hexcode":"263A","shortcodes":["relaxed"],"tags":["呵呵","开心","放松","笑","脸"],"emoji":"☺️","text":"☺︎","type":0,"order":20,"group":0,"subgroup":1,"version":0.6},{"annotation":"羞涩亲亲","name":"KISSING FACE WITH CLOSED EYES","hexcode":"1F61A","shortcodes":["loving_kiss"],"tags":["亲亲","吻","羞涩","脸","闭眼"],"emoji":"😚","text":"","type":1,"order":21,"group":0,"subgroup":1,"version":0.6,"emoticon":":*"},{"annotation":"微笑亲亲","name":"KISSING FACE WITH SMILING EYES","hexcode":"1F619","shortcodes":["happy_kiss"],"tags":["亲亲","吻","微笑","脸"],"emoji":"😙","text":"","type":1,"order":22,"group":0,"subgroup":1,"version":1},{"annotation":"含泪的笑脸","name":"SMILING FACE WITH TEAR","hexcode":"1F972","shortcodes":["tear_smile"],"tags":["微笑的","感动的","感恩的","眼泪","释怀的","骄傲的"],"emoji":"🥲","text":"","type":1,"order":23,"group":0,"subgroup":1,"version":13},{"annotation":"好吃","name":"FACE SAVOURING DELICIOUS FOOD","hexcode":"1F60B","shortcodes":["yum","savour"],"tags":["津津有味","美味","脸"],"emoji":"😋","text":"","type":1,"order":24,"group":0,"subgroup":2,"version":0.6},{"annotation":"吐舌","name":"FACE WITH STUCK-OUT TONGUE","hexcode":"1F61B","shortcodes":["playful","tongue_out"],"tags":["脸","舌头","调皮"],"emoji":"😛","text":"","type":1,"order":25,"group":0,"subgroup":2,"version":1,"emoticon":":p"},{"annotation":"单眼吐舌","name":"FACE WITH STUCK-OUT TONGUE AND WINKING EYE","hexcode":"1F61C","shortcodes":["mischievous"],"tags":["单眼","吐舌","开玩笑","脸"],"emoji":"😜","text":"","type":1,"order":26,"group":0,"subgroup":2,"version":0.6,"emoticon":";p"},{"annotation":"滑稽","name":"GRINNING FACE WITH ONE LARGE AND ONE SMALL EYE","hexcode":"1F92A","shortcodes":["crazy"],"tags":["大眼","小眼","滑稽的脸","疯狂的脸","脸"],"emoji":"🤪","text":"","type":1,"order":27,"group":0,"subgroup":2,"version":5},{"annotation":"眯眼吐舌","name":"FACE WITH STUCK-OUT TONGUE AND TIGHTLY-CLOSED EYES","hexcode":"1F61D","shortcodes":["facetious","lmao"],"tags":["可怕","吐舌","眯眼","眼睛","脸"],"emoji":"😝","text":"","type":1,"order":28,"group":0,"subgroup":2,"version":0.6,"emoticon":"xp"},{"annotation":"发财","name":"MONEY-MOUTH FACE","hexcode":"1F911","shortcodes":["pretentious","money_mouth"],"tags":["拜金","脸","见钱眼开","钱"],"emoji":"🤑","text":"","type":1,"order":29,"group":0,"subgroup":2,"version":1},{"annotation":"抱抱","name":"HUGGING FACE","hexcode":"1F917","shortcodes":["hugging"],"tags":["抱","拥抱","笑","脸"],"emoji":"🤗","text":"","type":1,"order":30,"group":0,"subgroup":3,"version":1},{"annotation":"不说","name":"SMILING FACE WITH SMILING EYES AND HAND COVERING MOUTH","hexcode":"1F92D","shortcodes":["gasp"],"tags":["哎呀","脸"],"emoji":"🤭","text":"","type":1,"order":31,"group":0,"subgroup":3,"version":5},{"annotation":"安静的脸","name":"FACE WITH FINGER COVERING CLOSED LIPS","hexcode":"1F92B","shortcodes":["shushing"],"tags":["嘘","安静"],"emoji":"🤫","text":"","type":1,"order":32,"group":0,"subgroup":3,"version":5},{"annotation":"想一想","name":"THINKING FACE","hexcode":"1F914","shortcodes":["curious","thinking"],"tags":["思考","想","脸"],"emoji":"🤔","text":"","type":1,"order":33,"group":0,"subgroup":3,"version":1,"emoticon":":l"},{"annotation":"闭嘴","name":"ZIPPER-MOUTH FACE","hexcode":"1F910","shortcodes":["silenced","zipper_mouth"],"tags":["嘴","脸"],"emoji":"🤐","text":"","type":1,"order":34,"group":0,"subgroup":4,"version":1,"emoticon":":z"},{"annotation":"挑眉","name":"FACE WITH ONE EYEBROW RAISED","hexcode":"1F928","shortcodes":["contempt"],"tags":["不信任","怀疑","眉毛上挑的脸","脸"],"emoji":"🤨","text":"","type":1,"order":35,"group":0,"subgroup":4,"version":5},{"annotation":"冷漠","name":"NEUTRAL FACE","hexcode":"1F610","shortcodes":["indifferent","neutral"],"tags":["脸","面无表情"],"emoji":"😐️","text":"😐︎","type":1,"order":36,"group":0,"subgroup":4,"version":0.7,"emoticon":":|"},{"annotation":"无语","name":"EXPRESSIONLESS FACE","hexcode":"1F611","shortcodes":["apathetic","expressionless"],"tags":["脸","茫然","面无表情"],"emoji":"😑","text":"","type":1,"order":37,"group":0,"subgroup":4,"version":1},{"annotation":"沉默","name":"FACE WITHOUT MOUTH","hexcode":"1F636","shortcodes":["vacant","no_mouth"],"tags":["嘴","安静","脸"],"emoji":"😶","text":"","type":1,"order":38,"group":0,"subgroup":4,"version":1,"emoticon":":#"},{"annotation":"得意","name":"SMIRKING FACE","hexcode":"1F60F","shortcodes":["cocky","smirk"],"tags":["假笑"],"emoji":"😏","text":"","type":1,"order":39,"group":0,"subgroup":4,"version":0.6,"emoticon":":j"},{"annotation":"不高兴","name":"UNAMUSED FACE","hexcode":"1F612","shortcodes":["unamused"],"tags":["不屑","不服","脸","郁闷","鄙视"],"emoji":"😒","text":"","type":1,"order":40,"group":0,"subgroup":4,"version":0.6,"emoticon":":?"},{"annotation":"翻白眼","name":"FACE WITH ROLLING EYES","hexcode":"1F644","shortcodes":["disbelief"],"tags":["无语","白眼","脸"],"emoji":"🙄","text":"","type":1,"order":41,"group":0,"subgroup":4,"version":1},{"annotation":"龇牙咧嘴","name":"GRIMACING FACE","hexcode":"1F62C","shortcodes":["grimaced"],"tags":["咬牙切齿","脸","露齿","鬼脸"],"emoji":"😬","text":"","type":1,"order":42,"group":0,"subgroup":4,"version":1,"emoticon":"8D"},{"annotation":"说谎","name":"LYING FACE","hexcode":"1F925","shortcodes":["lying"],"tags":["匹诺曹","脸","长鼻子"],"emoji":"🤥","text":"","type":1,"order":43,"group":0,"subgroup":4,"version":3},{"annotation":"松了口气","name":"RELIEVED FACE","hexcode":"1F60C","shortcodes":["relieved"],"tags":["如释重负","松口气","脸"],"emoji":"😌","text":"","type":1,"order":44,"group":0,"subgroup":5,"version":0.6},{"annotation":"沉思","name":"PENSIVE FACE","hexcode":"1F614","shortcodes":["pensive"],"tags":["心事重重","脸"],"emoji":"😔","text":"","type":1,"order":45,"group":0,"subgroup":5,"version":0.6},{"annotation":"困","name":"SLEEPY FACE","hexcode":"1F62A","shortcodes":["sleepy"],"tags":["睡觉","瞌睡","脸"],"emoji":"😪","text":"","type":1,"order":46,"group":0,"subgroup":5,"version":0.6},{"annotation":"流口水","name":"DROOLING FACE","hexcode":"1F924","shortcodes":["drooling"],"tags":["口水","垂涎三尺","脸"],"emoji":"🤤","text":"","type":1,"order":47,"group":0,"subgroup":5,"version":3},{"annotation":"睡着了","name":"SLEEPING FACE","hexcode":"1F634","shortcodes":["exhausted","sleeping"],"tags":["呼噜","打呼","脸"],"emoji":"😴","text":"","type":1,"order":48,"group":0,"subgroup":5,"version":1},{"annotation":"感冒","name":"FACE WITH MEDICAL MASK","hexcode":"1F637","shortcodes":["ill","mask"],"tags":["医生","口罩","生病","脸"],"emoji":"😷","text":"","type":1,"order":49,"group":0,"subgroup":6,"version":0.6},{"annotation":"发烧","name":"FACE WITH THERMOMETER","hexcode":"1F912","shortcodes":["sick"],"tags":["体温计","温度计","生病","脸"],"emoji":"🤒","text":"","type":1,"order":50,"group":0,"subgroup":6,"version":1},{"annotation":"受伤","name":"FACE WITH HEAD-BANDAGE","hexcode":"1F915","shortcodes":["injured"],"tags":["打绷带","脸"],"emoji":"🤕","text":"","type":1,"order":51,"group":0,"subgroup":6,"version":1},{"annotation":"恶心","name":"NAUSEATED FACE","hexcode":"1F922","shortcodes":["nauseated"],"tags":["吐","呕","脸"],"emoji":"🤢","text":"","type":1,"order":52,"group":0,"subgroup":6,"version":3,"emoticon":"%("},{"annotation":"呕吐","name":"FACE WITH OPEN MOUTH VOMITING","hexcode":"1F92E","shortcodes":["vomiting"],"tags":["不舒服","脸"],"emoji":"🤮","text":"","type":1,"order":53,"group":0,"subgroup":6,"version":5},{"annotation":"打喷嚏","name":"SNEEZING FACE","hexcode":"1F927","shortcodes":["sneezing"],"tags":["喷嚏","脸","鼻涕"],"emoji":"🤧","text":"","type":1,"order":54,"group":0,"subgroup":6,"version":3},{"annotation":"脸发烧","name":"OVERHEATED FACE","hexcode":"1F975","shortcodes":["overheating"],"tags":["出汗","发烧","发热","心狂跳","脸红"],"emoji":"🥵","text":"","type":1,"order":55,"group":0,"subgroup":6,"version":11},{"annotation":"冷脸","name":"FREEZING FACE","hexcode":"1F976","shortcodes":["freezing"],"tags":["冷","冷冰冰","冻僵","满面寒霜"],"emoji":"🥶","text":"","type":1,"order":56,"group":0,"subgroup":6,"version":11},{"annotation":"头昏眼花","name":"FACE WITH UNEVEN EYES AND WAVY MOUTH","hexcode":"1F974","shortcodes":["woozy"],"tags":["嘴唇颤抖","头晕眼花","微醺","眼花","醉醺醺"],"emoji":"🥴","text":"","type":1,"order":57,"group":0,"subgroup":6,"version":11,"emoticon":":&"},{"annotation":"晕头转向","name":"DIZZY FACE","hexcode":"1F635","shortcodes":["dizzy"],"tags":["头晕","头晕眼花","晕头","脸"],"emoji":"😵","text":"","type":1,"order":58,"group":0,"subgroup":6,"version":0.6,"emoticon":"xo"},{"annotation":"爆炸头","name":"SHOCKED FACE WITH EXPLODING HEAD","hexcode":"1F92F","shortcodes":["shocked","exploding_head"],"tags":["震惊"],"emoji":"🤯","text":"","type":1,"order":59,"group":0,"subgroup":6,"version":5},{"annotation":"牛仔帽脸","name":"FACE WITH COWBOY HAT","hexcode":"1F920","shortcodes":["cowboy"],"tags":["帽","牛仔","脸"],"emoji":"🤠","text":"","type":1,"order":60,"group":0,"subgroup":7,"version":3},{"annotation":"聚会笑脸","name":"FACE WITH PARTY HORN AND PARTY HAT","hexcode":"1F973","shortcodes":["partying","celebrating"],"tags":["号角","帽子","庆祝","聚会"],"emoji":"🥳","text":"","type":1,"order":61,"group":0,"subgroup":7,"version":11},{"annotation":"伪装的脸","name":"DISGUISED FACE","hexcode":"1F978","shortcodes":["disguised_face"],"tags":["伪装","眼镜","脸","隐瞒身份","鼻子"],"emoji":"🥸","text":"","type":1,"order":62,"group":0,"subgroup":7,"version":13},{"annotation":"墨镜笑脸","name":"SMILING FACE WITH SUNGLASSES","hexcode":"1F60E","shortcodes":["confident"],"tags":["墨镜","太阳镜","眼镜","酷"],"emoji":"😎","text":"","type":1,"order":63,"group":0,"subgroup":8,"version":1,"emoticon":"8)"},{"annotation":"书呆子脸","name":"NERD FACE","hexcode":"1F913","shortcodes":["nerd"],"tags":["奇葩","脸"],"emoji":"🤓","text":"","type":1,"order":64,"group":0,"subgroup":8,"version":1,"emoticon":":B"},{"annotation":"带单片眼镜的脸","name":"FACE WITH MONOCLE","hexcode":"1F9D0","shortcodes":["monocle"],"tags":["古板"],"emoji":"🧐","text":"","type":1,"order":65,"group":0,"subgroup":8,"version":5},{"annotation":"困扰","name":"CONFUSED FACE","hexcode":"1F615","shortcodes":["confused"],"tags":["不懂","困惑","疑惑","脸"],"emoji":"😕","text":"","type":1,"order":66,"group":0,"subgroup":9,"version":1,"emoticon":":/"},{"annotation":"担心","name":"WORRIED FACE","hexcode":"1F61F","shortcodes":["worried"],"tags":["不高兴","伤心","担忧","焦虑","脸"],"emoji":"😟","text":"","type":1,"order":67,"group":0,"subgroup":9,"version":1},{"annotation":"微微不满","name":"SLIGHTLY FROWNING FACE","hexcode":"1F641","shortcodes":["cheerless","slight_frown"],"tags":["不开心","不高兴","委屈","心情不好","脸"],"emoji":"🙁","text":"","type":1,"order":68,"group":0,"subgroup":9,"version":1},{"annotation":"不满","name":"WHITE FROWNING FACE","hexcode":"2639","shortcodes":["sad","frowning"],"tags":["不爽","不高兴","皱眉","脸"],"emoji":"☹️","text":"☹︎","type":0,"order":70,"group":0,"subgroup":9,"version":0.7,"emoticon":":("},{"annotation":"吃惊","name":"FACE WITH OPEN MOUTH","hexcode":"1F62E","shortcodes":["surprised"],"tags":["同情","啊","脸"],"emoji":"😮","text":"","type":1,"order":71,"group":0,"subgroup":9,"version":1},{"annotation":"缄默","name":"HUSHED FACE","hexcode":"1F62F","shortcodes":["hushed"],"tags":["吃惊","脸"],"emoji":"😯","text":"","type":1,"order":72,"group":0,"subgroup":9,"version":1},{"annotation":"震惊","name":"ASTONISHED FACE","hexcode":"1F632","shortcodes":["astonished"],"tags":["惊","惊讶","脸"],"emoji":"😲","text":"","type":1,"order":73,"group":0,"subgroup":9,"version":0.6,"emoticon":":o"},{"annotation":"脸红","name":"FLUSHED FACE","hexcode":"1F633","shortcodes":["flushed"],"tags":["困惑","害羞","羞涩","脸","茫然","迷茫"],"emoji":"😳","text":"","type":1,"order":74,"group":0,"subgroup":9,"version":0.6,"emoticon":":$"},{"annotation":"恳求的脸","name":"FACE WITH PLEADING EYES","hexcode":"1F97A","shortcodes":["pleading"],"tags":["可怜兮兮的眼神","怜悯","祈求"],"emoji":"🥺","text":"","type":1,"order":75,"group":0,"subgroup":9,"version":11},{"annotation":"啊","name":"FROWNING FACE WITH OPEN MOUTH","hexcode":"1F626","shortcodes":["bored"],"tags":["惊讶","目瞪口呆","脸"],"emoji":"😦","text":"","type":1,"order":76,"group":0,"subgroup":9,"version":1},{"annotation":"极度痛苦","name":"ANGUISHED FACE","hexcode":"1F627","shortcodes":["anguished","wtf"],"tags":["痛","脸","难受"],"emoji":"😧","text":"","type":1,"order":77,"group":0,"subgroup":9,"version":1,"emoticon":":s"},{"annotation":"害怕","name":"FEARFUL FACE","hexcode":"1F628","shortcodes":["fearful"],"tags":["怕","恐怖","恐惧","脸"],"emoji":"😨","text":"","type":1,"order":78,"group":0,"subgroup":9,"version":0.6},{"annotation":"冷汗","name":"FACE WITH OPEN MOUTH AND COLD SWEAT","hexcode":"1F630","shortcodes":["cold_sweat","anxious","frustrated"],"tags":["无语","汗","焦虑","紧张","脸"],"emoji":"😰","text":"","type":1,"order":79,"group":0,"subgroup":9,"version":0.6},{"annotation":"失望但如释重负","name":"DISAPPOINTED BUT RELIEVED FACE","hexcode":"1F625","shortcodes":["hopeful"],"tags":["失望","如释重负","脸"],"emoji":"😥","text":"","type":1,"order":80,"group":0,"subgroup":9,"version":0.6},{"annotation":"哭","name":"CRYING FACE","hexcode":"1F622","shortcodes":["upset","cry"],"tags":["伤心","泪","脸"],"emoji":"😢","text":"","type":1,"order":81,"group":0,"subgroup":9,"version":0.6,"emoticon":":'("},{"annotation":"放声大哭","name":"LOUDLY CRYING FACE","hexcode":"1F62D","shortcodes":["distressed","sob"],"tags":["哭","大哭","泪","痛哭","脸"],"emoji":"😭","text":"","type":1,"order":82,"group":0,"subgroup":9,"version":0.6,"emoticon":":'o"},{"annotation":"吓死了","name":"FACE SCREAMING IN FEAR","hexcode":"1F631","shortcodes":["frightened","scream"],"tags":["吓死","害怕","尖叫","恐怖","脸"],"emoji":"😱","text":"","type":1,"order":83,"group":0,"subgroup":9,"version":0.6,"emoticon":"Dx"},{"annotation":"困惑","name":"CONFOUNDED FACE","hexcode":"1F616","shortcodes":["confounded"],"tags":["焦头烂额","纠结","脸"],"emoji":"😖","text":"","type":1,"order":84,"group":0,"subgroup":9,"version":0.6,"emoticon":"x("},{"annotation":"痛苦","name":"PERSEVERING FACE","hexcode":"1F623","shortcodes":["persevered"],"tags":["忍耐","脸","难受"],"emoji":"😣","text":"","type":1,"order":85,"group":0,"subgroup":9,"version":0.6},{"annotation":"失望","name":"DISAPPOINTED FACE","hexcode":"1F61E","shortcodes":["disappointed"],"tags":["不高兴","脸","难过"],"emoji":"😞","text":"","type":1,"order":86,"group":0,"subgroup":9,"version":0.6},{"annotation":"汗","name":"FACE WITH COLD SWEAT","hexcode":"1F613","shortcodes":["shamed"],"tags":["冷","尴尬","脸"],"emoji":"😓","text":"","type":1,"order":87,"group":0,"subgroup":9,"version":0.6,"emoticon":":<"},{"annotation":"累死了","name":"WEARY FACE","hexcode":"1F629","shortcodes":["weary"],"tags":["疲倦","疲劳","疲惫","累","脸"],"emoji":"😩","text":"","type":1,"order":88,"group":0,"subgroup":9,"version":0.6,"emoticon":"D:"},{"annotation":"累","name":"TIRED FACE","hexcode":"1F62B","shortcodes":["tired"],"tags":["疲倦","疲劳","疲惫","脸"],"emoji":"😫","text":"","type":1,"order":89,"group":0,"subgroup":9,"version":0.6,"emoticon":":c"},{"annotation":"打呵欠","name":"YAWNING FACE","hexcode":"1F971","shortcodes":["yawn"],"tags":["呵欠","哈欠","困","无聊","累"],"emoji":"🥱","text":"","type":1,"order":90,"group":0,"subgroup":9,"version":12},{"annotation":"傲慢","name":"FACE WITH LOOK OF TRIUMPH","hexcode":"1F624","shortcodes":["annoyed","hrmph"],"tags":["胜利","自负","赢","趾高气昂"],"emoji":"😤","text":"","type":1,"order":91,"group":0,"subgroup":10,"version":0.6},{"annotation":"怒火中烧","name":"POUTING FACE","hexcode":"1F621","shortcodes":["enraged","pout"],"tags":["发火","发飙","怒","生气","脸"],"emoji":"😡","text":"","type":1,"order":92,"group":0,"subgroup":10,"version":0.6,"emoticon":">:/"},{"annotation":"生气","name":"ANGRY FACE","hexcode":"1F620","shortcodes":["angry"],"tags":["怒","愤怒","脸"],"emoji":"😠","text":"","type":1,"order":93,"group":0,"subgroup":10,"version":0.6},{"annotation":"嘴上有符号的脸","name":"SERIOUS FACE WITH SYMBOLS COVERING MOUTH","hexcode":"1F92C","shortcodes":["censored"],"tags":["发誓","咒骂","脸"],"emoji":"🤬","text":"","type":1,"order":94,"group":0,"subgroup":10,"version":5,"emoticon":":@"},{"annotation":"恶魔微笑","name":"SMILING FACE WITH HORNS","hexcode":"1F608","shortcodes":["imp"],"tags":["幻想","犄角","神话故事","脸"],"emoji":"😈","text":"","type":1,"order":95,"group":0,"subgroup":10,"version":1,"emoticon":">:)"},{"annotation":"生气的恶魔","name":"IMP","hexcode":"1F47F","shortcodes":["angry_imp"],"tags":["幻想","顽童"],"emoji":"👿","text":"","type":1,"order":96,"group":0,"subgroup":10,"version":0.6,"emoticon":">:("},{"annotation":"头骨","name":"SKULL","hexcode":"1F480","shortcodes":["skull"],"tags":["妖怪","死亡","神话故事","脸"],"emoji":"💀","text":"","type":1,"order":97,"group":0,"subgroup":10,"version":0.6},{"annotation":"骷髅","name":"SKULL AND CROSSBONES","hexcode":"2620","shortcodes":["crossbones"],"tags":["头骨","妖怪","死亡","脸","骨头"],"emoji":"☠️","text":"☠︎","type":0,"order":99,"group":0,"subgroup":10,"version":1},{"annotation":"大便","name":"PILE OF POO","hexcode":"1F4A9","shortcodes":["poop"],"tags":["屎","怪物","粑粑","脸"],"emoji":"💩","text":"","type":1,"order":100,"group":0,"subgroup":11,"version":0.6},{"annotation":"小丑脸","name":"CLOWN FACE","hexcode":"1F921","shortcodes":["clown"],"tags":["小丑","脸"],"emoji":"🤡","text":"","type":1,"order":101,"group":0,"subgroup":11,"version":3},{"annotation":"食人魔","name":"JAPANESE OGRE","hexcode":"1F479","shortcodes":["ogre"],"tags":["妖怪","幻想","神话故事","脸","鬼"],"emoji":"👹","text":"","type":1,"order":102,"group":0,"subgroup":11,"version":0.6,"emoticon":">0)"},{"annotation":"小妖精","name":"JAPANESE GOBLIN","hexcode":"1F47A","shortcodes":["goblin"],"tags":["妖怪","幻想","神话故事","脸"],"emoji":"👺","text":"","type":1,"order":103,"group":0,"subgroup":11,"version":0.6},{"annotation":"鬼","name":"GHOST","hexcode":"1F47B","shortcodes":["ghost"],"tags":["妖怪","幻想","幽灵","神话故事","脸"],"emoji":"👻","text":"","type":1,"order":104,"group":0,"subgroup":11,"version":0.6},{"annotation":"外星人","name":"EXTRATERRESTRIAL ALIEN","hexcode":"1F47D","shortcodes":["alien"],"tags":["ufo","外星","太空","幻想","星际","脸"],"emoji":"👽️","text":"👽︎","type":1,"order":105,"group":0,"subgroup":11,"version":0.6},{"annotation":"外星怪物","name":"ALIEN MONSTER","hexcode":"1F47E","shortcodes":["alien_monster","space_invader"],"tags":["ufo","外星","太空","怪物","星际","脸","飞碟"],"emoji":"👾","text":"","type":1,"order":106,"group":0,"subgroup":11,"version":0.6},{"annotation":"机器人","name":"ROBOT FACE","hexcode":"1F916","shortcodes":["robot"],"tags":["怪物"],"emoji":"🤖","text":"","type":1,"order":107,"group":0,"subgroup":11,"version":1},{"annotation":"大笑的猫","name":"SMILING CAT FACE WITH OPEN MOUTH","hexcode":"1F63A","shortcodes":["smiling_cat"],"tags":["哈哈","猫脸","笑","脸"],"emoji":"😺","text":"","type":1,"order":108,"group":0,"subgroup":12,"version":0.6},{"annotation":"微笑的猫","name":"GRINNING CAT FACE WITH SMILING EYES","hexcode":"1F638","shortcodes":["grinning_cat"],"tags":["呵呵","猫脸","笑","脸"],"emoji":"😸","text":"","type":1,"order":109,"group":0,"subgroup":12,"version":0.6},{"annotation":"笑出眼泪的猫","name":"CAT FACE WITH TEARS OF JOY","hexcode":"1F639","shortcodes":["joyful_cat"],"tags":["喜极而泣","快乐","猫脸","眼泪","脸"],"emoji":"😹","text":"","type":1,"order":110,"group":0,"subgroup":12,"version":0.6},{"annotation":"花痴的猫","name":"SMILING CAT FACE WITH HEART-SHAPED EYES","hexcode":"1F63B","shortcodes":["lovestruck_cat"],"tags":["喜欢","心","猫脸","脸","花痴"],"emoji":"😻","text":"","type":1,"order":111,"group":0,"subgroup":12,"version":0.6},{"annotation":"奸笑的猫","name":"CAT FACE WITH WRY SMILE","hexcode":"1F63C","shortcodes":["smirking_cat"],"tags":["奸笑","猫脸","脸","讽刺"],"emoji":"😼","text":"","type":1,"order":112,"group":0,"subgroup":12,"version":0.6},{"annotation":"亲亲猫","name":"KISSING CAT FACE WITH CLOSED EYES","hexcode":"1F63D","shortcodes":["kissing_cat"],"tags":["亲亲","吻","猫脸","脸"],"emoji":"😽","text":"","type":1,"order":113,"group":0,"subgroup":12,"version":0.6,"emoticon":":3"},{"annotation":"疲倦的猫","name":"WEARY CAT FACE","hexcode":"1F640","shortcodes":["weary_cat"],"tags":["惊讶","猫脸","疲倦","累","脸"],"emoji":"🙀","text":"","type":1,"order":114,"group":0,"subgroup":12,"version":0.6},{"annotation":"哭泣的猫","name":"CRYING CAT FACE","hexcode":"1F63F","shortcodes":["crying_cat"],"tags":["哭","猫脸","眼泪","脸","难过"],"emoji":"😿","text":"","type":1,"order":115,"group":0,"subgroup":12,"version":0.6},{"annotation":"生气的猫","name":"POUTING CAT FACE","hexcode":"1F63E","shortcodes":["pouting_cat"],"tags":["猫脸","生气","脸"],"emoji":"😾","text":"","type":1,"order":116,"group":0,"subgroup":12,"version":0.6},{"annotation":"非礼勿视","name":"SEE-NO-EVIL MONKEY","hexcode":"1F648","shortcodes":["see_no_evil"],"tags":["脸","蒙住眼睛","蒙眼"],"emoji":"🙈","text":"","type":1,"order":117,"group":0,"subgroup":13,"version":0.6},{"annotation":"非礼勿听","name":"HEAR-NO-EVIL MONKEY","hexcode":"1F649","shortcodes":["hear_no_evil"],"tags":["堵上耳朵","堵耳","脸"],"emoji":"🙉","text":"","type":1,"order":118,"group":0,"subgroup":13,"version":0.6},{"annotation":"非礼勿言","name":"SPEAK-NO-EVIL MONKEY","hexcode":"1F64A","shortcodes":["speak_no_evil"],"tags":["捂上嘴巴","捂嘴","脸"],"emoji":"🙊","text":"","type":1,"order":119,"group":0,"subgroup":13,"version":0.6},{"annotation":"唇印","name":"KISS MARK","hexcode":"1F48B","shortcodes":["kiss_lips"],"tags":["吻","唇","浪漫"],"emoji":"💋","text":"","type":1,"order":120,"group":0,"subgroup":14,"version":0.6},{"annotation":"情书","name":"LOVE LETTER","hexcode":"1F48C","shortcodes":["love_letter"],"tags":["信","邮件"],"emoji":"💌","text":"","type":1,"order":121,"group":0,"subgroup":14,"version":0.6},{"annotation":"心中箭了","name":"HEART WITH ARROW","hexcode":"1F498","shortcodes":["cupid"],"tags":["丘比特","浪漫","爱情","箭","红心"],"emoji":"💘","text":"","type":1,"order":122,"group":0,"subgroup":14,"version":0.6},{"annotation":"系有缎带的心","name":"HEART WITH RIBBON","hexcode":"1F49D","shortcodes":["heart_ribbon"],"tags":["爱的礼物","送你一颗心"],"emoji":"💝","text":"","type":1,"order":123,"group":0,"subgroup":14,"version":0.6},{"annotation":"闪亮的心","name":"SPARKLING HEART","hexcode":"1F496","shortcodes":["sparkling_heart"],"tags":["激动","红心","闪亮"],"emoji":"💖","text":"","type":1,"order":124,"group":0,"subgroup":14,"version":0.6},{"annotation":"搏动的心","name":"GROWING HEART","hexcode":"1F497","shortcodes":["heartpulse"],"tags":["搏动","激动","紧张","红心"],"emoji":"💗","text":"","type":1,"order":125,"group":0,"subgroup":14,"version":0.6},{"annotation":"心跳","name":"BEATING HEART","hexcode":"1F493","shortcodes":["heartbeat"],"tags":["心动","爱"],"emoji":"💓","text":"","type":1,"order":126,"group":0,"subgroup":14,"version":0.6},{"annotation":"舞动的心","name":"REVOLVING HEARTS","hexcode":"1F49E","shortcodes":["revolving_hearts"],"tags":["旋转","涌动","跃动"],"emoji":"💞","text":"","type":1,"order":127,"group":0,"subgroup":14,"version":0.6},{"annotation":"两颗心","name":"TWO HEARTS","hexcode":"1F495","shortcodes":["two_hearts"],"tags":["爱情"],"emoji":"💕","text":"","type":1,"order":128,"group":0,"subgroup":14,"version":0.6},{"annotation":"心型装饰","name":"HEART DECORATION","hexcode":"1F49F","shortcodes":["heart_decoration"],"tags":["装饰"],"emoji":"💟","text":"","type":1,"order":129,"group":0,"subgroup":14,"version":0.6},{"annotation":"心叹号","name":"HEAVY HEART EXCLAMATION MARK ORNAMENT","hexcode":"2763","shortcodes":["heart_exclamation"],"tags":["叹号","心动"],"emoji":"❣️","text":"❣︎","type":0,"order":131,"group":0,"subgroup":14,"version":1},{"annotation":"心碎","name":"BROKEN HEART","hexcode":"1F494","shortcodes":["broken_heart"],"tags":["伤心"],"emoji":"💔","text":"","type":1,"order":132,"group":0,"subgroup":14,"version":0.6,"emoticon":"","skins":[{"annotation":"男法师: 较浅肤色","name":"MAGE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D9-1F3FB-200D-2642-FE0F","shortcodes":["man_mage_tone1"],"emoji":"🧙🏻‍♂️","text":"","type":1,"order":1591,"group":1,"subgroup":25,"version":5,"gender":1,"tone":1},{"annotation":"男法师: 中等-浅肤色","name":"MAGE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D9-1F3FC-200D-2642-FE0F","shortcodes":["man_mage_tone2"],"emoji":"🧙🏼‍♂️","text":"","type":1,"order":1593,"group":1,"subgroup":25,"version":5,"gender":1,"tone":2},{"annotation":"男法师: 中等肤色","name":"MAGE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D9-1F3FD-200D-2642-FE0F","shortcodes":["man_mage_tone3"],"emoji":"🧙🏽‍♂️","text":"","type":1,"order":1595,"group":1,"subgroup":25,"version":5,"gender":1,"tone":3},{"annotation":"男法师: 中等-深肤色","name":"MAGE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D9-1F3FE-200D-2642-FE0F","shortcodes":["man_mage_tone4"],"emoji":"🧙🏾‍♂️","text":"","type":1,"order":1597,"group":1,"subgroup":25,"version":5,"gender":1,"tone":4},{"annotation":"男法师: 较深肤色","name":"MAGE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D9-1F3FF-200D-2642-FE0F","shortcodes":["man_mage_tone5"],"emoji":"🧙🏿‍♂️","text":"","type":1,"order":1599,"group":1,"subgroup":25,"version":5,"gender":1,"tone":5}]},{"annotation":"女法师","name":"MAGE, FEMALE SIGN","hexcode":"1F9D9-200D-2640-FE0F","shortcodes":["woman_mage"],"tags":["女巫","女魔术师"],"emoji":"🧙‍♀️","text":"","type":1,"order":1601,"group":1,"subgroup":25,"version":5,"gender":0,"skins":[{"annotation":"女法师: 较浅肤色","name":"MAGE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D9-1F3FB-200D-2640-FE0F","shortcodes":["woman_mage_tone1"],"emoji":"🧙🏻‍♀️","text":"","type":1,"order":1603,"group":1,"subgroup":25,"version":5,"gender":0,"tone":1},{"annotation":"女法师: 中等-浅肤色","name":"MAGE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D9-1F3FC-200D-2640-FE0F","shortcodes":["woman_mage_tone2"],"emoji":"🧙🏼‍♀️","text":"","type":1,"order":1605,"group":1,"subgroup":25,"version":5,"gender":0,"tone":2},{"annotation":"女法师: 中等肤色","name":"MAGE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D9-1F3FD-200D-2640-FE0F","shortcodes":["woman_mage_tone3"],"emoji":"🧙🏽‍♀️","text":"","type":1,"order":1607,"group":1,"subgroup":25,"version":5,"gender":0,"tone":3},{"annotation":"女法师: 中等-深肤色","name":"MAGE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D9-1F3FE-200D-2640-FE0F","shortcodes":["woman_mage_tone4"],"emoji":"🧙🏾‍♀️","text":"","type":1,"order":1609,"group":1,"subgroup":25,"version":5,"gender":0,"tone":4},{"annotation":"女法师: 较深肤色","name":"MAGE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D9-1F3FF-200D-2640-FE0F","shortcodes":["woman_mage_tone5"],"emoji":"🧙🏿‍♀️","text":"","type":1,"order":1611,"group":1,"subgroup":25,"version":5,"gender":0,"tone":5}]},{"annotation":"精灵","name":"FAIRY","hexcode":"1F9DA","shortcodes":["fairy"],"tags":["天卫三","天卫十五","天卫四"],"emoji":"🧚","text":"","type":1,"order":1613,"group":1,"subgroup":25,"version":5,"skins":[{"annotation":"精灵: 较浅肤色","name":"FAIRY, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DA-1F3FB","shortcodes":["fairy_tone1"],"emoji":"🧚🏻","text":"","type":1,"order":1614,"group":1,"subgroup":25,"version":5,"tone":1},{"annotation":"精灵: 中等-浅肤色","name":"FAIRY, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DA-1F3FC","shortcodes":["fairy_tone2"],"emoji":"🧚🏼","text":"","type":1,"order":1615,"group":1,"subgroup":25,"version":5,"tone":2},{"annotation":"精灵: 中等肤色","name":"FAIRY, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DA-1F3FD","shortcodes":["fairy_tone3"],"emoji":"🧚🏽","text":"","type":1,"order":1616,"group":1,"subgroup":25,"version":5,"tone":3},{"annotation":"精灵: 中等-深肤色","name":"FAIRY, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DA-1F3FE","shortcodes":["fairy_tone4"],"emoji":"🧚🏾","text":"","type":1,"order":1617,"group":1,"subgroup":25,"version":5,"tone":4},{"annotation":"精灵: 较深肤色","name":"FAIRY, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DA-1F3FF","shortcodes":["fairy_tone5"],"emoji":"🧚🏿","text":"","type":1,"order":1618,"group":1,"subgroup":25,"version":5,"tone":5}]},{"annotation":"仙人","name":"FAIRY, MALE SIGN","hexcode":"1F9DA-200D-2642-FE0F","shortcodes":["man_fairy"],"tags":["仙男","天卫十五","天卫四","男精灵"],"emoji":"🧚‍♂️","text":"","type":1,"order":1619,"group":1,"subgroup":25,"version":5,"gender":1,"skins":[{"annotation":"仙人: 较浅肤色","name":"FAIRY, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DA-1F3FB-200D-2642-FE0F","shortcodes":["man_fairy_tone1"],"emoji":"🧚🏻‍♂️","text":"","type":1,"order":1621,"group":1,"subgroup":25,"version":5,"gender":1,"tone":1},{"annotation":"仙人: 中等-浅肤色","name":"FAIRY, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DA-1F3FC-200D-2642-FE0F","shortcodes":["man_fairy_tone2"],"emoji":"🧚🏼‍♂️","text":"","type":1,"order":1623,"group":1,"subgroup":25,"version":5,"gender":1,"tone":2},{"annotation":"仙人: 中等肤色","name":"FAIRY, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DA-1F3FD-200D-2642-FE0F","shortcodes":["man_fairy_tone3"],"emoji":"🧚🏽‍♂️","text":"","type":1,"order":1625,"group":1,"subgroup":25,"version":5,"gender":1,"tone":3},{"annotation":"仙人: 中等-深肤色","name":"FAIRY, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DA-1F3FE-200D-2642-FE0F","shortcodes":["man_fairy_tone4"],"emoji":"🧚🏾‍♂️","text":"","type":1,"order":1627,"group":1,"subgroup":25,"version":5,"gender":1,"tone":4},{"annotation":"仙人: 较深肤色","name":"FAIRY, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DA-1F3FF-200D-2642-FE0F","shortcodes":["man_fairy_tone5"],"emoji":"🧚🏿‍♂️","text":"","type":1,"order":1629,"group":1,"subgroup":25,"version":5,"gender":1,"tone":5}]},{"annotation":"仙女","name":"FAIRY, FEMALE SIGN","hexcode":"1F9DA-200D-2640-FE0F","shortcodes":["woman_fairy"],"tags":["女精灵","妖精王后"],"emoji":"🧚‍♀️","text":"","type":1,"order":1631,"group":1,"subgroup":25,"version":5,"gender":0,"skins":[{"annotation":"仙女: 较浅肤色","name":"FAIRY, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DA-1F3FB-200D-2640-FE0F","shortcodes":["woman_fairy_tone1"],"emoji":"🧚🏻‍♀️","text":"","type":1,"order":1633,"group":1,"subgroup":25,"version":5,"gender":0,"tone":1},{"annotation":"仙女: 中等-浅肤色","name":"FAIRY, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DA-1F3FC-200D-2640-FE0F","shortcodes":["woman_fairy_tone2"],"emoji":"🧚🏼‍♀️","text":"","type":1,"order":1635,"group":1,"subgroup":25,"version":5,"gender":0,"tone":2},{"annotation":"仙女: 中等肤色","name":"FAIRY, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DA-1F3FD-200D-2640-FE0F","shortcodes":["woman_fairy_tone3"],"emoji":"🧚🏽‍♀️","text":"","type":1,"order":1637,"group":1,"subgroup":25,"version":5,"gender":0,"tone":3},{"annotation":"仙女: 中等-深肤色","name":"FAIRY, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DA-1F3FE-200D-2640-FE0F","shortcodes":["woman_fairy_tone4"],"emoji":"🧚🏾‍♀️","text":"","type":1,"order":1639,"group":1,"subgroup":25,"version":5,"gender":0,"tone":4},{"annotation":"仙女: 较深肤色","name":"FAIRY, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DA-1F3FF-200D-2640-FE0F","shortcodes":["woman_fairy_tone5"],"emoji":"🧚🏿‍♀️","text":"","type":1,"order":1641,"group":1,"subgroup":25,"version":5,"gender":0,"tone":5}]},{"annotation":"吸血鬼","name":"VAMPIRE","hexcode":"1F9DB","shortcodes":["vampire"],"tags":["不死族"],"emoji":"🧛","text":"","type":1,"order":1643,"group":1,"subgroup":25,"version":5,"emoticon":":E","skins":[{"annotation":"吸血鬼: 较浅肤色","name":"VAMPIRE, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DB-1F3FB","shortcodes":["vampire_tone1"],"emoji":"🧛🏻","text":"","type":1,"order":1644,"group":1,"subgroup":25,"version":5,"tone":1},{"annotation":"吸血鬼: 中等-浅肤色","name":"VAMPIRE, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DB-1F3FC","shortcodes":["vampire_tone2"],"emoji":"🧛🏼","text":"","type":1,"order":1645,"group":1,"subgroup":25,"version":5,"tone":2},{"annotation":"吸血鬼: 中等肤色","name":"VAMPIRE, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DB-1F3FD","shortcodes":["vampire_tone3"],"emoji":"🧛🏽","text":"","type":1,"order":1646,"group":1,"subgroup":25,"version":5,"tone":3},{"annotation":"吸血鬼: 中等-深肤色","name":"VAMPIRE, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DB-1F3FE","shortcodes":["vampire_tone4"],"emoji":"🧛🏾","text":"","type":1,"order":1647,"group":1,"subgroup":25,"version":5,"tone":4},{"annotation":"吸血鬼: 较深肤色","name":"VAMPIRE, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DB-1F3FF","shortcodes":["vampire_tone5"],"emoji":"🧛🏿","text":"","type":1,"order":1648,"group":1,"subgroup":25,"version":5,"tone":5}]},{"annotation":"男吸血鬼","name":"VAMPIRE, MALE SIGN","hexcode":"1F9DB-200D-2642-FE0F","shortcodes":["man_vampire"],"tags":["男不死族"],"emoji":"🧛‍♂️","text":"","type":1,"order":1649,"group":1,"subgroup":25,"version":5,"gender":1,"skins":[{"annotation":"男吸血鬼: 较浅肤色","name":"VAMPIRE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DB-1F3FB-200D-2642-FE0F","shortcodes":["man_vampire_tone1"],"emoji":"🧛🏻‍♂️","text":"","type":1,"order":1651,"group":1,"subgroup":25,"version":5,"gender":1,"tone":1},{"annotation":"男吸血鬼: 中等-浅肤色","name":"VAMPIRE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DB-1F3FC-200D-2642-FE0F","shortcodes":["man_vampire_tone2"],"emoji":"🧛🏼‍♂️","text":"","type":1,"order":1653,"group":1,"subgroup":25,"version":5,"gender":1,"tone":2},{"annotation":"男吸血鬼: 中等肤色","name":"VAMPIRE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DB-1F3FD-200D-2642-FE0F","shortcodes":["man_vampire_tone3"],"emoji":"🧛🏽‍♂️","text":"","type":1,"order":1655,"group":1,"subgroup":25,"version":5,"gender":1,"tone":3},{"annotation":"男吸血鬼: 中等-深肤色","name":"VAMPIRE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DB-1F3FE-200D-2642-FE0F","shortcodes":["man_vampire_tone4"],"emoji":"🧛🏾‍♂️","text":"","type":1,"order":1657,"group":1,"subgroup":25,"version":5,"gender":1,"tone":4},{"annotation":"男吸血鬼: 较深肤色","name":"VAMPIRE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DB-1F3FF-200D-2642-FE0F","shortcodes":["man_vampire_tone5"],"emoji":"🧛🏿‍♂️","text":"","type":1,"order":1659,"group":1,"subgroup":25,"version":5,"gender":1,"tone":5}]},{"annotation":"女吸血鬼","name":"VAMPIRE, FEMALE SIGN","hexcode":"1F9DB-200D-2640-FE0F","shortcodes":["woman_vampire"],"tags":["女不死族"],"emoji":"🧛‍♀️","text":"","type":1,"order":1661,"group":1,"subgroup":25,"version":5,"gender":0,"skins":[{"annotation":"女吸血鬼: 较浅肤色","name":"VAMPIRE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DB-1F3FB-200D-2640-FE0F","shortcodes":["woman_vampire_tone1"],"emoji":"🧛🏻‍♀️","text":"","type":1,"order":1663,"group":1,"subgroup":25,"version":5,"gender":0,"tone":1},{"annotation":"女吸血鬼: 中等-浅肤色","name":"VAMPIRE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DB-1F3FC-200D-2640-FE0F","shortcodes":["woman_vampire_tone2"],"emoji":"🧛🏼‍♀️","text":"","type":1,"order":1665,"group":1,"subgroup":25,"version":5,"gender":0,"tone":2},{"annotation":"女吸血鬼: 中等肤色","name":"VAMPIRE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DB-1F3FD-200D-2640-FE0F","shortcodes":["woman_vampire_tone3"],"emoji":"🧛🏽‍♀️","text":"","type":1,"order":1667,"group":1,"subgroup":25,"version":5,"gender":0,"tone":3},{"annotation":"女吸血鬼: 中等-深肤色","name":"VAMPIRE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DB-1F3FE-200D-2640-FE0F","shortcodes":["woman_vampire_tone4"],"emoji":"🧛🏾‍♀️","text":"","type":1,"order":1669,"group":1,"subgroup":25,"version":5,"gender":0,"tone":4},{"annotation":"女吸血鬼: 较深肤色","name":"VAMPIRE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DB-1F3FF-200D-2640-FE0F","shortcodes":["woman_vampire_tone5"],"emoji":"🧛🏿‍♀️","text":"","type":1,"order":1671,"group":1,"subgroup":25,"version":5,"gender":0,"tone":5}]},{"annotation":"人鱼","name":"MERPERSON","hexcode":"1F9DC","shortcodes":["merperson"],"tags":["女人鱼","男人鱼","美人鱼"],"emoji":"🧜","text":"","type":1,"order":1673,"group":1,"subgroup":25,"version":5,"skins":[{"annotation":"人鱼: 较浅肤色","name":"MERPERSON, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DC-1F3FB","shortcodes":["merperson_tone1"],"emoji":"🧜🏻","text":"","type":1,"order":1674,"group":1,"subgroup":25,"version":5,"tone":1},{"annotation":"人鱼: 中等-浅肤色","name":"MERPERSON, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DC-1F3FC","shortcodes":["merperson_tone2"],"emoji":"🧜🏼","text":"","type":1,"order":1675,"group":1,"subgroup":25,"version":5,"tone":2},{"annotation":"人鱼: 中等肤色","name":"MERPERSON, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DC-1F3FD","shortcodes":["merperson_tone3"],"emoji":"🧜🏽","text":"","type":1,"order":1676,"group":1,"subgroup":25,"version":5,"tone":3},{"annotation":"人鱼: 中等-深肤色","name":"MERPERSON, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DC-1F3FE","shortcodes":["merperson_tone4"],"emoji":"🧜🏾","text":"","type":1,"order":1677,"group":1,"subgroup":25,"version":5,"tone":4},{"annotation":"人鱼: 较深肤色","name":"MERPERSON, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DC-1F3FF","shortcodes":["merperson_tone5"],"emoji":"🧜🏿","text":"","type":1,"order":1678,"group":1,"subgroup":25,"version":5,"tone":5}]},{"annotation":"男人鱼","name":"MERPERSON, MALE SIGN","hexcode":"1F9DC-200D-2642-FE0F","shortcodes":["merman"],"tags":["特里同"],"emoji":"🧜‍♂️","text":"","type":1,"order":1679,"group":1,"subgroup":25,"version":5,"gender":1,"skins":[{"annotation":"男人鱼: 较浅肤色","name":"MERPERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DC-1F3FB-200D-2642-FE0F","shortcodes":["merman_tone1"],"emoji":"🧜🏻‍♂️","text":"","type":1,"order":1681,"group":1,"subgroup":25,"version":5,"gender":1,"tone":1},{"annotation":"男人鱼: 中等-浅肤色","name":"MERPERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DC-1F3FC-200D-2642-FE0F","shortcodes":["merman_tone2"],"emoji":"🧜🏼‍♂️","text":"","type":1,"order":1683,"group":1,"subgroup":25,"version":5,"gender":1,"tone":2},{"annotation":"男人鱼: 中等肤色","name":"MERPERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DC-1F3FD-200D-2642-FE0F","shortcodes":["merman_tone3"],"emoji":"🧜🏽‍♂️","text":"","type":1,"order":1685,"group":1,"subgroup":25,"version":5,"gender":1,"tone":3},{"annotation":"男人鱼: 中等-深肤色","name":"MERPERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DC-1F3FE-200D-2642-FE0F","shortcodes":["merman_tone4"],"emoji":"🧜🏾‍♂️","text":"","type":1,"order":1687,"group":1,"subgroup":25,"version":5,"gender":1,"tone":4},{"annotation":"男人鱼: 较深肤色","name":"MERPERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DC-1F3FF-200D-2642-FE0F","shortcodes":["merman_tone5"],"emoji":"🧜🏿‍♂️","text":"","type":1,"order":1689,"group":1,"subgroup":25,"version":5,"gender":1,"tone":5}]},{"annotation":"美人鱼","name":"MERPERSON, FEMALE SIGN","hexcode":"1F9DC-200D-2640-FE0F","shortcodes":["mermaid"],"tags":["女人鱼"],"emoji":"🧜‍♀️","text":"","type":1,"order":1691,"group":1,"subgroup":25,"version":5,"gender":0,"skins":[{"annotation":"美人鱼: 较浅肤色","name":"MERPERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DC-1F3FB-200D-2640-FE0F","shortcodes":["mermaid_tone1"],"emoji":"🧜🏻‍♀️","text":"","type":1,"order":1693,"group":1,"subgroup":25,"version":5,"gender":0,"tone":1},{"annotation":"美人鱼: 中等-浅肤色","name":"MERPERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DC-1F3FC-200D-2640-FE0F","shortcodes":["mermaid_tone2"],"emoji":"🧜🏼‍♀️","text":"","type":1,"order":1695,"group":1,"subgroup":25,"version":5,"gender":0,"tone":2},{"annotation":"美人鱼: 中等肤色","name":"MERPERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DC-1F3FD-200D-2640-FE0F","shortcodes":["mermaid_tone3"],"emoji":"🧜🏽‍♀️","text":"","type":1,"order":1697,"group":1,"subgroup":25,"version":5,"gender":0,"tone":3},{"annotation":"美人鱼: 中等-深肤色","name":"MERPERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DC-1F3FE-200D-2640-FE0F","shortcodes":["mermaid_tone4"],"emoji":"🧜🏾‍♀️","text":"","type":1,"order":1699,"group":1,"subgroup":25,"version":5,"gender":0,"tone":4},{"annotation":"美人鱼: 较深肤色","name":"MERPERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DC-1F3FF-200D-2640-FE0F","shortcodes":["mermaid_tone5"],"emoji":"🧜🏿‍♀️","text":"","type":1,"order":1701,"group":1,"subgroup":25,"version":5,"gender":0,"tone":5}]},{"annotation":"小精灵","name":"ELF","hexcode":"1F9DD","shortcodes":["elf"],"tags":["魔术"],"emoji":"🧝","text":"","type":1,"order":1703,"group":1,"subgroup":25,"version":5,"skins":[{"annotation":"小精灵: 较浅肤色","name":"ELF, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DD-1F3FB","shortcodes":["elf_tone1"],"emoji":"🧝🏻","text":"","type":1,"order":1704,"group":1,"subgroup":25,"version":5,"tone":1},{"annotation":"小精灵: 中等-浅肤色","name":"ELF, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DD-1F3FC","shortcodes":["elf_tone2"],"emoji":"🧝🏼","text":"","type":1,"order":1705,"group":1,"subgroup":25,"version":5,"tone":2},{"annotation":"小精灵: 中等肤色","name":"ELF, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DD-1F3FD","shortcodes":["elf_tone3"],"emoji":"🧝🏽","text":"","type":1,"order":1706,"group":1,"subgroup":25,"version":5,"tone":3},{"annotation":"小精灵: 中等-深肤色","name":"ELF, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DD-1F3FE","shortcodes":["elf_tone4"],"emoji":"🧝🏾","text":"","type":1,"order":1707,"group":1,"subgroup":25,"version":5,"tone":4},{"annotation":"小精灵: 较深肤色","name":"ELF, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DD-1F3FF","shortcodes":["elf_tone5"],"emoji":"🧝🏿","text":"","type":1,"order":1708,"group":1,"subgroup":25,"version":5,"tone":5}]},{"annotation":"男小精灵","name":"ELF, MALE SIGN","hexcode":"1F9DD-200D-2642-FE0F","shortcodes":["man_elf"],"tags":["男性魔术"],"emoji":"🧝‍♂️","text":"","type":1,"order":1709,"group":1,"subgroup":25,"version":5,"gender":1,"skins":[{"annotation":"男小精灵: 较浅肤色","name":"ELF, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DD-1F3FB-200D-2642-FE0F","shortcodes":["man_elf_tone1"],"emoji":"🧝🏻‍♂️","text":"","type":1,"order":1711,"group":1,"subgroup":25,"version":5,"gender":1,"tone":1},{"annotation":"男小精灵: 中等-浅肤色","name":"ELF, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DD-1F3FC-200D-2642-FE0F","shortcodes":["man_elf_tone2"],"emoji":"🧝🏼‍♂️","text":"","type":1,"order":1713,"group":1,"subgroup":25,"version":5,"gender":1,"tone":2},{"annotation":"男小精灵: 中等肤色","name":"ELF, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DD-1F3FD-200D-2642-FE0F","shortcodes":["man_elf_tone3"],"emoji":"🧝🏽‍♂️","text":"","type":1,"order":1715,"group":1,"subgroup":25,"version":5,"gender":1,"tone":3},{"annotation":"男小精灵: 中等-深肤色","name":"ELF, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DD-1F3FE-200D-2642-FE0F","shortcodes":["man_elf_tone4"],"emoji":"🧝🏾‍♂️","text":"","type":1,"order":1717,"group":1,"subgroup":25,"version":5,"gender":1,"tone":4},{"annotation":"男小精灵: 较深肤色","name":"ELF, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DD-1F3FF-200D-2642-FE0F","shortcodes":["man_elf_tone5"],"emoji":"🧝🏿‍♂️","text":"","type":1,"order":1719,"group":1,"subgroup":25,"version":5,"gender":1,"tone":5}]},{"annotation":"女小精灵","name":"ELF, FEMALE SIGN","hexcode":"1F9DD-200D-2640-FE0F","shortcodes":["woman_elf"],"tags":["女性魔术"],"emoji":"🧝‍♀️","text":"","type":1,"order":1721,"group":1,"subgroup":25,"version":5,"gender":0,"skins":[{"annotation":"女小精灵: 较浅肤色","name":"ELF, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9DD-1F3FB-200D-2640-FE0F","shortcodes":["woman_elf_tone1"],"emoji":"🧝🏻‍♀️","text":"","type":1,"order":1723,"group":1,"subgroup":25,"version":5,"gender":0,"tone":1},{"annotation":"女小精灵: 中等-浅肤色","name":"ELF, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9DD-1F3FC-200D-2640-FE0F","shortcodes":["woman_elf_tone2"],"emoji":"🧝🏼‍♀️","text":"","type":1,"order":1725,"group":1,"subgroup":25,"version":5,"gender":0,"tone":2},{"annotation":"女小精灵: 中等肤色","name":"ELF, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9DD-1F3FD-200D-2640-FE0F","shortcodes":["woman_elf_tone3"],"emoji":"🧝🏽‍♀️","text":"","type":1,"order":1727,"group":1,"subgroup":25,"version":5,"gender":0,"tone":3},{"annotation":"女小精灵: 中等-深肤色","name":"ELF, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9DD-1F3FE-200D-2640-FE0F","shortcodes":["woman_elf_tone4"],"emoji":"🧝🏾‍♀️","text":"","type":1,"order":1729,"group":1,"subgroup":25,"version":5,"gender":0,"tone":4},{"annotation":"女小精灵: 较深肤色","name":"ELF, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9DD-1F3FF-200D-2640-FE0F","shortcodes":["woman_elf_tone5"],"emoji":"🧝🏿‍♀️","text":"","type":1,"order":1731,"group":1,"subgroup":25,"version":5,"gender":0,"tone":5}]},{"annotation":"妖怪","name":"GENIE","hexcode":"1F9DE","shortcodes":["genie"],"tags":["神灵"],"emoji":"🧞","text":"","type":1,"order":1733,"group":1,"subgroup":25,"version":5},{"annotation":"男妖怪","name":"GENIE, MALE SIGN","hexcode":"1F9DE-200D-2642-FE0F","shortcodes":["man_genie"],"tags":["男神灵"],"emoji":"🧞‍♂️","text":"","type":1,"order":1734,"group":1,"subgroup":25,"version":5,"gender":1},{"annotation":"女妖怪","name":"GENIE, FEMALE SIGN","hexcode":"1F9DE-200D-2640-FE0F","shortcodes":["woman_genie"],"tags":["女神灵"],"emoji":"🧞‍♀️","text":"","type":1,"order":1736,"group":1,"subgroup":25,"version":5,"gender":0},{"annotation":"僵尸","name":"ZOMBIE","hexcode":"1F9DF","shortcodes":["zombie"],"tags":["不死族","行尸走肉"],"emoji":"🧟","text":"","type":1,"order":1738,"group":1,"subgroup":25,"version":5,"emoticon":"8#"},{"annotation":"男僵尸","name":"ZOMBIE, MALE SIGN","hexcode":"1F9DF-200D-2642-FE0F","shortcodes":["man_zombie"],"tags":["男行尸走肉"],"emoji":"🧟‍♂️","text":"","type":1,"order":1739,"group":1,"subgroup":25,"version":5,"gender":1},{"annotation":"女僵尸","name":"ZOMBIE, FEMALE SIGN","hexcode":"1F9DF-200D-2640-FE0F","shortcodes":["woman_zombie"],"tags":["女行尸走肉"],"emoji":"🧟‍♀️","text":"","type":1,"order":1741,"group":1,"subgroup":25,"version":5,"gender":0},{"annotation":"按摩","name":"FACE MASSAGE","hexcode":"1F486","shortcodes":["person_getting_massage"],"tags":["美容"],"emoji":"💆","text":"","type":1,"order":1743,"group":1,"subgroup":26,"version":0.6,"skins":[{"annotation":"按摩: 较浅肤色","name":"FACE MASSAGE, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F486-1F3FB","shortcodes":["person_getting_massage_tone1"],"emoji":"💆🏻","text":"","type":1,"order":1744,"group":1,"subgroup":26,"version":1,"tone":1},{"annotation":"按摩: 中等-浅肤色","name":"FACE MASSAGE, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F486-1F3FC","shortcodes":["person_getting_massage_tone2"],"emoji":"💆🏼","text":"","type":1,"order":1745,"group":1,"subgroup":26,"version":1,"tone":2},{"annotation":"按摩: 中等肤色","name":"FACE MASSAGE, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F486-1F3FD","shortcodes":["person_getting_massage_tone3"],"emoji":"💆🏽","text":"","type":1,"order":1746,"group":1,"subgroup":26,"version":1,"tone":3},{"annotation":"按摩: 中等-深肤色","name":"FACE MASSAGE, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F486-1F3FE","shortcodes":["person_getting_massage_tone4"],"emoji":"💆🏾","text":"","type":1,"order":1747,"group":1,"subgroup":26,"version":1,"tone":4},{"annotation":"按摩: 较深肤色","name":"FACE MASSAGE, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F486-1F3FF","shortcodes":["person_getting_massage_tone5"],"emoji":"💆🏿","text":"","type":1,"order":1748,"group":1,"subgroup":26,"version":1,"tone":5}]},{"annotation":"男生按摩","name":"FACE MASSAGE, MALE SIGN","hexcode":"1F486-200D-2642-FE0F","shortcodes":["man_getting_face_massage"],"tags":["按摩","男"],"emoji":"💆‍♂️","text":"","type":1,"order":1749,"group":1,"subgroup":26,"version":4,"gender":1,"skins":[{"annotation":"男生按摩: 较浅肤色","name":"FACE MASSAGE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F486-1F3FB-200D-2642-FE0F","shortcodes":["man_getting_face_massage_tone1"],"emoji":"💆🏻‍♂️","text":"","type":1,"order":1751,"group":1,"subgroup":26,"version":4,"gender":1,"tone":1},{"annotation":"男生按摩: 中等-浅肤色","name":"FACE MASSAGE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F486-1F3FC-200D-2642-FE0F","shortcodes":["man_getting_face_massage_tone2"],"emoji":"💆🏼‍♂️","text":"","type":1,"order":1753,"group":1,"subgroup":26,"version":4,"gender":1,"tone":2},{"annotation":"男生按摩: 中等肤色","name":"FACE MASSAGE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F486-1F3FD-200D-2642-FE0F","shortcodes":["man_getting_face_massage_tone3"],"emoji":"💆🏽‍♂️","text":"","type":1,"order":1755,"group":1,"subgroup":26,"version":4,"gender":1,"tone":3},{"annotation":"男生按摩: 中等-深肤色","name":"FACE MASSAGE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F486-1F3FE-200D-2642-FE0F","shortcodes":["man_getting_face_massage_tone4"],"emoji":"💆🏾‍♂️","text":"","type":1,"order":1757,"group":1,"subgroup":26,"version":4,"gender":1,"tone":4},{"annotation":"男生按摩: 较深肤色","name":"FACE MASSAGE, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F486-1F3FF-200D-2642-FE0F","shortcodes":["man_getting_face_massage_tone5"],"emoji":"💆🏿‍♂️","text":"","type":1,"order":1759,"group":1,"subgroup":26,"version":4,"gender":1,"tone":5}]},{"annotation":"女生按摩","name":"FACE MASSAGE, FEMALE SIGN","hexcode":"1F486-200D-2640-FE0F","shortcodes":["woman_getting_face_massage"],"tags":["女","按摩"],"emoji":"💆‍♀️","text":"","type":1,"order":1761,"group":1,"subgroup":26,"version":4,"gender":0,"skins":[{"annotation":"女生按摩: 较浅肤色","name":"FACE MASSAGE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F486-1F3FB-200D-2640-FE0F","shortcodes":["woman_getting_face_massage_tone1"],"emoji":"💆🏻‍♀️","text":"","type":1,"order":1763,"group":1,"subgroup":26,"version":4,"gender":0,"tone":1},{"annotation":"女生按摩: 中等-浅肤色","name":"FACE MASSAGE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F486-1F3FC-200D-2640-FE0F","shortcodes":["woman_getting_face_massage_tone2"],"emoji":"💆🏼‍♀️","text":"","type":1,"order":1765,"group":1,"subgroup":26,"version":4,"gender":0,"tone":2},{"annotation":"女生按摩: 中等肤色","name":"FACE MASSAGE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F486-1F3FD-200D-2640-FE0F","shortcodes":["woman_getting_face_massage_tone3"],"emoji":"💆🏽‍♀️","text":"","type":1,"order":1767,"group":1,"subgroup":26,"version":4,"gender":0,"tone":3},{"annotation":"女生按摩: 中等-深肤色","name":"FACE MASSAGE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F486-1F3FE-200D-2640-FE0F","shortcodes":["woman_getting_face_massage_tone4"],"emoji":"💆🏾‍♀️","text":"","type":1,"order":1769,"group":1,"subgroup":26,"version":4,"gender":0,"tone":4},{"annotation":"女生按摩: 较深肤色","name":"FACE MASSAGE, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F486-1F3FF-200D-2640-FE0F","shortcodes":["woman_getting_face_massage_tone5"],"emoji":"💆🏿‍♀️","text":"","type":1,"order":1771,"group":1,"subgroup":26,"version":4,"gender":0,"tone":5}]},{"annotation":"理发","name":"HAIRCUT","hexcode":"1F487","shortcodes":["person_getting_haircut"],"tags":["剪头"],"emoji":"💇","text":"","type":1,"order":1773,"group":1,"subgroup":26,"version":0.6,"skins":[{"annotation":"理发: 较浅肤色","name":"HAIRCUT, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F487-1F3FB","shortcodes":["person_getting_haircut_tone1"],"emoji":"💇🏻","text":"","type":1,"order":1774,"group":1,"subgroup":26,"version":1,"tone":1},{"annotation":"理发: 中等-浅肤色","name":"HAIRCUT, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F487-1F3FC","shortcodes":["person_getting_haircut_tone2"],"emoji":"💇🏼","text":"","type":1,"order":1775,"group":1,"subgroup":26,"version":1,"tone":2},{"annotation":"理发: 中等肤色","name":"HAIRCUT, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F487-1F3FD","shortcodes":["person_getting_haircut_tone3"],"emoji":"💇🏽","text":"","type":1,"order":1776,"group":1,"subgroup":26,"version":1,"tone":3},{"annotation":"理发: 中等-深肤色","name":"HAIRCUT, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F487-1F3FE","shortcodes":["person_getting_haircut_tone4"],"emoji":"💇🏾","text":"","type":1,"order":1777,"group":1,"subgroup":26,"version":1,"tone":4},{"annotation":"理发: 较深肤色","name":"HAIRCUT, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F487-1F3FF","shortcodes":["person_getting_haircut_tone5"],"emoji":"💇🏿","text":"","type":1,"order":1778,"group":1,"subgroup":26,"version":1,"tone":5}]},{"annotation":"男生理发","name":"HAIRCUT, MALE SIGN","hexcode":"1F487-200D-2642-FE0F","shortcodes":["man_getting_haircut"],"tags":["剪头","理发","男"],"emoji":"💇‍♂️","text":"","type":1,"order":1779,"group":1,"subgroup":26,"version":4,"gender":1,"skins":[{"annotation":"男生理发: 较浅肤色","name":"HAIRCUT, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F487-1F3FB-200D-2642-FE0F","shortcodes":["man_getting_haircut_tone1"],"emoji":"💇🏻‍♂️","text":"","type":1,"order":1781,"group":1,"subgroup":26,"version":4,"gender":1,"tone":1},{"annotation":"男生理发: 中等-浅肤色","name":"HAIRCUT, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F487-1F3FC-200D-2642-FE0F","shortcodes":["man_getting_haircut_tone2"],"emoji":"💇🏼‍♂️","text":"","type":1,"order":1783,"group":1,"subgroup":26,"version":4,"gender":1,"tone":2},{"annotation":"男生理发: 中等肤色","name":"HAIRCUT, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F487-1F3FD-200D-2642-FE0F","shortcodes":["man_getting_haircut_tone3"],"emoji":"💇🏽‍♂️","text":"","type":1,"order":1785,"group":1,"subgroup":26,"version":4,"gender":1,"tone":3},{"annotation":"男生理发: 中等-深肤色","name":"HAIRCUT, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F487-1F3FE-200D-2642-FE0F","shortcodes":["man_getting_haircut_tone4"],"emoji":"💇🏾‍♂️","text":"","type":1,"order":1787,"group":1,"subgroup":26,"version":4,"gender":1,"tone":4},{"annotation":"男生理发: 较深肤色","name":"HAIRCUT, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F487-1F3FF-200D-2642-FE0F","shortcodes":["man_getting_haircut_tone5"],"emoji":"💇🏿‍♂️","text":"","type":1,"order":1789,"group":1,"subgroup":26,"version":4,"gender":1,"tone":5}]},{"annotation":"女生理发","name":"HAIRCUT, FEMALE SIGN","hexcode":"1F487-200D-2640-FE0F","shortcodes":["woman_getting_haircut"],"tags":["剪头","女","理发"],"emoji":"💇‍♀️","text":"","type":1,"order":1791,"group":1,"subgroup":26,"version":4,"gender":0,"skins":[{"annotation":"女生理发: 较浅肤色","name":"HAIRCUT, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F487-1F3FB-200D-2640-FE0F","shortcodes":["woman_getting_haircut_tone1"],"emoji":"💇🏻‍♀️","text":"","type":1,"order":1793,"group":1,"subgroup":26,"version":4,"gender":0,"tone":1},{"annotation":"女生理发: 中等-浅肤色","name":"HAIRCUT, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F487-1F3FC-200D-2640-FE0F","shortcodes":["woman_getting_haircut_tone2"],"emoji":"💇🏼‍♀️","text":"","type":1,"order":1795,"group":1,"subgroup":26,"version":4,"gender":0,"tone":2},{"annotation":"女生理发: 中等肤色","name":"HAIRCUT, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F487-1F3FD-200D-2640-FE0F","shortcodes":["woman_getting_haircut_tone3"],"emoji":"💇🏽‍♀️","text":"","type":1,"order":1797,"group":1,"subgroup":26,"version":4,"gender":0,"tone":3},{"annotation":"女生理发: 中等-深肤色","name":"HAIRCUT, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F487-1F3FE-200D-2640-FE0F","shortcodes":["woman_getting_haircut_tone4"],"emoji":"💇🏾‍♀️","text":"","type":1,"order":1799,"group":1,"subgroup":26,"version":4,"gender":0,"tone":4},{"annotation":"女生理发: 较深肤色","name":"HAIRCUT, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F487-1F3FF-200D-2640-FE0F","shortcodes":["woman_getting_haircut_tone5"],"emoji":"💇🏿‍♀️","text":"","type":1,"order":1801,"group":1,"subgroup":26,"version":4,"gender":0,"tone":5}]},{"annotation":"行人","name":"PEDESTRIAN","hexcode":"1F6B6","shortcodes":["person_walking"],"tags":["徒步","走路"],"emoji":"🚶","text":"","type":1,"order":1803,"group":1,"subgroup":26,"version":0.6,"skins":[{"annotation":"行人: 较浅肤色","name":"PEDESTRIAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6B6-1F3FB","shortcodes":["person_walking_tone1"],"emoji":"🚶🏻","text":"","type":1,"order":1804,"group":1,"subgroup":26,"version":1,"tone":1},{"annotation":"行人: 中等-浅肤色","name":"PEDESTRIAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6B6-1F3FC","shortcodes":["person_walking_tone2"],"emoji":"🚶🏼","text":"","type":1,"order":1805,"group":1,"subgroup":26,"version":1,"tone":2},{"annotation":"行人: 中等肤色","name":"PEDESTRIAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6B6-1F3FD","shortcodes":["person_walking_tone3"],"emoji":"🚶🏽","text":"","type":1,"order":1806,"group":1,"subgroup":26,"version":1,"tone":3},{"annotation":"行人: 中等-深肤色","name":"PEDESTRIAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6B6-1F3FE","shortcodes":["person_walking_tone4"],"emoji":"🚶🏾","text":"","type":1,"order":1807,"group":1,"subgroup":26,"version":1,"tone":4},{"annotation":"行人: 较深肤色","name":"PEDESTRIAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6B6-1F3FF","shortcodes":["person_walking_tone5"],"emoji":"🚶🏿","text":"","type":1,"order":1808,"group":1,"subgroup":26,"version":1,"tone":5}]},{"annotation":"男行人","name":"PEDESTRIAN, MALE SIGN","hexcode":"1F6B6-200D-2642-FE0F","shortcodes":["man_walking"],"tags":["徒步","男","走路"],"emoji":"🚶‍♂️","text":"","type":1,"order":1809,"group":1,"subgroup":26,"version":4,"gender":1,"skins":[{"annotation":"男行人: 较浅肤色","name":"PEDESTRIAN, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6B6-1F3FB-200D-2642-FE0F","shortcodes":["man_walking_tone1"],"emoji":"🚶🏻‍♂️","text":"","type":1,"order":1811,"group":1,"subgroup":26,"version":4,"gender":1,"tone":1},{"annotation":"男行人: 中等-浅肤色","name":"PEDESTRIAN, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6B6-1F3FC-200D-2642-FE0F","shortcodes":["man_walking_tone2"],"emoji":"🚶🏼‍♂️","text":"","type":1,"order":1813,"group":1,"subgroup":26,"version":4,"gender":1,"tone":2},{"annotation":"男行人: 中等肤色","name":"PEDESTRIAN, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6B6-1F3FD-200D-2642-FE0F","shortcodes":["man_walking_tone3"],"emoji":"🚶🏽‍♂️","text":"","type":1,"order":1815,"group":1,"subgroup":26,"version":4,"gender":1,"tone":3},{"annotation":"男行人: 中等-深肤色","name":"PEDESTRIAN, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6B6-1F3FE-200D-2642-FE0F","shortcodes":["man_walking_tone4"],"emoji":"🚶🏾‍♂️","text":"","type":1,"order":1817,"group":1,"subgroup":26,"version":4,"gender":1,"tone":4},{"annotation":"男行人: 较深肤色","name":"PEDESTRIAN, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6B6-1F3FF-200D-2642-FE0F","shortcodes":["man_walking_tone5"],"emoji":"🚶🏿‍♂️","text":"","type":1,"order":1819,"group":1,"subgroup":26,"version":4,"gender":1,"tone":5}]},{"annotation":"女行人","name":"PEDESTRIAN, FEMALE SIGN","hexcode":"1F6B6-200D-2640-FE0F","shortcodes":["woman_walking"],"tags":["女","徒步","走路"],"emoji":"🚶‍♀️","text":"","type":1,"order":1821,"group":1,"subgroup":26,"version":4,"gender":0,"skins":[{"annotation":"女行人: 较浅肤色","name":"PEDESTRIAN, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6B6-1F3FB-200D-2640-FE0F","shortcodes":["woman_walking_tone1"],"emoji":"🚶🏻‍♀️","text":"","type":1,"order":1823,"group":1,"subgroup":26,"version":4,"gender":0,"tone":1},{"annotation":"女行人: 中等-浅肤色","name":"PEDESTRIAN, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6B6-1F3FC-200D-2640-FE0F","shortcodes":["woman_walking_tone2"],"emoji":"🚶🏼‍♀️","text":"","type":1,"order":1825,"group":1,"subgroup":26,"version":4,"gender":0,"tone":2},{"annotation":"女行人: 中等肤色","name":"PEDESTRIAN, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6B6-1F3FD-200D-2640-FE0F","shortcodes":["woman_walking_tone3"],"emoji":"🚶🏽‍♀️","text":"","type":1,"order":1827,"group":1,"subgroup":26,"version":4,"gender":0,"tone":3},{"annotation":"女行人: 中等-深肤色","name":"PEDESTRIAN, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6B6-1F3FE-200D-2640-FE0F","shortcodes":["woman_walking_tone4"],"emoji":"🚶🏾‍♀️","text":"","type":1,"order":1829,"group":1,"subgroup":26,"version":4,"gender":0,"tone":4},{"annotation":"女行人: 较深肤色","name":"PEDESTRIAN, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6B6-1F3FF-200D-2640-FE0F","shortcodes":["woman_walking_tone5"],"emoji":"🚶🏿‍♀️","text":"","type":1,"order":1831,"group":1,"subgroup":26,"version":4,"gender":0,"tone":5}]},{"annotation":"站立者","name":"STANDING PERSON","hexcode":"1F9CD","shortcodes":["person_standing"],"tags":["站着","站立"],"emoji":"🧍","text":"","type":1,"order":1833,"group":1,"subgroup":26,"version":12,"skins":[{"annotation":"站立者: 较浅肤色","name":"STANDING PERSON, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9CD-1F3FB","shortcodes":["person_standing_tone1"],"emoji":"🧍🏻","text":"","type":1,"order":1834,"group":1,"subgroup":26,"version":12,"tone":1},{"annotation":"站立者: 中等-浅肤色","name":"STANDING PERSON, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9CD-1F3FC","shortcodes":["person_standing_tone2"],"emoji":"🧍🏼","text":"","type":1,"order":1835,"group":1,"subgroup":26,"version":12,"tone":2},{"annotation":"站立者: 中等肤色","name":"STANDING PERSON, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9CD-1F3FD","shortcodes":["person_standing_tone3"],"emoji":"🧍🏽","text":"","type":1,"order":1836,"group":1,"subgroup":26,"version":12,"tone":3},{"annotation":"站立者: 中等-深肤色","name":"STANDING PERSON, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9CD-1F3FE","shortcodes":["person_standing_tone4"],"emoji":"🧍🏾","text":"","type":1,"order":1837,"group":1,"subgroup":26,"version":12,"tone":4},{"annotation":"站立者: 较深肤色","name":"STANDING PERSON, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9CD-1F3FF","shortcodes":["person_standing_tone5"],"emoji":"🧍🏿","text":"","type":1,"order":1838,"group":1,"subgroup":26,"version":12,"tone":5}]},{"annotation":"站立的男人","name":"STANDING PERSON, MALE SIGN","hexcode":"1F9CD-200D-2642-FE0F","shortcodes":["man_standing"],"tags":["男","站着","站立"],"emoji":"🧍‍♂️","text":"","type":1,"order":1839,"group":1,"subgroup":26,"version":12,"gender":1,"skins":[{"annotation":"站立的男人: 较浅肤色","name":"STANDING PERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9CD-1F3FB-200D-2642-FE0F","shortcodes":["man_standing_tone1"],"emoji":"🧍🏻‍♂️","text":"","type":1,"order":1841,"group":1,"subgroup":26,"version":12,"gender":1,"tone":1},{"annotation":"站立的男人: 中等-浅肤色","name":"STANDING PERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9CD-1F3FC-200D-2642-FE0F","shortcodes":["man_standing_tone2"],"emoji":"🧍🏼‍♂️","text":"","type":1,"order":1843,"group":1,"subgroup":26,"version":12,"gender":1,"tone":2},{"annotation":"站立的男人: 中等肤色","name":"STANDING PERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9CD-1F3FD-200D-2642-FE0F","shortcodes":["man_standing_tone3"],"emoji":"🧍🏽‍♂️","text":"","type":1,"order":1845,"group":1,"subgroup":26,"version":12,"gender":1,"tone":3},{"annotation":"站立的男人: 中等-深肤色","name":"STANDING PERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9CD-1F3FE-200D-2642-FE0F","shortcodes":["man_standing_tone4"],"emoji":"🧍🏾‍♂️","text":"","type":1,"order":1847,"group":1,"subgroup":26,"version":12,"gender":1,"tone":4},{"annotation":"站立的男人: 较深肤色","name":"STANDING PERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9CD-1F3FF-200D-2642-FE0F","shortcodes":["man_standing_tone5"],"emoji":"🧍🏿‍♂️","text":"","type":1,"order":1849,"group":1,"subgroup":26,"version":12,"gender":1,"tone":5}]},{"annotation":"站立的女人","name":"STANDING PERSON, FEMALE SIGN","hexcode":"1F9CD-200D-2640-FE0F","shortcodes":["woman_standing"],"tags":["女","站着","站立"],"emoji":"🧍‍♀️","text":"","type":1,"order":1851,"group":1,"subgroup":26,"version":12,"gender":0,"skins":[{"annotation":"站立的女人: 较浅肤色","name":"STANDING PERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9CD-1F3FB-200D-2640-FE0F","shortcodes":["woman_standing_tone1"],"emoji":"🧍🏻‍♀️","text":"","type":1,"order":1853,"group":1,"subgroup":26,"version":12,"gender":0,"tone":1},{"annotation":"站立的女人: 中等-浅肤色","name":"STANDING PERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9CD-1F3FC-200D-2640-FE0F","shortcodes":["woman_standing_tone2"],"emoji":"🧍🏼‍♀️","text":"","type":1,"order":1855,"group":1,"subgroup":26,"version":12,"gender":0,"tone":2},{"annotation":"站立的女人: 中等肤色","name":"STANDING PERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9CD-1F3FD-200D-2640-FE0F","shortcodes":["woman_standing_tone3"],"emoji":"🧍🏽‍♀️","text":"","type":1,"order":1857,"group":1,"subgroup":26,"version":12,"gender":0,"tone":3},{"annotation":"站立的女人: 中等-深肤色","name":"STANDING PERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9CD-1F3FE-200D-2640-FE0F","shortcodes":["woman_standing_tone4"],"emoji":"🧍🏾‍♀️","text":"","type":1,"order":1859,"group":1,"subgroup":26,"version":12,"gender":0,"tone":4},{"annotation":"站立的女人: 较深肤色","name":"STANDING PERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9CD-1F3FF-200D-2640-FE0F","shortcodes":["woman_standing_tone5"],"emoji":"🧍🏿‍♀️","text":"","type":1,"order":1861,"group":1,"subgroup":26,"version":12,"gender":0,"tone":5}]},{"annotation":"下跪者","name":"KNEELING PERSON","hexcode":"1F9CE","shortcodes":["person_kneeling"],"tags":["跪下","跪坐"],"emoji":"🧎","text":"","type":1,"order":1863,"group":1,"subgroup":26,"version":12,"skins":[{"annotation":"下跪者: 较浅肤色","name":"KNEELING PERSON, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9CE-1F3FB","shortcodes":["person_kneeling_tone1"],"emoji":"🧎🏻","text":"","type":1,"order":1864,"group":1,"subgroup":26,"version":12,"tone":1},{"annotation":"下跪者: 中等-浅肤色","name":"KNEELING PERSON, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9CE-1F3FC","shortcodes":["person_kneeling_tone2"],"emoji":"🧎🏼","text":"","type":1,"order":1865,"group":1,"subgroup":26,"version":12,"tone":2},{"annotation":"下跪者: 中等肤色","name":"KNEELING PERSON, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9CE-1F3FD","shortcodes":["person_kneeling_tone3"],"emoji":"🧎🏽","text":"","type":1,"order":1866,"group":1,"subgroup":26,"version":12,"tone":3},{"annotation":"下跪者: 中等-深肤色","name":"KNEELING PERSON, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9CE-1F3FE","shortcodes":["person_kneeling_tone4"],"emoji":"🧎🏾","text":"","type":1,"order":1867,"group":1,"subgroup":26,"version":12,"tone":4},{"annotation":"下跪者: 较深肤色","name":"KNEELING PERSON, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9CE-1F3FF","shortcodes":["person_kneeling_tone5"],"emoji":"🧎🏿","text":"","type":1,"order":1868,"group":1,"subgroup":26,"version":12,"tone":5}]},{"annotation":"跪下的男人","name":"KNEELING PERSON, MALE SIGN","hexcode":"1F9CE-200D-2642-FE0F","shortcodes":["man_kneeling"],"tags":["下跪","男","跪坐"],"emoji":"🧎‍♂️","text":"","type":1,"order":1869,"group":1,"subgroup":26,"version":12,"gender":1,"skins":[{"annotation":"跪下的男人: 较浅肤色","name":"KNEELING PERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9CE-1F3FB-200D-2642-FE0F","shortcodes":["man_kneeling_tone1"],"emoji":"🧎🏻‍♂️","text":"","type":1,"order":1871,"group":1,"subgroup":26,"version":12,"gender":1,"tone":1},{"annotation":"跪下的男人: 中等-浅肤色","name":"KNEELING PERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9CE-1F3FC-200D-2642-FE0F","shortcodes":["man_kneeling_tone2"],"emoji":"🧎🏼‍♂️","text":"","type":1,"order":1873,"group":1,"subgroup":26,"version":12,"gender":1,"tone":2},{"annotation":"跪下的男人: 中等肤色","name":"KNEELING PERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9CE-1F3FD-200D-2642-FE0F","shortcodes":["man_kneeling_tone3"],"emoji":"🧎🏽‍♂️","text":"","type":1,"order":1875,"group":1,"subgroup":26,"version":12,"gender":1,"tone":3},{"annotation":"跪下的男人: 中等-深肤色","name":"KNEELING PERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9CE-1F3FE-200D-2642-FE0F","shortcodes":["man_kneeling_tone4"],"emoji":"🧎🏾‍♂️","text":"","type":1,"order":1877,"group":1,"subgroup":26,"version":12,"gender":1,"tone":4},{"annotation":"跪下的男人: 较深肤色","name":"KNEELING PERSON, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9CE-1F3FF-200D-2642-FE0F","shortcodes":["man_kneeling_tone5"],"emoji":"🧎🏿‍♂️","text":"","type":1,"order":1879,"group":1,"subgroup":26,"version":12,"gender":1,"tone":5}]},{"annotation":"跪下的女人","name":"KNEELING PERSON, FEMALE SIGN","hexcode":"1F9CE-200D-2640-FE0F","shortcodes":["woman_kneeling"],"tags":["下跪","女","跪坐"],"emoji":"🧎‍♀️","text":"","type":1,"order":1881,"group":1,"subgroup":26,"version":12,"gender":0,"skins":[{"annotation":"跪下的女人: 较浅肤色","name":"KNEELING PERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9CE-1F3FB-200D-2640-FE0F","shortcodes":["woman_kneeling_tone1"],"emoji":"🧎🏻‍♀️","text":"","type":1,"order":1883,"group":1,"subgroup":26,"version":12,"gender":0,"tone":1},{"annotation":"跪下的女人: 中等-浅肤色","name":"KNEELING PERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9CE-1F3FC-200D-2640-FE0F","shortcodes":["woman_kneeling_tone2"],"emoji":"🧎🏼‍♀️","text":"","type":1,"order":1885,"group":1,"subgroup":26,"version":12,"gender":0,"tone":2},{"annotation":"跪下的女人: 中等肤色","name":"KNEELING PERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9CE-1F3FD-200D-2640-FE0F","shortcodes":["woman_kneeling_tone3"],"emoji":"🧎🏽‍♀️","text":"","type":1,"order":1887,"group":1,"subgroup":26,"version":12,"gender":0,"tone":3},{"annotation":"跪下的女人: 中等-深肤色","name":"KNEELING PERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9CE-1F3FE-200D-2640-FE0F","shortcodes":["woman_kneeling_tone4"],"emoji":"🧎🏾‍♀️","text":"","type":1,"order":1889,"group":1,"subgroup":26,"version":12,"gender":0,"tone":4},{"annotation":"跪下的女人: 较深肤色","name":"KNEELING PERSON, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9CE-1F3FF-200D-2640-FE0F","shortcodes":["woman_kneeling_tone5"],"emoji":"🧎🏿‍♀️","text":"","type":1,"order":1891,"group":1,"subgroup":26,"version":12,"gender":0,"tone":5}]},{"annotation":"拄盲杖的人","name":"ADULT, PROBING CANE","hexcode":"1F9D1-200D-1F9AF","shortcodes":["person_probing_cane"],"tags":["失明的","实用性"],"emoji":"🧑‍🦯","text":"","type":1,"order":1893,"group":1,"subgroup":26,"version":12.1,"skins":[{"annotation":"拄盲杖的人: 较浅肤色","name":"ADULT, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D1-1F3FB-200D-1F9AF","shortcodes":["person_probing_cane_tone1"],"emoji":"🧑🏻‍🦯","text":"","type":1,"order":1894,"group":1,"subgroup":26,"version":12.1,"tone":1},{"annotation":"拄盲杖的人: 中等-浅肤色","name":"ADULT, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D1-1F3FC-200D-1F9AF","shortcodes":["person_probing_cane_tone2"],"emoji":"🧑🏼‍🦯","text":"","type":1,"order":1895,"group":1,"subgroup":26,"version":12.1,"tone":2},{"annotation":"拄盲杖的人: 中等肤色","name":"ADULT, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D1-1F3FD-200D-1F9AF","shortcodes":["person_probing_cane_tone3"],"emoji":"🧑🏽‍🦯","text":"","type":1,"order":1896,"group":1,"subgroup":26,"version":12.1,"tone":3},{"annotation":"拄盲杖的人: 中等-深肤色","name":"ADULT, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D1-1F3FE-200D-1F9AF","shortcodes":["person_probing_cane_tone4"],"emoji":"🧑🏾‍🦯","text":"","type":1,"order":1897,"group":1,"subgroup":26,"version":12.1,"tone":4},{"annotation":"拄盲杖的人: 较深肤色","name":"ADULT, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D1-1F3FF-200D-1F9AF","shortcodes":["person_probing_cane_tone5"],"emoji":"🧑🏿‍🦯","text":"","type":1,"order":1898,"group":1,"subgroup":26,"version":12.1,"tone":5}]},{"annotation":"拄盲杖的男人","name":"MAN, PROBING CANE","hexcode":"1F468-200D-1F9AF","shortcodes":["man_probing_cane"],"tags":["拐杖","无障碍","男","盲"],"emoji":"👨‍🦯","text":"","type":1,"order":1899,"group":1,"subgroup":26,"version":12,"skins":[{"annotation":"拄盲杖的男人: 较浅肤色","name":"MAN, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F468-1F3FB-200D-1F9AF","shortcodes":["man_probing_cane_tone1"],"emoji":"👨🏻‍🦯","text":"","type":1,"order":1900,"group":1,"subgroup":26,"version":12,"tone":1},{"annotation":"拄盲杖的男人: 中等-浅肤色","name":"MAN, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F468-1F3FC-200D-1F9AF","shortcodes":["man_probing_cane_tone2"],"emoji":"👨🏼‍🦯","text":"","type":1,"order":1901,"group":1,"subgroup":26,"version":12,"tone":2},{"annotation":"拄盲杖的男人: 中等肤色","name":"MAN, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F468-1F3FD-200D-1F9AF","shortcodes":["man_probing_cane_tone3"],"emoji":"👨🏽‍🦯","text":"","type":1,"order":1902,"group":1,"subgroup":26,"version":12,"tone":3},{"annotation":"拄盲杖的男人: 中等-深肤色","name":"MAN, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F468-1F3FE-200D-1F9AF","shortcodes":["man_probing_cane_tone4"],"emoji":"👨🏾‍🦯","text":"","type":1,"order":1903,"group":1,"subgroup":26,"version":12,"tone":4},{"annotation":"拄盲杖的男人: 较深肤色","name":"MAN, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F468-1F3FF-200D-1F9AF","shortcodes":["man_probing_cane_tone5"],"emoji":"👨🏿‍🦯","text":"","type":1,"order":1904,"group":1,"subgroup":26,"version":12,"tone":5}]},{"annotation":"拄盲杖的女人","name":"WOMAN, PROBING CANE","hexcode":"1F469-200D-1F9AF","shortcodes":["woman_probing_cane"],"tags":["女","拐杖","无障碍","盲"],"emoji":"👩‍🦯","text":"","type":1,"order":1905,"group":1,"subgroup":26,"version":12,"skins":[{"annotation":"拄盲杖的女人: 较浅肤色","name":"WOMAN, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FB-200D-1F9AF","shortcodes":["woman_probing_cane_tone1"],"emoji":"👩🏻‍🦯","text":"","type":1,"order":1906,"group":1,"subgroup":26,"version":12,"tone":1},{"annotation":"拄盲杖的女人: 中等-浅肤色","name":"WOMAN, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FC-200D-1F9AF","shortcodes":["woman_probing_cane_tone2"],"emoji":"👩🏼‍🦯","text":"","type":1,"order":1907,"group":1,"subgroup":26,"version":12,"tone":2},{"annotation":"拄盲杖的女人: 中等肤色","name":"WOMAN, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FD-200D-1F9AF","shortcodes":["woman_probing_cane_tone3"],"emoji":"👩🏽‍🦯","text":"","type":1,"order":1908,"group":1,"subgroup":26,"version":12,"tone":3},{"annotation":"拄盲杖的女人: 中等-深肤色","name":"WOMAN, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FE-200D-1F9AF","shortcodes":["woman_probing_cane_tone4"],"emoji":"👩🏾‍🦯","text":"","type":1,"order":1909,"group":1,"subgroup":26,"version":12,"tone":4},{"annotation":"拄盲杖的女人: 较深肤色","name":"WOMAN, PROBING CANE, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FF-200D-1F9AF","shortcodes":["woman_probing_cane_tone5"],"emoji":"👩🏿‍🦯","text":"","type":1,"order":1910,"group":1,"subgroup":26,"version":12,"tone":5}]},{"annotation":"坐电动轮椅的人","name":"ADULT, MOTORIZED WHEELCHAIR","hexcode":"1F9D1-200D-1F9BC","shortcodes":["person_motor_wheelchair"],"tags":["可访问性","轮椅"],"emoji":"🧑‍🦼","text":"","type":1,"order":1911,"group":1,"subgroup":26,"version":12.1,"skins":[{"annotation":"坐电动轮椅的人: 较浅肤色","name":"ADULT, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D1-1F3FB-200D-1F9BC","shortcodes":["person_motor_wheelchair_tone1"],"emoji":"🧑🏻‍🦼","text":"","type":1,"order":1912,"group":1,"subgroup":26,"version":12.1,"tone":1},{"annotation":"坐电动轮椅的人: 中等-浅肤色","name":"ADULT, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D1-1F3FC-200D-1F9BC","shortcodes":["person_motor_wheelchair_tone2"],"emoji":"🧑🏼‍🦼","text":"","type":1,"order":1913,"group":1,"subgroup":26,"version":12.1,"tone":2},{"annotation":"坐电动轮椅的人: 中等肤色","name":"ADULT, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D1-1F3FD-200D-1F9BC","shortcodes":["person_motor_wheelchair_tone3"],"emoji":"🧑🏽‍🦼","text":"","type":1,"order":1914,"group":1,"subgroup":26,"version":12.1,"tone":3},{"annotation":"坐电动轮椅的人: 中等-深肤色","name":"ADULT, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D1-1F3FE-200D-1F9BC","shortcodes":["person_motor_wheelchair_tone4"],"emoji":"🧑🏾‍🦼","text":"","type":1,"order":1915,"group":1,"subgroup":26,"version":12.1,"tone":4},{"annotation":"坐电动轮椅的人: 较深肤色","name":"ADULT, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D1-1F3FF-200D-1F9BC","shortcodes":["person_motor_wheelchair_tone5"],"emoji":"🧑🏿‍🦼","text":"","type":1,"order":1916,"group":1,"subgroup":26,"version":12.1,"tone":5}]},{"annotation":"坐电动轮椅的男人","name":"MAN, MOTORIZED WHEELCHAIR","hexcode":"1F468-200D-1F9BC","shortcodes":["man_motor_wheelchair"],"tags":["无障碍","电动","男","轮椅"],"emoji":"👨‍🦼","text":"","type":1,"order":1917,"group":1,"subgroup":26,"version":12,"skins":[{"annotation":"坐电动轮椅的男人: 较浅肤色","name":"MAN, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F468-1F3FB-200D-1F9BC","shortcodes":["man_motor_wheelchair_tone1"],"emoji":"👨🏻‍🦼","text":"","type":1,"order":1918,"group":1,"subgroup":26,"version":12,"tone":1},{"annotation":"坐电动轮椅的男人: 中等-浅肤色","name":"MAN, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F468-1F3FC-200D-1F9BC","shortcodes":["man_motor_wheelchair_tone2"],"emoji":"👨🏼‍🦼","text":"","type":1,"order":1919,"group":1,"subgroup":26,"version":12,"tone":2},{"annotation":"坐电动轮椅的男人: 中等肤色","name":"MAN, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F468-1F3FD-200D-1F9BC","shortcodes":["man_motor_wheelchair_tone3"],"emoji":"👨🏽‍🦼","text":"","type":1,"order":1920,"group":1,"subgroup":26,"version":12,"tone":3},{"annotation":"坐电动轮椅的男人: 中等-深肤色","name":"MAN, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F468-1F3FE-200D-1F9BC","shortcodes":["man_motor_wheelchair_tone4"],"emoji":"👨🏾‍🦼","text":"","type":1,"order":1921,"group":1,"subgroup":26,"version":12,"tone":4},{"annotation":"坐电动轮椅的男人: 较深肤色","name":"MAN, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F468-1F3FF-200D-1F9BC","shortcodes":["man_motor_wheelchair_tone5"],"emoji":"👨🏿‍🦼","text":"","type":1,"order":1922,"group":1,"subgroup":26,"version":12,"tone":5}]},{"annotation":"坐电动轮椅的女人","name":"WOMAN, MOTORIZED WHEELCHAIR","hexcode":"1F469-200D-1F9BC","shortcodes":["woman_motor_wheelchair"],"tags":["女","无障碍","电动","轮椅"],"emoji":"👩‍🦼","text":"","type":1,"order":1923,"group":1,"subgroup":26,"version":12,"skins":[{"annotation":"坐电动轮椅的女人: 较浅肤色","name":"WOMAN, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FB-200D-1F9BC","shortcodes":["woman_motor_wheelchair_tone1"],"emoji":"👩🏻‍🦼","text":"","type":1,"order":1924,"group":1,"subgroup":26,"version":12,"tone":1},{"annotation":"坐电动轮椅的女人: 中等-浅肤色","name":"WOMAN, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FC-200D-1F9BC","shortcodes":["woman_motor_wheelchair_tone2"],"emoji":"👩🏼‍🦼","text":"","type":1,"order":1925,"group":1,"subgroup":26,"version":12,"tone":2},{"annotation":"坐电动轮椅的女人: 中等肤色","name":"WOMAN, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FD-200D-1F9BC","shortcodes":["woman_motor_wheelchair_tone3"],"emoji":"👩🏽‍🦼","text":"","type":1,"order":1926,"group":1,"subgroup":26,"version":12,"tone":3},{"annotation":"坐电动轮椅的女人: 中等-深肤色","name":"WOMAN, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FE-200D-1F9BC","shortcodes":["woman_motor_wheelchair_tone4"],"emoji":"👩🏾‍🦼","text":"","type":1,"order":1927,"group":1,"subgroup":26,"version":12,"tone":4},{"annotation":"坐电动轮椅的女人: 较深肤色","name":"WOMAN, MOTORIZED WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FF-200D-1F9BC","shortcodes":["woman_motor_wheelchair_tone5"],"emoji":"👩🏿‍🦼","text":"","type":1,"order":1928,"group":1,"subgroup":26,"version":12,"tone":5}]},{"annotation":"坐手动轮椅的人","name":"ADULT, MANUAL WHEELCHAIR","hexcode":"1F9D1-200D-1F9BD","shortcodes":["person_wheelchair"],"tags":["可访问性","轮椅"],"emoji":"🧑‍🦽","text":"","type":1,"order":1929,"group":1,"subgroup":26,"version":12.1,"skins":[{"annotation":"坐手动轮椅的人: 较浅肤色","name":"ADULT, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D1-1F3FB-200D-1F9BD","shortcodes":["person_wheelchair_tone1"],"emoji":"🧑🏻‍🦽","text":"","type":1,"order":1930,"group":1,"subgroup":26,"version":12.1,"tone":1},{"annotation":"坐手动轮椅的人: 中等-浅肤色","name":"ADULT, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D1-1F3FC-200D-1F9BD","shortcodes":["person_wheelchair_tone2"],"emoji":"🧑🏼‍🦽","text":"","type":1,"order":1931,"group":1,"subgroup":26,"version":12.1,"tone":2},{"annotation":"坐手动轮椅的人: 中等肤色","name":"ADULT, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D1-1F3FD-200D-1F9BD","shortcodes":["person_wheelchair_tone3"],"emoji":"🧑🏽‍🦽","text":"","type":1,"order":1932,"group":1,"subgroup":26,"version":12.1,"tone":3},{"annotation":"坐手动轮椅的人: 中等-深肤色","name":"ADULT, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D1-1F3FE-200D-1F9BD","shortcodes":["person_wheelchair_tone4"],"emoji":"🧑🏾‍🦽","text":"","type":1,"order":1933,"group":1,"subgroup":26,"version":12.1,"tone":4},{"annotation":"坐手动轮椅的人: 较深肤色","name":"ADULT, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D1-1F3FF-200D-1F9BD","shortcodes":["person_wheelchair_tone5"],"emoji":"🧑🏿‍🦽","text":"","type":1,"order":1934,"group":1,"subgroup":26,"version":12.1,"tone":5}]},{"annotation":"坐手动轮椅的男人","name":"MAN, MANUAL WHEELCHAIR","hexcode":"1F468-200D-1F9BD","shortcodes":["man_wheelchair"],"tags":["手动","无障碍","男","轮椅"],"emoji":"👨‍🦽","text":"","type":1,"order":1935,"group":1,"subgroup":26,"version":12,"skins":[{"annotation":"坐手动轮椅的男人: 较浅肤色","name":"MAN, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F468-1F3FB-200D-1F9BD","shortcodes":["man_wheelchair_tone1"],"emoji":"👨🏻‍🦽","text":"","type":1,"order":1936,"group":1,"subgroup":26,"version":12,"tone":1},{"annotation":"坐手动轮椅的男人: 中等-浅肤色","name":"MAN, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F468-1F3FC-200D-1F9BD","shortcodes":["man_wheelchair_tone2"],"emoji":"👨🏼‍🦽","text":"","type":1,"order":1937,"group":1,"subgroup":26,"version":12,"tone":2},{"annotation":"坐手动轮椅的男人: 中等肤色","name":"MAN, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F468-1F3FD-200D-1F9BD","shortcodes":["man_wheelchair_tone3"],"emoji":"👨🏽‍🦽","text":"","type":1,"order":1938,"group":1,"subgroup":26,"version":12,"tone":3},{"annotation":"坐手动轮椅的男人: 中等-深肤色","name":"MAN, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F468-1F3FE-200D-1F9BD","shortcodes":["man_wheelchair_tone4"],"emoji":"👨🏾‍🦽","text":"","type":1,"order":1939,"group":1,"subgroup":26,"version":12,"tone":4},{"annotation":"坐手动轮椅的男人: 较深肤色","name":"MAN, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F468-1F3FF-200D-1F9BD","shortcodes":["man_wheelchair_tone5"],"emoji":"👨🏿‍🦽","text":"","type":1,"order":1940,"group":1,"subgroup":26,"version":12,"tone":5}]},{"annotation":"坐手动轮椅的女人","name":"WOMAN, MANUAL WHEELCHAIR","hexcode":"1F469-200D-1F9BD","shortcodes":["woman_wheelchair"],"tags":["女","手动","无障碍","轮椅"],"emoji":"👩‍🦽","text":"","type":1,"order":1941,"group":1,"subgroup":26,"version":12,"skins":[{"annotation":"坐手动轮椅的女人: 较浅肤色","name":"WOMAN, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FB-200D-1F9BD","shortcodes":["woman_wheelchair_tone1"],"emoji":"👩🏻‍🦽","text":"","type":1,"order":1942,"group":1,"subgroup":26,"version":12,"tone":1},{"annotation":"坐手动轮椅的女人: 中等-浅肤色","name":"WOMAN, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FC-200D-1F9BD","shortcodes":["woman_wheelchair_tone2"],"emoji":"👩🏼‍🦽","text":"","type":1,"order":1943,"group":1,"subgroup":26,"version":12,"tone":2},{"annotation":"坐手动轮椅的女人: 中等肤色","name":"WOMAN, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FD-200D-1F9BD","shortcodes":["woman_wheelchair_tone3"],"emoji":"👩🏽‍🦽","text":"","type":1,"order":1944,"group":1,"subgroup":26,"version":12,"tone":3},{"annotation":"坐手动轮椅的女人: 中等-深肤色","name":"WOMAN, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FE-200D-1F9BD","shortcodes":["woman_wheelchair_tone4"],"emoji":"👩🏾‍🦽","text":"","type":1,"order":1945,"group":1,"subgroup":26,"version":12,"tone":4},{"annotation":"坐手动轮椅的女人: 较深肤色","name":"WOMAN, MANUAL WHEELCHAIR, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FF-200D-1F9BD","shortcodes":["woman_wheelchair_tone5"],"emoji":"👩🏿‍🦽","text":"","type":1,"order":1946,"group":1,"subgroup":26,"version":12,"tone":5}]},{"annotation":"跑步者","name":"RUNNER","hexcode":"1F3C3","shortcodes":["person_running"],"tags":["跑步","马拉松"],"emoji":"🏃","text":"","type":1,"order":1947,"group":1,"subgroup":26,"version":0.6,"skins":[{"annotation":"跑步者: 较浅肤色","name":"RUNNER, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3C3-1F3FB","shortcodes":["person_running_tone1"],"emoji":"🏃🏻","text":"","type":1,"order":1948,"group":1,"subgroup":26,"version":1,"tone":1},{"annotation":"跑步者: 中等-浅肤色","name":"RUNNER, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3C3-1F3FC","shortcodes":["person_running_tone2"],"emoji":"🏃🏼","text":"","type":1,"order":1949,"group":1,"subgroup":26,"version":1,"tone":2},{"annotation":"跑步者: 中等肤色","name":"RUNNER, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3C3-1F3FD","shortcodes":["person_running_tone3"],"emoji":"🏃🏽","text":"","type":1,"order":1950,"group":1,"subgroup":26,"version":1,"tone":3},{"annotation":"跑步者: 中等-深肤色","name":"RUNNER, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3C3-1F3FE","shortcodes":["person_running_tone4"],"emoji":"🏃🏾","text":"","type":1,"order":1951,"group":1,"subgroup":26,"version":1,"tone":4},{"annotation":"跑步者: 较深肤色","name":"RUNNER, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3C3-1F3FF","shortcodes":["person_running_tone5"],"emoji":"🏃🏿","text":"","type":1,"order":1952,"group":1,"subgroup":26,"version":1,"tone":5}]},{"annotation":"男生跑步","name":"RUNNER, MALE SIGN","hexcode":"1F3C3-200D-2642-FE0F","shortcodes":["man_running"],"tags":["男","跑","马拉松"],"emoji":"🏃‍♂️","text":"","type":1,"order":1953,"group":1,"subgroup":26,"version":4,"gender":1,"skins":[{"annotation":"男生跑步: 较浅肤色","name":"RUNNER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3C3-1F3FB-200D-2642-FE0F","shortcodes":["man_running_tone1"],"emoji":"🏃🏻‍♂️","text":"","type":1,"order":1955,"group":1,"subgroup":26,"version":4,"gender":1,"tone":1},{"annotation":"男生跑步: 中等-浅肤色","name":"RUNNER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3C3-1F3FC-200D-2642-FE0F","shortcodes":["man_running_tone2"],"emoji":"🏃🏼‍♂️","text":"","type":1,"order":1957,"group":1,"subgroup":26,"version":4,"gender":1,"tone":2},{"annotation":"男生跑步: 中等肤色","name":"RUNNER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3C3-1F3FD-200D-2642-FE0F","shortcodes":["man_running_tone3"],"emoji":"🏃🏽‍♂️","text":"","type":1,"order":1959,"group":1,"subgroup":26,"version":4,"gender":1,"tone":3},{"annotation":"男生跑步: 中等-深肤色","name":"RUNNER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3C3-1F3FE-200D-2642-FE0F","shortcodes":["man_running_tone4"],"emoji":"🏃🏾‍♂️","text":"","type":1,"order":1961,"group":1,"subgroup":26,"version":4,"gender":1,"tone":4},{"annotation":"男生跑步: 较深肤色","name":"RUNNER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3C3-1F3FF-200D-2642-FE0F","shortcodes":["man_running_tone5"],"emoji":"🏃🏿‍♂️","text":"","type":1,"order":1963,"group":1,"subgroup":26,"version":4,"gender":1,"tone":5}]},{"annotation":"女生跑步","name":"RUNNER, FEMALE SIGN","hexcode":"1F3C3-200D-2640-FE0F","shortcodes":["woman_running"],"tags":["女","比赛","跑步","马拉松"],"emoji":"🏃‍♀️","text":"","type":1,"order":1965,"group":1,"subgroup":26,"version":4,"gender":0,"skins":[{"annotation":"女生跑步: 较浅肤色","name":"RUNNER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3C3-1F3FB-200D-2640-FE0F","shortcodes":["woman_running_tone1"],"emoji":"🏃🏻‍♀️","text":"","type":1,"order":1967,"group":1,"subgroup":26,"version":4,"gender":0,"tone":1},{"annotation":"女生跑步: 中等-浅肤色","name":"RUNNER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3C3-1F3FC-200D-2640-FE0F","shortcodes":["woman_running_tone2"],"emoji":"🏃🏼‍♀️","text":"","type":1,"order":1969,"group":1,"subgroup":26,"version":4,"gender":0,"tone":2},{"annotation":"女生跑步: 中等肤色","name":"RUNNER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3C3-1F3FD-200D-2640-FE0F","shortcodes":["woman_running_tone3"],"emoji":"🏃🏽‍♀️","text":"","type":1,"order":1971,"group":1,"subgroup":26,"version":4,"gender":0,"tone":3},{"annotation":"女生跑步: 中等-深肤色","name":"RUNNER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3C3-1F3FE-200D-2640-FE0F","shortcodes":["woman_running_tone4"],"emoji":"🏃🏾‍♀️","text":"","type":1,"order":1973,"group":1,"subgroup":26,"version":4,"gender":0,"tone":4},{"annotation":"女生跑步: 较深肤色","name":"RUNNER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3C3-1F3FF-200D-2640-FE0F","shortcodes":["woman_running_tone5"],"emoji":"🏃🏿‍♀️","text":"","type":1,"order":1975,"group":1,"subgroup":26,"version":4,"gender":0,"tone":5}]},{"annotation":"跳舞的女人","name":"DANCER","hexcode":"1F483","shortcodes":["dancer","woman_dancing"],"tags":["女人","跳舞"],"emoji":"💃","text":"","type":1,"order":1977,"group":1,"subgroup":26,"version":0.6,"skins":[{"annotation":"跳舞的女人: 较浅肤色","name":"DANCER, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F483-1F3FB","shortcodes":["dancer_tone1","woman_dancing_tone1"],"emoji":"💃🏻","text":"","type":1,"order":1978,"group":1,"subgroup":26,"version":1,"tone":1},{"annotation":"跳舞的女人: 中等-浅肤色","name":"DANCER, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F483-1F3FC","shortcodes":["dancer_tone2","woman_dancing_tone2"],"emoji":"💃🏼","text":"","type":1,"order":1979,"group":1,"subgroup":26,"version":1,"tone":2},{"annotation":"跳舞的女人: 中等肤色","name":"DANCER, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F483-1F3FD","shortcodes":["dancer_tone3","woman_dancing_tone3"],"emoji":"💃🏽","text":"","type":1,"order":1980,"group":1,"subgroup":26,"version":1,"tone":3},{"annotation":"跳舞的女人: 中等-深肤色","name":"DANCER, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F483-1F3FE","shortcodes":["dancer_tone4","woman_dancing_tone4"],"emoji":"💃🏾","text":"","type":1,"order":1981,"group":1,"subgroup":26,"version":1,"tone":4},{"annotation":"跳舞的女人: 较深肤色","name":"DANCER, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F483-1F3FF","shortcodes":["dancer_tone5","woman_dancing_tone5"],"emoji":"💃🏿","text":"","type":1,"order":1982,"group":1,"subgroup":26,"version":1,"tone":5}]},{"annotation":"跳舞的男人","name":"MAN DANCING","hexcode":"1F57A","shortcodes":["man_dancing"],"tags":["男人","跳舞"],"emoji":"🕺","text":"","type":1,"order":1983,"group":1,"subgroup":26,"version":3,"skins":[{"annotation":"跳舞的男人: 较浅肤色","name":"MAN DANCING, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F57A-1F3FB","shortcodes":["man_dancing_tone1"],"emoji":"🕺🏻","text":"","type":1,"order":1984,"group":1,"subgroup":26,"version":3,"tone":1},{"annotation":"跳舞的男人: 中等-浅肤色","name":"MAN DANCING, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F57A-1F3FC","shortcodes":["man_dancing_tone2"],"emoji":"🕺🏼","text":"","type":1,"order":1985,"group":1,"subgroup":26,"version":3,"tone":2},{"annotation":"跳舞的男人: 中等肤色","name":"MAN DANCING, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F57A-1F3FD","shortcodes":["man_dancing_tone3"],"emoji":"🕺🏽","text":"","type":1,"order":1986,"group":1,"subgroup":26,"version":3,"tone":3},{"annotation":"跳舞的男人: 中等-深肤色","name":"MAN DANCING, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F57A-1F3FE","shortcodes":["man_dancing_tone4"],"emoji":"🕺🏾","text":"","type":1,"order":1987,"group":1,"subgroup":26,"version":3,"tone":4},{"annotation":"跳舞的男人: 较深肤色","name":"MAN DANCING, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F57A-1F3FF","shortcodes":["man_dancing_tone5"],"emoji":"🕺🏿","text":"","type":1,"order":1988,"group":1,"subgroup":26,"version":3,"tone":5}]},{"annotation":"西装革履的人","name":"MAN IN BUSINESS SUIT LEVITATING","hexcode":"1F574","shortcodes":["levitate"],"tags":["商务","正装","西装革履"],"emoji":"🕴️","text":"🕴︎","type":0,"order":1990,"group":1,"subgroup":26,"version":0.7,"skins":[{"annotation":"西装革履的人: 较浅肤色","name":"MAN IN BUSINESS SUIT LEVITATING, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F574-1F3FB","shortcodes":["levitate_tone1"],"emoji":"🕴🏻","text":"","type":1,"order":1991,"group":1,"subgroup":26,"version":4,"tone":1},{"annotation":"西装革履的人: 中等-浅肤色","name":"MAN IN BUSINESS SUIT LEVITATING, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F574-1F3FC","shortcodes":["levitate_tone2"],"emoji":"🕴🏼","text":"","type":1,"order":1992,"group":1,"subgroup":26,"version":4,"tone":2},{"annotation":"西装革履的人: 中等肤色","name":"MAN IN BUSINESS SUIT LEVITATING, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F574-1F3FD","shortcodes":["levitate_tone3"],"emoji":"🕴🏽","text":"","type":1,"order":1993,"group":1,"subgroup":26,"version":4,"tone":3},{"annotation":"西装革履的人: 中等-深肤色","name":"MAN IN BUSINESS SUIT LEVITATING, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F574-1F3FE","shortcodes":["levitate_tone4"],"emoji":"🕴🏾","text":"","type":1,"order":1994,"group":1,"subgroup":26,"version":4,"tone":4},{"annotation":"西装革履的人: 较深肤色","name":"MAN IN BUSINESS SUIT LEVITATING, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F574-1F3FF","shortcodes":["levitate_tone5"],"emoji":"🕴🏿","text":"","type":1,"order":1995,"group":1,"subgroup":26,"version":4,"tone":5}]},{"annotation":"戴兔耳朵的人","name":"WOMAN WITH BUNNY EARS","hexcode":"1F46F","shortcodes":["people_bunny_ears_partying"],"tags":["兔耳朵","派对","聚会","跳舞"],"emoji":"👯","text":"","type":1,"order":1996,"group":1,"subgroup":26,"version":0.6},{"annotation":"兔先生","name":"WOMAN WITH BUNNY EARS, MALE SIGN","hexcode":"1F46F-200D-2642-FE0F","shortcodes":["men_bunny_ears_partying"],"tags":["兔耳朵","派对","男生派对","聚会","跳舞"],"emoji":"👯‍♂️","text":"","type":1,"order":1997,"group":1,"subgroup":26,"version":4,"gender":1},{"annotation":"兔女郎","name":"WOMAN WITH BUNNY EARS, FEMALE SIGN","hexcode":"1F46F-200D-2640-FE0F","shortcodes":["women_bunny_ears_partying"],"tags":["兔耳朵","女生派对","派对","聚会","跳舞"],"emoji":"👯‍♀️","text":"","type":1,"order":1999,"group":1,"subgroup":26,"version":4,"gender":0},{"annotation":"蒸房里的人","name":"PERSON IN STEAMY ROOM","hexcode":"1F9D6","shortcodes":["person_steamy_room"],"tags":["桑拿","蒸房"],"emoji":"🧖","text":"","type":1,"order":2001,"group":1,"subgroup":26,"version":5,"skins":[{"annotation":"蒸房里的人: 较浅肤色","name":"PERSON IN STEAMY ROOM, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D6-1F3FB","shortcodes":["person_steamy_room_tone1"],"emoji":"🧖🏻","text":"","type":1,"order":2002,"group":1,"subgroup":26,"version":5,"tone":1},{"annotation":"蒸房里的人: 中等-浅肤色","name":"PERSON IN STEAMY ROOM, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D6-1F3FC","shortcodes":["person_steamy_room_tone2"],"emoji":"🧖🏼","text":"","type":1,"order":2003,"group":1,"subgroup":26,"version":5,"tone":2},{"annotation":"蒸房里的人: 中等肤色","name":"PERSON IN STEAMY ROOM, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D6-1F3FD","shortcodes":["person_steamy_room_tone3"],"emoji":"🧖🏽","text":"","type":1,"order":2004,"group":1,"subgroup":26,"version":5,"tone":3},{"annotation":"蒸房里的人: 中等-深肤色","name":"PERSON IN STEAMY ROOM, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D6-1F3FE","shortcodes":["person_steamy_room_tone4"],"emoji":"🧖🏾","text":"","type":1,"order":2005,"group":1,"subgroup":26,"version":5,"tone":4},{"annotation":"蒸房里的人: 较深肤色","name":"PERSON IN STEAMY ROOM, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D6-1F3FF","shortcodes":["person_steamy_room_tone5"],"emoji":"🧖🏿","text":"","type":1,"order":2006,"group":1,"subgroup":26,"version":5,"tone":5}]},{"annotation":"蒸房里的男人","name":"PERSON IN STEAMY ROOM, MALE SIGN","hexcode":"1F9D6-200D-2642-FE0F","shortcodes":["man_steamy_room"],"tags":["桑拿","男性桑拿"],"emoji":"🧖‍♂️","text":"","type":1,"order":2007,"group":1,"subgroup":26,"version":5,"gender":1,"skins":[{"annotation":"蒸房里的男人: 较浅肤色","name":"PERSON IN STEAMY ROOM, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D6-1F3FB-200D-2642-FE0F","shortcodes":["man_steamy_room_tone1"],"emoji":"🧖🏻‍♂️","text":"","type":1,"order":2009,"group":1,"subgroup":26,"version":5,"gender":1,"tone":1},{"annotation":"蒸房里的男人: 中等-浅肤色","name":"PERSON IN STEAMY ROOM, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D6-1F3FC-200D-2642-FE0F","shortcodes":["man_steamy_room_tone2"],"emoji":"🧖🏼‍♂️","text":"","type":1,"order":2011,"group":1,"subgroup":26,"version":5,"gender":1,"tone":2},{"annotation":"蒸房里的男人: 中等肤色","name":"PERSON IN STEAMY ROOM, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D6-1F3FD-200D-2642-FE0F","shortcodes":["man_steamy_room_tone3"],"emoji":"🧖🏽‍♂️","text":"","type":1,"order":2013,"group":1,"subgroup":26,"version":5,"gender":1,"tone":3},{"annotation":"蒸房里的男人: 中等-深肤色","name":"PERSON IN STEAMY ROOM, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D6-1F3FE-200D-2642-FE0F","shortcodes":["man_steamy_room_tone4"],"emoji":"🧖🏾‍♂️","text":"","type":1,"order":2015,"group":1,"subgroup":26,"version":5,"gender":1,"tone":4},{"annotation":"蒸房里的男人: 较深肤色","name":"PERSON IN STEAMY ROOM, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D6-1F3FF-200D-2642-FE0F","shortcodes":["man_steamy_room_tone5"],"emoji":"🧖🏿‍♂️","text":"","type":1,"order":2017,"group":1,"subgroup":26,"version":5,"gender":1,"tone":5}]},{"annotation":"蒸房里的女人","name":"PERSON IN STEAMY ROOM, FEMALE SIGN","hexcode":"1F9D6-200D-2640-FE0F","shortcodes":["woman_steamy_room"],"tags":["女性桑拿","桑拿"],"emoji":"🧖‍♀️","text":"","type":1,"order":2019,"group":1,"subgroup":26,"version":5,"gender":0,"skins":[{"annotation":"蒸房里的女人: 较浅肤色","name":"PERSON IN STEAMY ROOM, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D6-1F3FB-200D-2640-FE0F","shortcodes":["woman_steamy_room_tone1"],"emoji":"🧖🏻‍♀️","text":"","type":1,"order":2021,"group":1,"subgroup":26,"version":5,"gender":0,"tone":1},{"annotation":"蒸房里的女人: 中等-浅肤色","name":"PERSON IN STEAMY ROOM, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D6-1F3FC-200D-2640-FE0F","shortcodes":["woman_steamy_room_tone2"],"emoji":"🧖🏼‍♀️","text":"","type":1,"order":2023,"group":1,"subgroup":26,"version":5,"gender":0,"tone":2},{"annotation":"蒸房里的女人: 中等肤色","name":"PERSON IN STEAMY ROOM, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D6-1F3FD-200D-2640-FE0F","shortcodes":["woman_steamy_room_tone3"],"emoji":"🧖🏽‍♀️","text":"","type":1,"order":2025,"group":1,"subgroup":26,"version":5,"gender":0,"tone":3},{"annotation":"蒸房里的女人: 中等-深肤色","name":"PERSON IN STEAMY ROOM, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D6-1F3FE-200D-2640-FE0F","shortcodes":["woman_steamy_room_tone4"],"emoji":"🧖🏾‍♀️","text":"","type":1,"order":2027,"group":1,"subgroup":26,"version":5,"gender":0,"tone":4},{"annotation":"蒸房里的女人: 较深肤色","name":"PERSON IN STEAMY ROOM, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D6-1F3FF-200D-2640-FE0F","shortcodes":["woman_steamy_room_tone5"],"emoji":"🧖🏿‍♀️","text":"","type":1,"order":2029,"group":1,"subgroup":26,"version":5,"gender":0,"tone":5}]},{"annotation":"攀爬的人","name":"PERSON CLIMBING","hexcode":"1F9D7","shortcodes":["person_climbing"],"tags":["登山者"],"emoji":"🧗","text":"","type":1,"order":2031,"group":1,"subgroup":26,"version":5,"skins":[{"annotation":"攀爬的人: 较浅肤色","name":"PERSON CLIMBING, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D7-1F3FB","shortcodes":["person_climbing_tone1"],"emoji":"🧗🏻","text":"","type":1,"order":2032,"group":1,"subgroup":26,"version":5,"tone":1},{"annotation":"攀爬的人: 中等-浅肤色","name":"PERSON CLIMBING, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D7-1F3FC","shortcodes":["person_climbing_tone2"],"emoji":"🧗🏼","text":"","type":1,"order":2033,"group":1,"subgroup":26,"version":5,"tone":2},{"annotation":"攀爬的人: 中等肤色","name":"PERSON CLIMBING, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D7-1F3FD","shortcodes":["person_climbing_tone3"],"emoji":"🧗🏽","text":"","type":1,"order":2034,"group":1,"subgroup":26,"version":5,"tone":3},{"annotation":"攀爬的人: 中等-深肤色","name":"PERSON CLIMBING, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D7-1F3FE","shortcodes":["person_climbing_tone4"],"emoji":"🧗🏾","text":"","type":1,"order":2035,"group":1,"subgroup":26,"version":5,"tone":4},{"annotation":"攀爬的人: 较深肤色","name":"PERSON CLIMBING, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D7-1F3FF","shortcodes":["person_climbing_tone5"],"emoji":"🧗🏿","text":"","type":1,"order":2036,"group":1,"subgroup":26,"version":5,"tone":5}]},{"annotation":"攀爬的男人","name":"PERSON CLIMBING, MALE SIGN","hexcode":"1F9D7-200D-2642-FE0F","shortcodes":["man_climbing"],"tags":["登山者"],"emoji":"🧗‍♂️","text":"","type":1,"order":2037,"group":1,"subgroup":26,"version":5,"gender":1,"skins":[{"annotation":"攀爬的男人: 较浅肤色","name":"PERSON CLIMBING, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D7-1F3FB-200D-2642-FE0F","shortcodes":["man_climbing_tone1"],"emoji":"🧗🏻‍♂️","text":"","type":1,"order":2039,"group":1,"subgroup":26,"version":5,"gender":1,"tone":1},{"annotation":"攀爬的男人: 中等-浅肤色","name":"PERSON CLIMBING, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D7-1F3FC-200D-2642-FE0F","shortcodes":["man_climbing_tone2"],"emoji":"🧗🏼‍♂️","text":"","type":1,"order":2041,"group":1,"subgroup":26,"version":5,"gender":1,"tone":2},{"annotation":"攀爬的男人: 中等肤色","name":"PERSON CLIMBING, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D7-1F3FD-200D-2642-FE0F","shortcodes":["man_climbing_tone3"],"emoji":"🧗🏽‍♂️","text":"","type":1,"order":2043,"group":1,"subgroup":26,"version":5,"gender":1,"tone":3},{"annotation":"攀爬的男人: 中等-深肤色","name":"PERSON CLIMBING, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D7-1F3FE-200D-2642-FE0F","shortcodes":["man_climbing_tone4"],"emoji":"🧗🏾‍♂️","text":"","type":1,"order":2045,"group":1,"subgroup":26,"version":5,"gender":1,"tone":4},{"annotation":"攀爬的男人: 较深肤色","name":"PERSON CLIMBING, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D7-1F3FF-200D-2642-FE0F","shortcodes":["man_climbing_tone5"],"emoji":"🧗🏿‍♂️","text":"","type":1,"order":2047,"group":1,"subgroup":26,"version":5,"gender":1,"tone":5}]},{"annotation":"攀爬的女人","name":"PERSON CLIMBING, FEMALE SIGN","hexcode":"1F9D7-200D-2640-FE0F","shortcodes":["woman_climbing"],"tags":["登山者"],"emoji":"🧗‍♀️","text":"","type":1,"order":2049,"group":1,"subgroup":26,"version":5,"gender":0,"skins":[{"annotation":"攀爬的女人: 较浅肤色","name":"PERSON CLIMBING, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D7-1F3FB-200D-2640-FE0F","shortcodes":["woman_climbing_tone1"],"emoji":"🧗🏻‍♀️","text":"","type":1,"order":2051,"group":1,"subgroup":26,"version":5,"gender":0,"tone":1},{"annotation":"攀爬的女人: 中等-浅肤色","name":"PERSON CLIMBING, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D7-1F3FC-200D-2640-FE0F","shortcodes":["woman_climbing_tone2"],"emoji":"🧗🏼‍♀️","text":"","type":1,"order":2053,"group":1,"subgroup":26,"version":5,"gender":0,"tone":2},{"annotation":"攀爬的女人: 中等肤色","name":"PERSON CLIMBING, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D7-1F3FD-200D-2640-FE0F","shortcodes":["woman_climbing_tone3"],"emoji":"🧗🏽‍♀️","text":"","type":1,"order":2055,"group":1,"subgroup":26,"version":5,"gender":0,"tone":3},{"annotation":"攀爬的女人: 中等-深肤色","name":"PERSON CLIMBING, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D7-1F3FE-200D-2640-FE0F","shortcodes":["woman_climbing_tone4"],"emoji":"🧗🏾‍♀️","text":"","type":1,"order":2057,"group":1,"subgroup":26,"version":5,"gender":0,"tone":4},{"annotation":"攀爬的女人: 较深肤色","name":"PERSON CLIMBING, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D7-1F3FF-200D-2640-FE0F","shortcodes":["woman_climbing_tone5"],"emoji":"🧗🏿‍♀️","text":"","type":1,"order":2059,"group":1,"subgroup":26,"version":5,"gender":0,"tone":5}]},{"annotation":"击剑选手","name":"FENCER","hexcode":"1F93A","shortcodes":["person_fencing"],"tags":["人","体育","击剑","剑"],"emoji":"🤺","text":"","type":1,"order":2061,"group":1,"subgroup":27,"version":3},{"annotation":"赛马","name":"HORSE RACING","hexcode":"1F3C7","shortcodes":["horse_racing"],"tags":["马"],"emoji":"🏇","text":"","type":1,"order":2062,"group":1,"subgroup":27,"version":1,"skins":[{"annotation":"赛马: 较浅肤色","name":"HORSE RACING, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3C7-1F3FB","shortcodes":["horse_racing_tone1"],"emoji":"🏇🏻","text":"","type":1,"order":2063,"group":1,"subgroup":27,"version":1,"tone":1},{"annotation":"赛马: 中等-浅肤色","name":"HORSE RACING, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3C7-1F3FC","shortcodes":["horse_racing_tone2"],"emoji":"🏇🏼","text":"","type":1,"order":2064,"group":1,"subgroup":27,"version":1,"tone":2},{"annotation":"赛马: 中等肤色","name":"HORSE RACING, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3C7-1F3FD","shortcodes":["horse_racing_tone3"],"emoji":"🏇🏽","text":"","type":1,"order":2065,"group":1,"subgroup":27,"version":1,"tone":3},{"annotation":"赛马: 中等-深肤色","name":"HORSE RACING, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3C7-1F3FE","shortcodes":["horse_racing_tone4"],"emoji":"🏇🏾","text":"","type":1,"order":2066,"group":1,"subgroup":27,"version":1,"tone":4},{"annotation":"赛马: 较深肤色","name":"HORSE RACING, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3C7-1F3FF","shortcodes":["horse_racing_tone5"],"emoji":"🏇🏿","text":"","type":1,"order":2067,"group":1,"subgroup":27,"version":1,"tone":5}]},{"annotation":"滑雪的人","name":"SKIER","hexcode":"26F7","shortcodes":["skier"],"tags":["滑雪","雪"],"emoji":"⛷️","text":"⛷︎","type":0,"order":2069,"group":1,"subgroup":27,"version":0.7},{"annotation":"滑雪板","name":"SNOWBOARDER","hexcode":"1F3C2","shortcodes":["snowboarder"],"tags":["滑雪","雪"],"emoji":"🏂️","text":"🏂︎","type":1,"order":2070,"group":1,"subgroup":27,"version":0.6,"skins":[{"annotation":"滑雪板: 较浅肤色","name":"SNOWBOARDER, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3C2-1F3FB","shortcodes":["snowboarder_tone1"],"emoji":"🏂🏻","text":"","type":1,"order":2071,"group":1,"subgroup":27,"version":1,"tone":1},{"annotation":"滑雪板: 中等-浅肤色","name":"SNOWBOARDER, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3C2-1F3FC","shortcodes":["snowboarder_tone2"],"emoji":"🏂🏼","text":"","type":1,"order":2072,"group":1,"subgroup":27,"version":1,"tone":2},{"annotation":"滑雪板: 中等肤色","name":"SNOWBOARDER, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3C2-1F3FD","shortcodes":["snowboarder_tone3"],"emoji":"🏂🏽","text":"","type":1,"order":2073,"group":1,"subgroup":27,"version":1,"tone":3},{"annotation":"滑雪板: 中等-深肤色","name":"SNOWBOARDER, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3C2-1F3FE","shortcodes":["snowboarder_tone4"],"emoji":"🏂🏾","text":"","type":1,"order":2074,"group":1,"subgroup":27,"version":1,"tone":4},{"annotation":"滑雪板: 较深肤色","name":"SNOWBOARDER, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3C2-1F3FF","shortcodes":["snowboarder_tone5"],"emoji":"🏂🏿","text":"","type":1,"order":2075,"group":1,"subgroup":27,"version":1,"tone":5}]},{"annotation":"打高尔夫的人","name":"GOLFER","hexcode":"1F3CC","shortcodes":["person_golfing"],"tags":["球","高尔夫"],"emoji":"🏌️","text":"🏌︎","type":0,"order":2077,"group":1,"subgroup":27,"version":0.7,"skins":[{"annotation":"打高尔夫的人: 较浅肤色","name":"GOLFER, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3CC-1F3FB","shortcodes":["person_golfing_tone1"],"emoji":"🏌🏻","text":"","type":1,"order":2078,"group":1,"subgroup":27,"version":4,"tone":1},{"annotation":"打高尔夫的人: 中等-浅肤色","name":"GOLFER, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3CC-1F3FC","shortcodes":["person_golfing_tone2"],"emoji":"🏌🏼","text":"","type":1,"order":2079,"group":1,"subgroup":27,"version":4,"tone":2},{"annotation":"打高尔夫的人: 中等肤色","name":"GOLFER, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3CC-1F3FD","shortcodes":["person_golfing_tone3"],"emoji":"🏌🏽","text":"","type":1,"order":2080,"group":1,"subgroup":27,"version":4,"tone":3},{"annotation":"打高尔夫的人: 中等-深肤色","name":"GOLFER, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3CC-1F3FE","shortcodes":["person_golfing_tone4"],"emoji":"🏌🏾","text":"","type":1,"order":2081,"group":1,"subgroup":27,"version":4,"tone":4},{"annotation":"打高尔夫的人: 较深肤色","name":"GOLFER, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3CC-1F3FF","shortcodes":["person_golfing_tone5"],"emoji":"🏌🏿","text":"","type":1,"order":2082,"group":1,"subgroup":27,"version":4,"tone":5}]},{"annotation":"男生打高尔夫","name":"GOLFER, MALE SIGN","hexcode":"1F3CC-FE0F-200D-2642-FE0F","shortcodes":["man_golfing"],"tags":["男","高尔夫"],"emoji":"🏌️‍♂️","text":"","type":1,"order":2083,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生打高尔夫: 较浅肤色","name":"GOLFER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3CC-1F3FB-200D-2642-FE0F","shortcodes":["man_golfing_tone1"],"emoji":"🏌🏻‍♂️","text":"","type":1,"order":2087,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生打高尔夫: 中等-浅肤色","name":"GOLFER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3CC-1F3FC-200D-2642-FE0F","shortcodes":["man_golfing_tone2"],"emoji":"🏌🏼‍♂️","text":"","type":1,"order":2089,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生打高尔夫: 中等肤色","name":"GOLFER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3CC-1F3FD-200D-2642-FE0F","shortcodes":["man_golfing_tone3"],"emoji":"🏌🏽‍♂️","text":"","type":1,"order":2091,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生打高尔夫: 中等-深肤色","name":"GOLFER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3CC-1F3FE-200D-2642-FE0F","shortcodes":["man_golfing_tone4"],"emoji":"🏌🏾‍♂️","text":"","type":1,"order":2093,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生打高尔夫: 较深肤色","name":"GOLFER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3CC-1F3FF-200D-2642-FE0F","shortcodes":["man_golfing_tone5"],"emoji":"🏌🏿‍♂️","text":"","type":1,"order":2095,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生打高尔夫","name":"GOLFER, FEMALE SIGN","hexcode":"1F3CC-FE0F-200D-2640-FE0F","shortcodes":["woman_golfing"],"tags":["女","高尔夫"],"emoji":"🏌️‍♀️","text":"","type":1,"order":2097,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生打高尔夫: 较浅肤色","name":"GOLFER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3CC-1F3FB-200D-2640-FE0F","shortcodes":["woman_golfing_tone1"],"emoji":"🏌🏻‍♀️","text":"","type":1,"order":2101,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生打高尔夫: 中等-浅肤色","name":"GOLFER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3CC-1F3FC-200D-2640-FE0F","shortcodes":["woman_golfing_tone2"],"emoji":"🏌🏼‍♀️","text":"","type":1,"order":2103,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生打高尔夫: 中等肤色","name":"GOLFER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3CC-1F3FD-200D-2640-FE0F","shortcodes":["woman_golfing_tone3"],"emoji":"🏌🏽‍♀️","text":"","type":1,"order":2105,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生打高尔夫: 中等-深肤色","name":"GOLFER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3CC-1F3FE-200D-2640-FE0F","shortcodes":["woman_golfing_tone4"],"emoji":"🏌🏾‍♀️","text":"","type":1,"order":2107,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生打高尔夫: 较深肤色","name":"GOLFER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3CC-1F3FF-200D-2640-FE0F","shortcodes":["woman_golfing_tone5"],"emoji":"🏌🏿‍♀️","text":"","type":1,"order":2109,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"冲浪","name":"SURFER","hexcode":"1F3C4","shortcodes":["person_surfing"],"tags":["冲浪"],"emoji":"🏄️","text":"🏄︎","type":1,"order":2111,"group":1,"subgroup":27,"version":0.6,"skins":[{"annotation":"冲浪: 较浅肤色","name":"SURFER, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3C4-1F3FB","shortcodes":["person_surfing_tone1"],"emoji":"🏄🏻","text":"","type":1,"order":2112,"group":1,"subgroup":27,"version":1,"tone":1},{"annotation":"冲浪: 中等-浅肤色","name":"SURFER, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3C4-1F3FC","shortcodes":["person_surfing_tone2"],"emoji":"🏄🏼","text":"","type":1,"order":2113,"group":1,"subgroup":27,"version":1,"tone":2},{"annotation":"冲浪: 中等肤色","name":"SURFER, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3C4-1F3FD","shortcodes":["person_surfing_tone3"],"emoji":"🏄🏽","text":"","type":1,"order":2114,"group":1,"subgroup":27,"version":1,"tone":3},{"annotation":"冲浪: 中等-深肤色","name":"SURFER, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3C4-1F3FE","shortcodes":["person_surfing_tone4"],"emoji":"🏄🏾","text":"","type":1,"order":2115,"group":1,"subgroup":27,"version":1,"tone":4},{"annotation":"冲浪: 较深肤色","name":"SURFER, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3C4-1F3FF","shortcodes":["person_surfing_tone5"],"emoji":"🏄🏿","text":"","type":1,"order":2116,"group":1,"subgroup":27,"version":1,"tone":5}]},{"annotation":"男生冲浪","name":"SURFER, MALE SIGN","hexcode":"1F3C4-200D-2642-FE0F","shortcodes":["man_surfing"],"tags":["冲浪","男"],"emoji":"🏄‍♂️","text":"","type":1,"order":2117,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生冲浪: 较浅肤色","name":"SURFER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3C4-1F3FB-200D-2642-FE0F","shortcodes":["man_surfing_tone1"],"emoji":"🏄🏻‍♂️","text":"","type":1,"order":2119,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生冲浪: 中等-浅肤色","name":"SURFER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3C4-1F3FC-200D-2642-FE0F","shortcodes":["man_surfing_tone2"],"emoji":"🏄🏼‍♂️","text":"","type":1,"order":2121,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生冲浪: 中等肤色","name":"SURFER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3C4-1F3FD-200D-2642-FE0F","shortcodes":["man_surfing_tone3"],"emoji":"🏄🏽‍♂️","text":"","type":1,"order":2123,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生冲浪: 中等-深肤色","name":"SURFER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3C4-1F3FE-200D-2642-FE0F","shortcodes":["man_surfing_tone4"],"emoji":"🏄🏾‍♂️","text":"","type":1,"order":2125,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生冲浪: 较深肤色","name":"SURFER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3C4-1F3FF-200D-2642-FE0F","shortcodes":["man_surfing_tone5"],"emoji":"🏄🏿‍♂️","text":"","type":1,"order":2127,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生冲浪","name":"SURFER, FEMALE SIGN","hexcode":"1F3C4-200D-2640-FE0F","shortcodes":["woman_surfing"],"tags":["冲浪","女"],"emoji":"🏄‍♀️","text":"","type":1,"order":2129,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生冲浪: 较浅肤色","name":"SURFER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3C4-1F3FB-200D-2640-FE0F","shortcodes":["woman_surfing_tone1"],"emoji":"🏄🏻‍♀️","text":"","type":1,"order":2131,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生冲浪: 中等-浅肤色","name":"SURFER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3C4-1F3FC-200D-2640-FE0F","shortcodes":["woman_surfing_tone2"],"emoji":"🏄🏼‍♀️","text":"","type":1,"order":2133,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生冲浪: 中等肤色","name":"SURFER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3C4-1F3FD-200D-2640-FE0F","shortcodes":["woman_surfing_tone3"],"emoji":"🏄🏽‍♀️","text":"","type":1,"order":2135,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生冲浪: 中等-深肤色","name":"SURFER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3C4-1F3FE-200D-2640-FE0F","shortcodes":["woman_surfing_tone4"],"emoji":"🏄🏾‍♀️","text":"","type":1,"order":2137,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生冲浪: 较深肤色","name":"SURFER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3C4-1F3FF-200D-2640-FE0F","shortcodes":["woman_surfing_tone5"],"emoji":"🏄🏿‍♀️","text":"","type":1,"order":2139,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"划艇","name":"ROWBOAT","hexcode":"1F6A3","shortcodes":["person_rowing_boat"],"tags":["船"],"emoji":"🚣","text":"","type":1,"order":2141,"group":1,"subgroup":27,"version":1,"skins":[{"annotation":"划艇: 较浅肤色","name":"ROWBOAT, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6A3-1F3FB","shortcodes":["person_rowing_boat_tone1"],"emoji":"🚣🏻","text":"","type":1,"order":2142,"group":1,"subgroup":27,"version":1,"tone":1},{"annotation":"划艇: 中等-浅肤色","name":"ROWBOAT, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6A3-1F3FC","shortcodes":["person_rowing_boat_tone2"],"emoji":"🚣🏼","text":"","type":1,"order":2143,"group":1,"subgroup":27,"version":1,"tone":2},{"annotation":"划艇: 中等肤色","name":"ROWBOAT, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6A3-1F3FD","shortcodes":["person_rowing_boat_tone3"],"emoji":"🚣🏽","text":"","type":1,"order":2144,"group":1,"subgroup":27,"version":1,"tone":3},{"annotation":"划艇: 中等-深肤色","name":"ROWBOAT, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6A3-1F3FE","shortcodes":["person_rowing_boat_tone4"],"emoji":"🚣🏾","text":"","type":1,"order":2145,"group":1,"subgroup":27,"version":1,"tone":4},{"annotation":"划艇: 较深肤色","name":"ROWBOAT, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6A3-1F3FF","shortcodes":["person_rowing_boat_tone5"],"emoji":"🚣🏿","text":"","type":1,"order":2146,"group":1,"subgroup":27,"version":1,"tone":5}]},{"annotation":"男生划船","name":"ROWBOAT, MALE SIGN","hexcode":"1F6A3-200D-2642-FE0F","shortcodes":["man_rowing_boat"],"tags":["划船","划艇","男","船"],"emoji":"🚣‍♂️","text":"","type":1,"order":2147,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生划船: 较浅肤色","name":"ROWBOAT, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6A3-1F3FB-200D-2642-FE0F","shortcodes":["man_rowing_boat_tone1"],"emoji":"🚣🏻‍♂️","text":"","type":1,"order":2149,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生划船: 中等-浅肤色","name":"ROWBOAT, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6A3-1F3FC-200D-2642-FE0F","shortcodes":["man_rowing_boat_tone2"],"emoji":"🚣🏼‍♂️","text":"","type":1,"order":2151,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生划船: 中等肤色","name":"ROWBOAT, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6A3-1F3FD-200D-2642-FE0F","shortcodes":["man_rowing_boat_tone3"],"emoji":"🚣🏽‍♂️","text":"","type":1,"order":2153,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生划船: 中等-深肤色","name":"ROWBOAT, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6A3-1F3FE-200D-2642-FE0F","shortcodes":["man_rowing_boat_tone4"],"emoji":"🚣🏾‍♂️","text":"","type":1,"order":2155,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生划船: 较深肤色","name":"ROWBOAT, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6A3-1F3FF-200D-2642-FE0F","shortcodes":["man_rowing_boat_tone5"],"emoji":"🚣🏿‍♂️","text":"","type":1,"order":2157,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生划船","name":"ROWBOAT, FEMALE SIGN","hexcode":"1F6A3-200D-2640-FE0F","shortcodes":["woman_rowing_boat"],"tags":["划船","划艇","女","船"],"emoji":"🚣‍♀️","text":"","type":1,"order":2159,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生划船: 较浅肤色","name":"ROWBOAT, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6A3-1F3FB-200D-2640-FE0F","shortcodes":["woman_rowing_boat_tone1"],"emoji":"🚣🏻‍♀️","text":"","type":1,"order":2161,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生划船: 中等-浅肤色","name":"ROWBOAT, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6A3-1F3FC-200D-2640-FE0F","shortcodes":["woman_rowing_boat_tone2"],"emoji":"🚣🏼‍♀️","text":"","type":1,"order":2163,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生划船: 中等肤色","name":"ROWBOAT, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6A3-1F3FD-200D-2640-FE0F","shortcodes":["woman_rowing_boat_tone3"],"emoji":"🚣🏽‍♀️","text":"","type":1,"order":2165,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生划船: 中等-深肤色","name":"ROWBOAT, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6A3-1F3FE-200D-2640-FE0F","shortcodes":["woman_rowing_boat_tone4"],"emoji":"🚣🏾‍♀️","text":"","type":1,"order":2167,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生划船: 较深肤色","name":"ROWBOAT, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6A3-1F3FF-200D-2640-FE0F","shortcodes":["woman_rowing_boat_tone5"],"emoji":"🚣🏿‍♀️","text":"","type":1,"order":2169,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"游泳","name":"SWIMMER","hexcode":"1F3CA","shortcodes":["person_swimming"],"tags":["游泳"],"emoji":"🏊️","text":"🏊︎","type":1,"order":2171,"group":1,"subgroup":27,"version":0.6,"skins":[{"annotation":"游泳: 较浅肤色","name":"SWIMMER, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3CA-1F3FB","shortcodes":["person_swimming_tone1"],"emoji":"🏊🏻","text":"","type":1,"order":2172,"group":1,"subgroup":27,"version":1,"tone":1},{"annotation":"游泳: 中等-浅肤色","name":"SWIMMER, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3CA-1F3FC","shortcodes":["person_swimming_tone2"],"emoji":"🏊🏼","text":"","type":1,"order":2173,"group":1,"subgroup":27,"version":1,"tone":2},{"annotation":"游泳: 中等肤色","name":"SWIMMER, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3CA-1F3FD","shortcodes":["person_swimming_tone3"],"emoji":"🏊🏽","text":"","type":1,"order":2174,"group":1,"subgroup":27,"version":1,"tone":3},{"annotation":"游泳: 中等-深肤色","name":"SWIMMER, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3CA-1F3FE","shortcodes":["person_swimming_tone4"],"emoji":"🏊🏾","text":"","type":1,"order":2175,"group":1,"subgroup":27,"version":1,"tone":4},{"annotation":"游泳: 较深肤色","name":"SWIMMER, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3CA-1F3FF","shortcodes":["person_swimming_tone5"],"emoji":"🏊🏿","text":"","type":1,"order":2176,"group":1,"subgroup":27,"version":1,"tone":5}]},{"annotation":"男生游泳","name":"SWIMMER, MALE SIGN","hexcode":"1F3CA-200D-2642-FE0F","shortcodes":["man_swimming"],"tags":["游泳","男"],"emoji":"🏊‍♂️","text":"","type":1,"order":2177,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生游泳: 较浅肤色","name":"SWIMMER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3CA-1F3FB-200D-2642-FE0F","shortcodes":["man_swimming_tone1"],"emoji":"🏊🏻‍♂️","text":"","type":1,"order":2179,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生游泳: 中等-浅肤色","name":"SWIMMER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3CA-1F3FC-200D-2642-FE0F","shortcodes":["man_swimming_tone2"],"emoji":"🏊🏼‍♂️","text":"","type":1,"order":2181,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生游泳: 中等肤色","name":"SWIMMER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3CA-1F3FD-200D-2642-FE0F","shortcodes":["man_swimming_tone3"],"emoji":"🏊🏽‍♂️","text":"","type":1,"order":2183,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生游泳: 中等-深肤色","name":"SWIMMER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3CA-1F3FE-200D-2642-FE0F","shortcodes":["man_swimming_tone4"],"emoji":"🏊🏾‍♂️","text":"","type":1,"order":2185,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生游泳: 较深肤色","name":"SWIMMER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3CA-1F3FF-200D-2642-FE0F","shortcodes":["man_swimming_tone5"],"emoji":"🏊🏿‍♂️","text":"","type":1,"order":2187,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生游泳","name":"SWIMMER, FEMALE SIGN","hexcode":"1F3CA-200D-2640-FE0F","shortcodes":["woman_swimming"],"tags":["女","游泳"],"emoji":"🏊‍♀️","text":"","type":1,"order":2189,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生游泳: 较浅肤色","name":"SWIMMER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3CA-1F3FB-200D-2640-FE0F","shortcodes":["woman_swimming_tone1"],"emoji":"🏊🏻‍♀️","text":"","type":1,"order":2191,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生游泳: 中等-浅肤色","name":"SWIMMER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3CA-1F3FC-200D-2640-FE0F","shortcodes":["woman_swimming_tone2"],"emoji":"🏊🏼‍♀️","text":"","type":1,"order":2193,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生游泳: 中等肤色","name":"SWIMMER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3CA-1F3FD-200D-2640-FE0F","shortcodes":["woman_swimming_tone3"],"emoji":"🏊🏽‍♀️","text":"","type":1,"order":2195,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生游泳: 中等-深肤色","name":"SWIMMER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3CA-1F3FE-200D-2640-FE0F","shortcodes":["woman_swimming_tone4"],"emoji":"🏊🏾‍♀️","text":"","type":1,"order":2197,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生游泳: 较深肤色","name":"SWIMMER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3CA-1F3FF-200D-2640-FE0F","shortcodes":["woman_swimming_tone5"],"emoji":"🏊🏿‍♀️","text":"","type":1,"order":2199,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"玩球","name":"PERSON WITH BALL","hexcode":"26F9","shortcodes":["person_bouncing_ball"],"tags":["游戏","玩","球"],"emoji":"⛹️","text":"⛹︎","type":0,"order":2202,"group":1,"subgroup":27,"version":0.7,"skins":[{"annotation":"玩球: 较浅肤色","name":"PERSON WITH BALL, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"26F9-1F3FB","shortcodes":["person_bouncing_ball_tone1"],"emoji":"⛹🏻","text":"","type":1,"order":2203,"group":1,"subgroup":27,"version":2,"tone":1},{"annotation":"玩球: 中等-浅肤色","name":"PERSON WITH BALL, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"26F9-1F3FC","shortcodes":["person_bouncing_ball_tone2"],"emoji":"⛹🏼","text":"","type":1,"order":2204,"group":1,"subgroup":27,"version":2,"tone":2},{"annotation":"玩球: 中等肤色","name":"PERSON WITH BALL, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"26F9-1F3FD","shortcodes":["person_bouncing_ball_tone3"],"emoji":"⛹🏽","text":"","type":1,"order":2205,"group":1,"subgroup":27,"version":2,"tone":3},{"annotation":"玩球: 中等-深肤色","name":"PERSON WITH BALL, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"26F9-1F3FE","shortcodes":["person_bouncing_ball_tone4"],"emoji":"⛹🏾","text":"","type":1,"order":2206,"group":1,"subgroup":27,"version":2,"tone":4},{"annotation":"玩球: 较深肤色","name":"PERSON WITH BALL, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"26F9-1F3FF","shortcodes":["person_bouncing_ball_tone5"],"emoji":"⛹🏿","text":"","type":1,"order":2207,"group":1,"subgroup":27,"version":2,"tone":5}]},{"annotation":"男生玩球","name":"PERSON WITH BALL, MALE SIGN","hexcode":"26F9-FE0F-200D-2642-FE0F","shortcodes":["man_bouncing_ball"],"tags":["球","男"],"emoji":"⛹️‍♂️","text":"","type":1,"order":2208,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生玩球: 较浅肤色","name":"PERSON WITH BALL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"26F9-1F3FB-200D-2642-FE0F","shortcodes":["man_bouncing_ball_tone1"],"emoji":"⛹🏻‍♂️","text":"","type":1,"order":2212,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生玩球: 中等-浅肤色","name":"PERSON WITH BALL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"26F9-1F3FC-200D-2642-FE0F","shortcodes":["man_bouncing_ball_tone2"],"emoji":"⛹🏼‍♂️","text":"","type":1,"order":2214,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生玩球: 中等肤色","name":"PERSON WITH BALL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"26F9-1F3FD-200D-2642-FE0F","shortcodes":["man_bouncing_ball_tone3"],"emoji":"⛹🏽‍♂️","text":"","type":1,"order":2216,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生玩球: 中等-深肤色","name":"PERSON WITH BALL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"26F9-1F3FE-200D-2642-FE0F","shortcodes":["man_bouncing_ball_tone4"],"emoji":"⛹🏾‍♂️","text":"","type":1,"order":2218,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生玩球: 较深肤色","name":"PERSON WITH BALL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"26F9-1F3FF-200D-2642-FE0F","shortcodes":["man_bouncing_ball_tone5"],"emoji":"⛹🏿‍♂️","text":"","type":1,"order":2220,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生玩球","name":"PERSON WITH BALL, FEMALE SIGN","hexcode":"26F9-FE0F-200D-2640-FE0F","shortcodes":["woman_bouncing_ball"],"tags":["女","游戏","玩","球"],"emoji":"⛹️‍♀️","text":"","type":1,"order":2222,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生玩球: 较浅肤色","name":"PERSON WITH BALL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"26F9-1F3FB-200D-2640-FE0F","shortcodes":["woman_bouncing_ball_tone1"],"emoji":"⛹🏻‍♀️","text":"","type":1,"order":2226,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生玩球: 中等-浅肤色","name":"PERSON WITH BALL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"26F9-1F3FC-200D-2640-FE0F","shortcodes":["woman_bouncing_ball_tone2"],"emoji":"⛹🏼‍♀️","text":"","type":1,"order":2228,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生玩球: 中等肤色","name":"PERSON WITH BALL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"26F9-1F3FD-200D-2640-FE0F","shortcodes":["woman_bouncing_ball_tone3"],"emoji":"⛹🏽‍♀️","text":"","type":1,"order":2230,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生玩球: 中等-深肤色","name":"PERSON WITH BALL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"26F9-1F3FE-200D-2640-FE0F","shortcodes":["woman_bouncing_ball_tone4"],"emoji":"⛹🏾‍♀️","text":"","type":1,"order":2232,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生玩球: 较深肤色","name":"PERSON WITH BALL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"26F9-1F3FF-200D-2640-FE0F","shortcodes":["woman_bouncing_ball_tone5"],"emoji":"⛹🏿‍♀️","text":"","type":1,"order":2234,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"举重","name":"WEIGHT LIFTER","hexcode":"1F3CB","shortcodes":["person_lifting_weights"],"tags":["举重"],"emoji":"🏋️","text":"🏋︎","type":0,"order":2237,"group":1,"subgroup":27,"version":0.7,"skins":[{"annotation":"举重: 较浅肤色","name":"WEIGHT LIFTER, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3CB-1F3FB","shortcodes":["person_lifting_weights_tone1"],"emoji":"🏋🏻","text":"","type":1,"order":2238,"group":1,"subgroup":27,"version":2,"tone":1},{"annotation":"举重: 中等-浅肤色","name":"WEIGHT LIFTER, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3CB-1F3FC","shortcodes":["person_lifting_weights_tone2"],"emoji":"🏋🏼","text":"","type":1,"order":2239,"group":1,"subgroup":27,"version":2,"tone":2},{"annotation":"举重: 中等肤色","name":"WEIGHT LIFTER, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3CB-1F3FD","shortcodes":["person_lifting_weights_tone3"],"emoji":"🏋🏽","text":"","type":1,"order":2240,"group":1,"subgroup":27,"version":2,"tone":3},{"annotation":"举重: 中等-深肤色","name":"WEIGHT LIFTER, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3CB-1F3FE","shortcodes":["person_lifting_weights_tone4"],"emoji":"🏋🏾","text":"","type":1,"order":2241,"group":1,"subgroup":27,"version":2,"tone":4},{"annotation":"举重: 较深肤色","name":"WEIGHT LIFTER, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3CB-1F3FF","shortcodes":["person_lifting_weights_tone5"],"emoji":"🏋🏿","text":"","type":1,"order":2242,"group":1,"subgroup":27,"version":2,"tone":5}]},{"annotation":"男生举重","name":"WEIGHT LIFTER, MALE SIGN","hexcode":"1F3CB-FE0F-200D-2642-FE0F","shortcodes":["man_lifting_weights"],"tags":["举重","男"],"emoji":"🏋️‍♂️","text":"","type":1,"order":2243,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生举重: 较浅肤色","name":"WEIGHT LIFTER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3CB-1F3FB-200D-2642-FE0F","shortcodes":["man_lifting_weights_tone1"],"emoji":"🏋🏻‍♂️","text":"","type":1,"order":2247,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生举重: 中等-浅肤色","name":"WEIGHT LIFTER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3CB-1F3FC-200D-2642-FE0F","shortcodes":["man_lifting_weights_tone2"],"emoji":"🏋🏼‍♂️","text":"","type":1,"order":2249,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生举重: 中等肤色","name":"WEIGHT LIFTER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3CB-1F3FD-200D-2642-FE0F","shortcodes":["man_lifting_weights_tone3"],"emoji":"🏋🏽‍♂️","text":"","type":1,"order":2251,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生举重: 中等-深肤色","name":"WEIGHT LIFTER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3CB-1F3FE-200D-2642-FE0F","shortcodes":["man_lifting_weights_tone4"],"emoji":"🏋🏾‍♂️","text":"","type":1,"order":2253,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生举重: 较深肤色","name":"WEIGHT LIFTER, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3CB-1F3FF-200D-2642-FE0F","shortcodes":["man_lifting_weights_tone5"],"emoji":"🏋🏿‍♂️","text":"","type":1,"order":2255,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生举重","name":"WEIGHT LIFTER, FEMALE SIGN","hexcode":"1F3CB-FE0F-200D-2640-FE0F","shortcodes":["woman_lifting_weights"],"tags":["举重","女"],"emoji":"🏋️‍♀️","text":"","type":1,"order":2257,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生举重: 较浅肤色","name":"WEIGHT LIFTER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3CB-1F3FB-200D-2640-FE0F","shortcodes":["woman_lifting_weights_tone1"],"emoji":"🏋🏻‍♀️","text":"","type":1,"order":2261,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生举重: 中等-浅肤色","name":"WEIGHT LIFTER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3CB-1F3FC-200D-2640-FE0F","shortcodes":["woman_lifting_weights_tone2"],"emoji":"🏋🏼‍♀️","text":"","type":1,"order":2263,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生举重: 中等肤色","name":"WEIGHT LIFTER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3CB-1F3FD-200D-2640-FE0F","shortcodes":["woman_lifting_weights_tone3"],"emoji":"🏋🏽‍♀️","text":"","type":1,"order":2265,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生举重: 中等-深肤色","name":"WEIGHT LIFTER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3CB-1F3FE-200D-2640-FE0F","shortcodes":["woman_lifting_weights_tone4"],"emoji":"🏋🏾‍♀️","text":"","type":1,"order":2267,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生举重: 较深肤色","name":"WEIGHT LIFTER, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3CB-1F3FF-200D-2640-FE0F","shortcodes":["woman_lifting_weights_tone5"],"emoji":"🏋🏿‍♀️","text":"","type":1,"order":2269,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"骑自行车","name":"BICYCLIST","hexcode":"1F6B4","shortcodes":["person_biking"],"tags":["单车","自行车","骑单车"],"emoji":"🚴","text":"","type":1,"order":2271,"group":1,"subgroup":27,"version":1,"skins":[{"annotation":"骑自行车: 较浅肤色","name":"BICYCLIST, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6B4-1F3FB","shortcodes":["person_biking_tone1"],"emoji":"🚴🏻","text":"","type":1,"order":2272,"group":1,"subgroup":27,"version":1,"tone":1},{"annotation":"骑自行车: 中等-浅肤色","name":"BICYCLIST, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6B4-1F3FC","shortcodes":["person_biking_tone2"],"emoji":"🚴🏼","text":"","type":1,"order":2273,"group":1,"subgroup":27,"version":1,"tone":2},{"annotation":"骑自行车: 中等肤色","name":"BICYCLIST, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6B4-1F3FD","shortcodes":["person_biking_tone3"],"emoji":"🚴🏽","text":"","type":1,"order":2274,"group":1,"subgroup":27,"version":1,"tone":3},{"annotation":"骑自行车: 中等-深肤色","name":"BICYCLIST, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6B4-1F3FE","shortcodes":["person_biking_tone4"],"emoji":"🚴🏾","text":"","type":1,"order":2275,"group":1,"subgroup":27,"version":1,"tone":4},{"annotation":"骑自行车: 较深肤色","name":"BICYCLIST, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6B4-1F3FF","shortcodes":["person_biking_tone5"],"emoji":"🚴🏿","text":"","type":1,"order":2276,"group":1,"subgroup":27,"version":1,"tone":5}]},{"annotation":"男生骑自行车","name":"BICYCLIST, MALE SIGN","hexcode":"1F6B4-200D-2642-FE0F","shortcodes":["man_biking"],"tags":["单车","男","自行车","骑车"],"emoji":"🚴‍♂️","text":"","type":1,"order":2277,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生骑自行车: 较浅肤色","name":"BICYCLIST, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6B4-1F3FB-200D-2642-FE0F","shortcodes":["man_biking_tone1"],"emoji":"🚴🏻‍♂️","text":"","type":1,"order":2279,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生骑自行车: 中等-浅肤色","name":"BICYCLIST, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6B4-1F3FC-200D-2642-FE0F","shortcodes":["man_biking_tone2"],"emoji":"🚴🏼‍♂️","text":"","type":1,"order":2281,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生骑自行车: 中等肤色","name":"BICYCLIST, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6B4-1F3FD-200D-2642-FE0F","shortcodes":["man_biking_tone3"],"emoji":"🚴🏽‍♂️","text":"","type":1,"order":2283,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生骑自行车: 中等-深肤色","name":"BICYCLIST, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6B4-1F3FE-200D-2642-FE0F","shortcodes":["man_biking_tone4"],"emoji":"🚴🏾‍♂️","text":"","type":1,"order":2285,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生骑自行车: 较深肤色","name":"BICYCLIST, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6B4-1F3FF-200D-2642-FE0F","shortcodes":["man_biking_tone5"],"emoji":"🚴🏿‍♂️","text":"","type":1,"order":2287,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生骑自行车","name":"BICYCLIST, FEMALE SIGN","hexcode":"1F6B4-200D-2640-FE0F","shortcodes":["woman_biking"],"tags":["单车","女","自行车","骑车"],"emoji":"🚴‍♀️","text":"","type":1,"order":2289,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生骑自行车: 较浅肤色","name":"BICYCLIST, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6B4-1F3FB-200D-2640-FE0F","shortcodes":["woman_biking_tone1"],"emoji":"🚴🏻‍♀️","text":"","type":1,"order":2291,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生骑自行车: 中等-浅肤色","name":"BICYCLIST, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6B4-1F3FC-200D-2640-FE0F","shortcodes":["woman_biking_tone2"],"emoji":"🚴🏼‍♀️","text":"","type":1,"order":2293,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生骑自行车: 中等肤色","name":"BICYCLIST, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6B4-1F3FD-200D-2640-FE0F","shortcodes":["woman_biking_tone3"],"emoji":"🚴🏽‍♀️","text":"","type":1,"order":2295,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生骑自行车: 中等-深肤色","name":"BICYCLIST, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6B4-1F3FE-200D-2640-FE0F","shortcodes":["woman_biking_tone4"],"emoji":"🚴🏾‍♀️","text":"","type":1,"order":2297,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生骑自行车: 较深肤色","name":"BICYCLIST, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6B4-1F3FF-200D-2640-FE0F","shortcodes":["woman_biking_tone5"],"emoji":"🚴🏿‍♀️","text":"","type":1,"order":2299,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"骑山地车","name":"MOUNTAIN BICYCLIST","hexcode":"1F6B5","shortcodes":["person_mountain_biking"],"tags":["单车","山地车","自行车","骑山地车的人"],"emoji":"🚵","text":"","type":1,"order":2301,"group":1,"subgroup":27,"version":1,"skins":[{"annotation":"骑山地车: 较浅肤色","name":"MOUNTAIN BICYCLIST, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6B5-1F3FB","shortcodes":["person_mountain_biking_tone1"],"emoji":"🚵🏻","text":"","type":1,"order":2302,"group":1,"subgroup":27,"version":1,"tone":1},{"annotation":"骑山地车: 中等-浅肤色","name":"MOUNTAIN BICYCLIST, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6B5-1F3FC","shortcodes":["person_mountain_biking_tone2"],"emoji":"🚵🏼","text":"","type":1,"order":2303,"group":1,"subgroup":27,"version":1,"tone":2},{"annotation":"骑山地车: 中等肤色","name":"MOUNTAIN BICYCLIST, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6B5-1F3FD","shortcodes":["person_mountain_biking_tone3"],"emoji":"🚵🏽","text":"","type":1,"order":2304,"group":1,"subgroup":27,"version":1,"tone":3},{"annotation":"骑山地车: 中等-深肤色","name":"MOUNTAIN BICYCLIST, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6B5-1F3FE","shortcodes":["person_mountain_biking_tone4"],"emoji":"🚵🏾","text":"","type":1,"order":2305,"group":1,"subgroup":27,"version":1,"tone":4},{"annotation":"骑山地车: 较深肤色","name":"MOUNTAIN BICYCLIST, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6B5-1F3FF","shortcodes":["person_mountain_biking_tone5"],"emoji":"🚵🏿","text":"","type":1,"order":2306,"group":1,"subgroup":27,"version":1,"tone":5}]},{"annotation":"男生骑山地车","name":"MOUNTAIN BICYCLIST, MALE SIGN","hexcode":"1F6B5-200D-2642-FE0F","shortcodes":["man_mountain_biking"],"tags":["单车","山地车","男","自行车","骑山地车的人"],"emoji":"🚵‍♂️","text":"","type":1,"order":2307,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生骑山地车: 较浅肤色","name":"MOUNTAIN BICYCLIST, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6B5-1F3FB-200D-2642-FE0F","shortcodes":["man_mountain_biking_tone1"],"emoji":"🚵🏻‍♂️","text":"","type":1,"order":2309,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生骑山地车: 中等-浅肤色","name":"MOUNTAIN BICYCLIST, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6B5-1F3FC-200D-2642-FE0F","shortcodes":["man_mountain_biking_tone2"],"emoji":"🚵🏼‍♂️","text":"","type":1,"order":2311,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生骑山地车: 中等肤色","name":"MOUNTAIN BICYCLIST, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6B5-1F3FD-200D-2642-FE0F","shortcodes":["man_mountain_biking_tone3"],"emoji":"🚵🏽‍♂️","text":"","type":1,"order":2313,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生骑山地车: 中等-深肤色","name":"MOUNTAIN BICYCLIST, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6B5-1F3FE-200D-2642-FE0F","shortcodes":["man_mountain_biking_tone4"],"emoji":"🚵🏾‍♂️","text":"","type":1,"order":2315,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生骑山地车: 较深肤色","name":"MOUNTAIN BICYCLIST, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6B5-1F3FF-200D-2642-FE0F","shortcodes":["man_mountain_biking_tone5"],"emoji":"🚵🏿‍♂️","text":"","type":1,"order":2317,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生骑山地车","name":"MOUNTAIN BICYCLIST, FEMALE SIGN","hexcode":"1F6B5-200D-2640-FE0F","shortcodes":["woman_mountain_biking"],"tags":["单车","女","山地车","自行车","骑车"],"emoji":"🚵‍♀️","text":"","type":1,"order":2319,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生骑山地车: 较浅肤色","name":"MOUNTAIN BICYCLIST, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6B5-1F3FB-200D-2640-FE0F","shortcodes":["woman_mountain_biking_tone1"],"emoji":"🚵🏻‍♀️","text":"","type":1,"order":2321,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生骑山地车: 中等-浅肤色","name":"MOUNTAIN BICYCLIST, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6B5-1F3FC-200D-2640-FE0F","shortcodes":["woman_mountain_biking_tone2"],"emoji":"🚵🏼‍♀️","text":"","type":1,"order":2323,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生骑山地车: 中等肤色","name":"MOUNTAIN BICYCLIST, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6B5-1F3FD-200D-2640-FE0F","shortcodes":["woman_mountain_biking_tone3"],"emoji":"🚵🏽‍♀️","text":"","type":1,"order":2325,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生骑山地车: 中等-深肤色","name":"MOUNTAIN BICYCLIST, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6B5-1F3FE-200D-2640-FE0F","shortcodes":["woman_mountain_biking_tone4"],"emoji":"🚵🏾‍♀️","text":"","type":1,"order":2327,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生骑山地车: 较深肤色","name":"MOUNTAIN BICYCLIST, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6B5-1F3FF-200D-2640-FE0F","shortcodes":["woman_mountain_biking_tone5"],"emoji":"🚵🏿‍♀️","text":"","type":1,"order":2329,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"侧手翻","name":"PERSON DOING CARTWHEEL","hexcode":"1F938","shortcodes":["person_cartwheel"],"tags":["人","体操","体育","翻筋斗"],"emoji":"🤸","text":"","type":1,"order":2331,"group":1,"subgroup":27,"version":3,"skins":[{"annotation":"侧手翻: 较浅肤色","name":"PERSON DOING CARTWHEEL, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F938-1F3FB","shortcodes":["person_cartwheel_tone1"],"emoji":"🤸🏻","text":"","type":1,"order":2332,"group":1,"subgroup":27,"version":3,"tone":1},{"annotation":"侧手翻: 中等-浅肤色","name":"PERSON DOING CARTWHEEL, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F938-1F3FC","shortcodes":["person_cartwheel_tone2"],"emoji":"🤸🏼","text":"","type":1,"order":2333,"group":1,"subgroup":27,"version":3,"tone":2},{"annotation":"侧手翻: 中等肤色","name":"PERSON DOING CARTWHEEL, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F938-1F3FD","shortcodes":["person_cartwheel_tone3"],"emoji":"🤸🏽","text":"","type":1,"order":2334,"group":1,"subgroup":27,"version":3,"tone":3},{"annotation":"侧手翻: 中等-深肤色","name":"PERSON DOING CARTWHEEL, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F938-1F3FE","shortcodes":["person_cartwheel_tone4"],"emoji":"🤸🏾","text":"","type":1,"order":2335,"group":1,"subgroup":27,"version":3,"tone":4},{"annotation":"侧手翻: 较深肤色","name":"PERSON DOING CARTWHEEL, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F938-1F3FF","shortcodes":["person_cartwheel_tone5"],"emoji":"🤸🏿","text":"","type":1,"order":2336,"group":1,"subgroup":27,"version":3,"tone":5}]},{"annotation":"男生侧手翻","name":"PERSON DOING CARTWHEEL, MALE SIGN","hexcode":"1F938-200D-2642-FE0F","shortcodes":["man_cartwheeling"],"tags":["体操","侧手翻","男","翻筋斗"],"emoji":"🤸‍♂️","text":"","type":1,"order":2337,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生侧手翻: 较浅肤色","name":"PERSON DOING CARTWHEEL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F938-1F3FB-200D-2642-FE0F","shortcodes":["man_cartwheeling_tone1"],"emoji":"🤸🏻‍♂️","text":"","type":1,"order":2339,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生侧手翻: 中等-浅肤色","name":"PERSON DOING CARTWHEEL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F938-1F3FC-200D-2642-FE0F","shortcodes":["man_cartwheeling_tone2"],"emoji":"🤸🏼‍♂️","text":"","type":1,"order":2341,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生侧手翻: 中等肤色","name":"PERSON DOING CARTWHEEL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F938-1F3FD-200D-2642-FE0F","shortcodes":["man_cartwheeling_tone3"],"emoji":"🤸🏽‍♂️","text":"","type":1,"order":2343,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生侧手翻: 中等-深肤色","name":"PERSON DOING CARTWHEEL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F938-1F3FE-200D-2642-FE0F","shortcodes":["man_cartwheeling_tone4"],"emoji":"🤸🏾‍♂️","text":"","type":1,"order":2345,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生侧手翻: 较深肤色","name":"PERSON DOING CARTWHEEL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F938-1F3FF-200D-2642-FE0F","shortcodes":["man_cartwheeling_tone5"],"emoji":"🤸🏿‍♂️","text":"","type":1,"order":2347,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生侧手翻","name":"PERSON DOING CARTWHEEL, FEMALE SIGN","hexcode":"1F938-200D-2640-FE0F","shortcodes":["woman_cartwheeling"],"tags":["体操","侧手翻","女","翻筋斗"],"emoji":"🤸‍♀️","text":"","type":1,"order":2349,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生侧手翻: 较浅肤色","name":"PERSON DOING CARTWHEEL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F938-1F3FB-200D-2640-FE0F","shortcodes":["woman_cartwheeling_tone1"],"emoji":"🤸🏻‍♀️","text":"","type":1,"order":2351,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生侧手翻: 中等-浅肤色","name":"PERSON DOING CARTWHEEL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F938-1F3FC-200D-2640-FE0F","shortcodes":["woman_cartwheeling_tone2"],"emoji":"🤸🏼‍♀️","text":"","type":1,"order":2353,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生侧手翻: 中等肤色","name":"PERSON DOING CARTWHEEL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F938-1F3FD-200D-2640-FE0F","shortcodes":["woman_cartwheeling_tone3"],"emoji":"🤸🏽‍♀️","text":"","type":1,"order":2355,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生侧手翻: 中等-深肤色","name":"PERSON DOING CARTWHEEL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F938-1F3FE-200D-2640-FE0F","shortcodes":["woman_cartwheeling_tone4"],"emoji":"🤸🏾‍♀️","text":"","type":1,"order":2357,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生侧手翻: 较深肤色","name":"PERSON DOING CARTWHEEL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F938-1F3FF-200D-2640-FE0F","shortcodes":["woman_cartwheeling_tone5"],"emoji":"🤸🏿‍♀️","text":"","type":1,"order":2359,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"摔跤选手","name":"WRESTLERS","hexcode":"1F93C","shortcodes":["people_wrestling"],"tags":["人","体育","摔跤"],"emoji":"🤼","text":"","type":1,"order":2361,"group":1,"subgroup":27,"version":3},{"annotation":"男生摔跤","name":"WRESTLERS, MALE SIGN","hexcode":"1F93C-200D-2642-FE0F","shortcodes":["men_wrestling"],"tags":["打架","摔跤","男"],"emoji":"🤼‍♂️","text":"","type":1,"order":2362,"group":1,"subgroup":27,"version":4,"gender":1},{"annotation":"女生摔跤","name":"WRESTLERS, FEMALE SIGN","hexcode":"1F93C-200D-2640-FE0F","shortcodes":["women_wrestling"],"tags":["女","打架","摔跤"],"emoji":"🤼‍♀️","text":"","type":1,"order":2364,"group":1,"subgroup":27,"version":4,"gender":0},{"annotation":"水球","name":"WATER POLO","hexcode":"1F93D","shortcodes":["person_water_polo"],"tags":["人","体育"],"emoji":"🤽","text":"","type":1,"order":2366,"group":1,"subgroup":27,"version":3,"skins":[{"annotation":"水球: 较浅肤色","name":"WATER POLO, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F93D-1F3FB","shortcodes":["person_water_polo_tone1"],"emoji":"🤽🏻","text":"","type":1,"order":2367,"group":1,"subgroup":27,"version":3,"tone":1},{"annotation":"水球: 中等-浅肤色","name":"WATER POLO, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F93D-1F3FC","shortcodes":["person_water_polo_tone2"],"emoji":"🤽🏼","text":"","type":1,"order":2368,"group":1,"subgroup":27,"version":3,"tone":2},{"annotation":"水球: 中等肤色","name":"WATER POLO, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F93D-1F3FD","shortcodes":["person_water_polo_tone3"],"emoji":"🤽🏽","text":"","type":1,"order":2369,"group":1,"subgroup":27,"version":3,"tone":3},{"annotation":"水球: 中等-深肤色","name":"WATER POLO, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F93D-1F3FE","shortcodes":["person_water_polo_tone4"],"emoji":"🤽🏾","text":"","type":1,"order":2370,"group":1,"subgroup":27,"version":3,"tone":4},{"annotation":"水球: 较深肤色","name":"WATER POLO, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F93D-1F3FF","shortcodes":["person_water_polo_tone5"],"emoji":"🤽🏿","text":"","type":1,"order":2371,"group":1,"subgroup":27,"version":3,"tone":5}]},{"annotation":"男生玩水球","name":"WATER POLO, MALE SIGN","hexcode":"1F93D-200D-2642-FE0F","shortcodes":["man_water_polo"],"tags":["水球","男"],"emoji":"🤽‍♂️","text":"","type":1,"order":2372,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生玩水球: 较浅肤色","name":"WATER POLO, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F93D-1F3FB-200D-2642-FE0F","shortcodes":["man_water_polo_tone1"],"emoji":"🤽🏻‍♂️","text":"","type":1,"order":2374,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生玩水球: 中等-浅肤色","name":"WATER POLO, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F93D-1F3FC-200D-2642-FE0F","shortcodes":["man_water_polo_tone2"],"emoji":"🤽🏼‍♂️","text":"","type":1,"order":2376,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生玩水球: 中等肤色","name":"WATER POLO, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F93D-1F3FD-200D-2642-FE0F","shortcodes":["man_water_polo_tone3"],"emoji":"🤽🏽‍♂️","text":"","type":1,"order":2378,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生玩水球: 中等-深肤色","name":"WATER POLO, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F93D-1F3FE-200D-2642-FE0F","shortcodes":["man_water_polo_tone4"],"emoji":"🤽🏾‍♂️","text":"","type":1,"order":2380,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生玩水球: 较深肤色","name":"WATER POLO, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F93D-1F3FF-200D-2642-FE0F","shortcodes":["man_water_polo_tone5"],"emoji":"🤽🏿‍♂️","text":"","type":1,"order":2382,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生玩水球","name":"WATER POLO, FEMALE SIGN","hexcode":"1F93D-200D-2640-FE0F","shortcodes":["woman_water_polo"],"tags":["女","水球"],"emoji":"🤽‍♀️","text":"","type":1,"order":2384,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生玩水球: 较浅肤色","name":"WATER POLO, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F93D-1F3FB-200D-2640-FE0F","shortcodes":["woman_water_polo_tone1"],"emoji":"🤽🏻‍♀️","text":"","type":1,"order":2386,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生玩水球: 中等-浅肤色","name":"WATER POLO, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F93D-1F3FC-200D-2640-FE0F","shortcodes":["woman_water_polo_tone2"],"emoji":"🤽🏼‍♀️","text":"","type":1,"order":2388,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生玩水球: 中等肤色","name":"WATER POLO, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F93D-1F3FD-200D-2640-FE0F","shortcodes":["woman_water_polo_tone3"],"emoji":"🤽🏽‍♀️","text":"","type":1,"order":2390,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生玩水球: 中等-深肤色","name":"WATER POLO, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F93D-1F3FE-200D-2640-FE0F","shortcodes":["woman_water_polo_tone4"],"emoji":"🤽🏾‍♀️","text":"","type":1,"order":2392,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生玩水球: 较深肤色","name":"WATER POLO, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F93D-1F3FF-200D-2640-FE0F","shortcodes":["woman_water_polo_tone5"],"emoji":"🤽🏿‍♀️","text":"","type":1,"order":2394,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"手球","name":"HANDBALL","hexcode":"1F93E","shortcodes":["person_handball"],"tags":["人","体育"],"emoji":"🤾","text":"","type":1,"order":2396,"group":1,"subgroup":27,"version":3,"skins":[{"annotation":"手球: 较浅肤色","name":"HANDBALL, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F93E-1F3FB","shortcodes":["person_handball_tone1"],"emoji":"🤾🏻","text":"","type":1,"order":2397,"group":1,"subgroup":27,"version":3,"tone":1},{"annotation":"手球: 中等-浅肤色","name":"HANDBALL, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F93E-1F3FC","shortcodes":["person_handball_tone2"],"emoji":"🤾🏼","text":"","type":1,"order":2398,"group":1,"subgroup":27,"version":3,"tone":2},{"annotation":"手球: 中等肤色","name":"HANDBALL, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F93E-1F3FD","shortcodes":["person_handball_tone3"],"emoji":"🤾🏽","text":"","type":1,"order":2399,"group":1,"subgroup":27,"version":3,"tone":3},{"annotation":"手球: 中等-深肤色","name":"HANDBALL, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F93E-1F3FE","shortcodes":["person_handball_tone4"],"emoji":"🤾🏾","text":"","type":1,"order":2400,"group":1,"subgroup":27,"version":3,"tone":4},{"annotation":"手球: 较深肤色","name":"HANDBALL, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F93E-1F3FF","shortcodes":["person_handball_tone5"],"emoji":"🤾🏿","text":"","type":1,"order":2401,"group":1,"subgroup":27,"version":3,"tone":5}]},{"annotation":"男生玩手球","name":"HANDBALL, MALE SIGN","hexcode":"1F93E-200D-2642-FE0F","shortcodes":["man_handball"],"tags":["手球","男"],"emoji":"🤾‍♂️","text":"","type":1,"order":2402,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生玩手球: 较浅肤色","name":"HANDBALL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F93E-1F3FB-200D-2642-FE0F","shortcodes":["man_handball_tone1"],"emoji":"🤾🏻‍♂️","text":"","type":1,"order":2404,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生玩手球: 中等-浅肤色","name":"HANDBALL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F93E-1F3FC-200D-2642-FE0F","shortcodes":["man_handball_tone2"],"emoji":"🤾🏼‍♂️","text":"","type":1,"order":2406,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生玩手球: 中等肤色","name":"HANDBALL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F93E-1F3FD-200D-2642-FE0F","shortcodes":["man_handball_tone3"],"emoji":"🤾🏽‍♂️","text":"","type":1,"order":2408,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生玩手球: 中等-深肤色","name":"HANDBALL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F93E-1F3FE-200D-2642-FE0F","shortcodes":["man_handball_tone4"],"emoji":"🤾🏾‍♂️","text":"","type":1,"order":2410,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生玩手球: 较深肤色","name":"HANDBALL, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F93E-1F3FF-200D-2642-FE0F","shortcodes":["man_handball_tone5"],"emoji":"🤾🏿‍♂️","text":"","type":1,"order":2412,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生玩手球","name":"HANDBALL, FEMALE SIGN","hexcode":"1F93E-200D-2640-FE0F","shortcodes":["woman_handball"],"tags":["女","手球"],"emoji":"🤾‍♀️","text":"","type":1,"order":2414,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生玩手球: 较浅肤色","name":"HANDBALL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F93E-1F3FB-200D-2640-FE0F","shortcodes":["woman_handball_tone1"],"emoji":"🤾🏻‍♀️","text":"","type":1,"order":2416,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生玩手球: 中等-浅肤色","name":"HANDBALL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F93E-1F3FC-200D-2640-FE0F","shortcodes":["woman_handball_tone2"],"emoji":"🤾🏼‍♀️","text":"","type":1,"order":2418,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生玩手球: 中等肤色","name":"HANDBALL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F93E-1F3FD-200D-2640-FE0F","shortcodes":["woman_handball_tone3"],"emoji":"🤾🏽‍♀️","text":"","type":1,"order":2420,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生玩手球: 中等-深肤色","name":"HANDBALL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F93E-1F3FE-200D-2640-FE0F","shortcodes":["woman_handball_tone4"],"emoji":"🤾🏾‍♀️","text":"","type":1,"order":2422,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生玩手球: 较深肤色","name":"HANDBALL, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F93E-1F3FF-200D-2640-FE0F","shortcodes":["woman_handball_tone5"],"emoji":"🤾🏿‍♀️","text":"","type":1,"order":2424,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"抛接杂耍","name":"JUGGLING","hexcode":"1F939","shortcodes":["person_juggling"],"tags":["平衡","抛接","杂技","杂耍"],"emoji":"🤹","text":"","type":1,"order":2426,"group":1,"subgroup":27,"version":3,"skins":[{"annotation":"抛接杂耍: 较浅肤色","name":"JUGGLING, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F939-1F3FB","shortcodes":["person_juggling_tone1"],"emoji":"🤹🏻","text":"","type":1,"order":2427,"group":1,"subgroup":27,"version":3,"tone":1},{"annotation":"抛接杂耍: 中等-浅肤色","name":"JUGGLING, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F939-1F3FC","shortcodes":["person_juggling_tone2"],"emoji":"🤹🏼","text":"","type":1,"order":2428,"group":1,"subgroup":27,"version":3,"tone":2},{"annotation":"抛接杂耍: 中等肤色","name":"JUGGLING, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F939-1F3FD","shortcodes":["person_juggling_tone3"],"emoji":"🤹🏽","text":"","type":1,"order":2429,"group":1,"subgroup":27,"version":3,"tone":3},{"annotation":"抛接杂耍: 中等-深肤色","name":"JUGGLING, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F939-1F3FE","shortcodes":["person_juggling_tone4"],"emoji":"🤹🏾","text":"","type":1,"order":2430,"group":1,"subgroup":27,"version":3,"tone":4},{"annotation":"抛接杂耍: 较深肤色","name":"JUGGLING, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F939-1F3FF","shortcodes":["person_juggling_tone5"],"emoji":"🤹🏿","text":"","type":1,"order":2431,"group":1,"subgroup":27,"version":3,"tone":5}]},{"annotation":"男生抛接杂耍","name":"JUGGLING, MALE SIGN","hexcode":"1F939-200D-2642-FE0F","shortcodes":["man_juggling"],"tags":["杂技","杂耍","男","颠球"],"emoji":"🤹‍♂️","text":"","type":1,"order":2432,"group":1,"subgroup":27,"version":4,"gender":1,"skins":[{"annotation":"男生抛接杂耍: 较浅肤色","name":"JUGGLING, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F939-1F3FB-200D-2642-FE0F","shortcodes":["man_juggling_tone1"],"emoji":"🤹🏻‍♂️","text":"","type":1,"order":2434,"group":1,"subgroup":27,"version":4,"gender":1,"tone":1},{"annotation":"男生抛接杂耍: 中等-浅肤色","name":"JUGGLING, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F939-1F3FC-200D-2642-FE0F","shortcodes":["man_juggling_tone2"],"emoji":"🤹🏼‍♂️","text":"","type":1,"order":2436,"group":1,"subgroup":27,"version":4,"gender":1,"tone":2},{"annotation":"男生抛接杂耍: 中等肤色","name":"JUGGLING, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F939-1F3FD-200D-2642-FE0F","shortcodes":["man_juggling_tone3"],"emoji":"🤹🏽‍♂️","text":"","type":1,"order":2438,"group":1,"subgroup":27,"version":4,"gender":1,"tone":3},{"annotation":"男生抛接杂耍: 中等-深肤色","name":"JUGGLING, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F939-1F3FE-200D-2642-FE0F","shortcodes":["man_juggling_tone4"],"emoji":"🤹🏾‍♂️","text":"","type":1,"order":2440,"group":1,"subgroup":27,"version":4,"gender":1,"tone":4},{"annotation":"男生抛接杂耍: 较深肤色","name":"JUGGLING, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F939-1F3FF-200D-2642-FE0F","shortcodes":["man_juggling_tone5"],"emoji":"🤹🏿‍♂️","text":"","type":1,"order":2442,"group":1,"subgroup":27,"version":4,"gender":1,"tone":5}]},{"annotation":"女生抛接杂耍","name":"JUGGLING, FEMALE SIGN","hexcode":"1F939-200D-2640-FE0F","shortcodes":["woman_juggling"],"tags":["女","杂技","杂耍","颠球"],"emoji":"🤹‍♀️","text":"","type":1,"order":2444,"group":1,"subgroup":27,"version":4,"gender":0,"skins":[{"annotation":"女生抛接杂耍: 较浅肤色","name":"JUGGLING, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F939-1F3FB-200D-2640-FE0F","shortcodes":["woman_juggling_tone1"],"emoji":"🤹🏻‍♀️","text":"","type":1,"order":2446,"group":1,"subgroup":27,"version":4,"gender":0,"tone":1},{"annotation":"女生抛接杂耍: 中等-浅肤色","name":"JUGGLING, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F939-1F3FC-200D-2640-FE0F","shortcodes":["woman_juggling_tone2"],"emoji":"🤹🏼‍♀️","text":"","type":1,"order":2448,"group":1,"subgroup":27,"version":4,"gender":0,"tone":2},{"annotation":"女生抛接杂耍: 中等肤色","name":"JUGGLING, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F939-1F3FD-200D-2640-FE0F","shortcodes":["woman_juggling_tone3"],"emoji":"🤹🏽‍♀️","text":"","type":1,"order":2450,"group":1,"subgroup":27,"version":4,"gender":0,"tone":3},{"annotation":"女生抛接杂耍: 中等-深肤色","name":"JUGGLING, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F939-1F3FE-200D-2640-FE0F","shortcodes":["woman_juggling_tone4"],"emoji":"🤹🏾‍♀️","text":"","type":1,"order":2452,"group":1,"subgroup":27,"version":4,"gender":0,"tone":4},{"annotation":"女生抛接杂耍: 较深肤色","name":"JUGGLING, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F939-1F3FF-200D-2640-FE0F","shortcodes":["woman_juggling_tone5"],"emoji":"🤹🏿‍♀️","text":"","type":1,"order":2454,"group":1,"subgroup":27,"version":4,"gender":0,"tone":5}]},{"annotation":"盘腿的人","name":"PERSON IN LOTUS POSITION","hexcode":"1F9D8","shortcodes":["person_lotus_position"],"tags":["冥想","瑜伽"],"emoji":"🧘","text":"","type":1,"order":2456,"group":1,"subgroup":28,"version":5,"skins":[{"annotation":"盘腿的人: 较浅肤色","name":"PERSON IN LOTUS POSITION, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D8-1F3FB","shortcodes":["person_lotus_position_tone1"],"emoji":"🧘🏻","text":"","type":1,"order":2457,"group":1,"subgroup":28,"version":5,"tone":1},{"annotation":"盘腿的人: 中等-浅肤色","name":"PERSON IN LOTUS POSITION, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D8-1F3FC","shortcodes":["person_lotus_position_tone2"],"emoji":"🧘🏼","text":"","type":1,"order":2458,"group":1,"subgroup":28,"version":5,"tone":2},{"annotation":"盘腿的人: 中等肤色","name":"PERSON IN LOTUS POSITION, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D8-1F3FD","shortcodes":["person_lotus_position_tone3"],"emoji":"🧘🏽","text":"","type":1,"order":2459,"group":1,"subgroup":28,"version":5,"tone":3},{"annotation":"盘腿的人: 中等-深肤色","name":"PERSON IN LOTUS POSITION, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D8-1F3FE","shortcodes":["person_lotus_position_tone4"],"emoji":"🧘🏾","text":"","type":1,"order":2460,"group":1,"subgroup":28,"version":5,"tone":4},{"annotation":"盘腿的人: 较深肤色","name":"PERSON IN LOTUS POSITION, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D8-1F3FF","shortcodes":["person_lotus_position_tone5"],"emoji":"🧘🏿","text":"","type":1,"order":2461,"group":1,"subgroup":28,"version":5,"tone":5}]},{"annotation":"盘腿的男人","name":"PERSON IN LOTUS POSITION, MALE SIGN","hexcode":"1F9D8-200D-2642-FE0F","shortcodes":["man_lotus_position"],"tags":["和尚","瑜伽男"],"emoji":"🧘‍♂️","text":"","type":1,"order":2462,"group":1,"subgroup":28,"version":5,"gender":1,"skins":[{"annotation":"盘腿的男人: 较浅肤色","name":"PERSON IN LOTUS POSITION, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D8-1F3FB-200D-2642-FE0F","shortcodes":["man_lotus_position_tone1"],"emoji":"🧘🏻‍♂️","text":"","type":1,"order":2464,"group":1,"subgroup":28,"version":5,"gender":1,"tone":1},{"annotation":"盘腿的男人: 中等-浅肤色","name":"PERSON IN LOTUS POSITION, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D8-1F3FC-200D-2642-FE0F","shortcodes":["man_lotus_position_tone2"],"emoji":"🧘🏼‍♂️","text":"","type":1,"order":2466,"group":1,"subgroup":28,"version":5,"gender":1,"tone":2},{"annotation":"盘腿的男人: 中等肤色","name":"PERSON IN LOTUS POSITION, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D8-1F3FD-200D-2642-FE0F","shortcodes":["man_lotus_position_tone3"],"emoji":"🧘🏽‍♂️","text":"","type":1,"order":2468,"group":1,"subgroup":28,"version":5,"gender":1,"tone":3},{"annotation":"盘腿的男人: 中等-深肤色","name":"PERSON IN LOTUS POSITION, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D8-1F3FE-200D-2642-FE0F","shortcodes":["man_lotus_position_tone4"],"emoji":"🧘🏾‍♂️","text":"","type":1,"order":2470,"group":1,"subgroup":28,"version":5,"gender":1,"tone":4},{"annotation":"盘腿的男人: 较深肤色","name":"PERSON IN LOTUS POSITION, MALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D8-1F3FF-200D-2642-FE0F","shortcodes":["man_lotus_position_tone5"],"emoji":"🧘🏿‍♂️","text":"","type":1,"order":2472,"group":1,"subgroup":28,"version":5,"gender":1,"tone":5}]},{"annotation":"盘腿的女人","name":"PERSON IN LOTUS POSITION, FEMALE SIGN","hexcode":"1F9D8-200D-2640-FE0F","shortcodes":["woman_lotus_position"],"tags":["尼姑","比丘尼","瑜伽女"],"emoji":"🧘‍♀️","text":"","type":1,"order":2474,"group":1,"subgroup":28,"version":5,"gender":0,"skins":[{"annotation":"盘腿的女人: 较浅肤色","name":"PERSON IN LOTUS POSITION, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D8-1F3FB-200D-2640-FE0F","shortcodes":["woman_lotus_position_tone1"],"emoji":"🧘🏻‍♀️","text":"","type":1,"order":2476,"group":1,"subgroup":28,"version":5,"gender":0,"tone":1},{"annotation":"盘腿的女人: 中等-浅肤色","name":"PERSON IN LOTUS POSITION, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D8-1F3FC-200D-2640-FE0F","shortcodes":["woman_lotus_position_tone2"],"emoji":"🧘🏼‍♀️","text":"","type":1,"order":2478,"group":1,"subgroup":28,"version":5,"gender":0,"tone":2},{"annotation":"盘腿的女人: 中等肤色","name":"PERSON IN LOTUS POSITION, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D8-1F3FD-200D-2640-FE0F","shortcodes":["woman_lotus_position_tone3"],"emoji":"🧘🏽‍♀️","text":"","type":1,"order":2480,"group":1,"subgroup":28,"version":5,"gender":0,"tone":3},{"annotation":"盘腿的女人: 中等-深肤色","name":"PERSON IN LOTUS POSITION, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D8-1F3FE-200D-2640-FE0F","shortcodes":["woman_lotus_position_tone4"],"emoji":"🧘🏾‍♀️","text":"","type":1,"order":2482,"group":1,"subgroup":28,"version":5,"gender":0,"tone":4},{"annotation":"盘腿的女人: 较深肤色","name":"PERSON IN LOTUS POSITION, FEMALE SIGN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D8-1F3FF-200D-2640-FE0F","shortcodes":["woman_lotus_position_tone5"],"emoji":"🧘🏿‍♀️","text":"","type":1,"order":2484,"group":1,"subgroup":28,"version":5,"gender":0,"tone":5}]},{"annotation":"洗澡的人","name":"BATH","hexcode":"1F6C0","shortcodes":["bath"],"tags":["洗澡","浴缸"],"emoji":"🛀","text":"","type":1,"order":2486,"group":1,"subgroup":28,"version":0.6,"skins":[{"annotation":"洗澡的人: 较浅肤色","name":"BATH, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6C0-1F3FB","shortcodes":["bath_tone1"],"emoji":"🛀🏻","text":"","type":1,"order":2487,"group":1,"subgroup":28,"version":1,"tone":1},{"annotation":"洗澡的人: 中等-浅肤色","name":"BATH, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6C0-1F3FC","shortcodes":["bath_tone2"],"emoji":"🛀🏼","text":"","type":1,"order":2488,"group":1,"subgroup":28,"version":1,"tone":2},{"annotation":"洗澡的人: 中等肤色","name":"BATH, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6C0-1F3FD","shortcodes":["bath_tone3"],"emoji":"🛀🏽","text":"","type":1,"order":2489,"group":1,"subgroup":28,"version":1,"tone":3},{"annotation":"洗澡的人: 中等-深肤色","name":"BATH, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6C0-1F3FE","shortcodes":["bath_tone4"],"emoji":"🛀🏾","text":"","type":1,"order":2490,"group":1,"subgroup":28,"version":1,"tone":4},{"annotation":"洗澡的人: 较深肤色","name":"BATH, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6C0-1F3FF","shortcodes":["bath_tone5"],"emoji":"🛀🏿","text":"","type":1,"order":2491,"group":1,"subgroup":28,"version":1,"tone":5}]},{"annotation":"躺在床上的人","name":"SLEEPING ACCOMMODATION","hexcode":"1F6CC","shortcodes":["in_bed"],"tags":["入睡","宾馆","酒店"],"emoji":"🛌","text":"","type":1,"order":2492,"group":1,"subgroup":28,"version":1,"skins":[{"annotation":"躺在床上的人: 较浅肤色","name":"SLEEPING ACCOMMODATION, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F6CC-1F3FB","shortcodes":["in_bed_tone1"],"emoji":"🛌🏻","text":"","type":1,"order":2493,"group":1,"subgroup":28,"version":4,"tone":1},{"annotation":"躺在床上的人: 中等-浅肤色","name":"SLEEPING ACCOMMODATION, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F6CC-1F3FC","shortcodes":["in_bed_tone2"],"emoji":"🛌🏼","text":"","type":1,"order":2494,"group":1,"subgroup":28,"version":4,"tone":2},{"annotation":"躺在床上的人: 中等肤色","name":"SLEEPING ACCOMMODATION, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F6CC-1F3FD","shortcodes":["in_bed_tone3"],"emoji":"🛌🏽","text":"","type":1,"order":2495,"group":1,"subgroup":28,"version":4,"tone":3},{"annotation":"躺在床上的人: 中等-深肤色","name":"SLEEPING ACCOMMODATION, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F6CC-1F3FE","shortcodes":["in_bed_tone4"],"emoji":"🛌🏾","text":"","type":1,"order":2496,"group":1,"subgroup":28,"version":4,"tone":4},{"annotation":"躺在床上的人: 较深肤色","name":"SLEEPING ACCOMMODATION, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F6CC-1F3FF","shortcodes":["in_bed_tone5"],"emoji":"🛌🏿","text":"","type":1,"order":2497,"group":1,"subgroup":28,"version":4,"tone":5}]},{"annotation":"手拉手的两个人","name":"ADULT, HANDSHAKE, ADULT","hexcode":"1F9D1-200D-1F91D-200D-1F9D1","shortcodes":["holding_hands_people"],"tags":["人","情侣","手","拉手","握手"],"emoji":"🧑‍🤝‍🧑","text":"","type":1,"order":2498,"group":1,"subgroup":29,"version":12,"skins":[{"annotation":"手拉手的两个人: 较浅肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D1-1F3FB-200D-1F91D-200D-1F9D1-1F3FB","shortcodes":["holding_hands_people_tone1"],"emoji":"🧑🏻‍🤝‍🧑🏻","text":"","type":1,"order":2499,"group":1,"subgroup":29,"version":12,"tone":1},{"annotation":"手拉手的两个人: 较浅肤色中等-浅肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D1-1F3FB-200D-1F91D-200D-1F9D1-1F3FC","shortcodes":["holding_hands_people_tone1-2"],"emoji":"🧑🏻‍🤝‍🧑🏼","text":"","type":1,"order":2500,"group":1,"subgroup":29,"version":12.1,"tone":[1,2]},{"annotation":"手拉手的两个人: 较浅肤色中等肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D1-1F3FB-200D-1F91D-200D-1F9D1-1F3FD","shortcodes":["holding_hands_people_tone1-3"],"emoji":"🧑🏻‍🤝‍🧑🏽","text":"","type":1,"order":2501,"group":1,"subgroup":29,"version":12.1,"tone":[1,3]},{"annotation":"手拉手的两个人: 较浅肤色中等-深肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D1-1F3FB-200D-1F91D-200D-1F9D1-1F3FE","shortcodes":["holding_hands_people_tone1-4"],"emoji":"🧑🏻‍🤝‍🧑🏾","text":"","type":1,"order":2502,"group":1,"subgroup":29,"version":12.1,"tone":[1,4]},{"annotation":"手拉手的两个人: 较浅肤色较深肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D1-1F3FB-200D-1F91D-200D-1F9D1-1F3FF","shortcodes":["holding_hands_people_tone1-5"],"emoji":"🧑🏻‍🤝‍🧑🏿","text":"","type":1,"order":2503,"group":1,"subgroup":29,"version":12.1,"tone":[1,5]},{"annotation":"手拉手的两个人: 中等-浅肤色较浅肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D1-1F3FC-200D-1F91D-200D-1F9D1-1F3FB","shortcodes":["holding_hands_people_tone2-1"],"emoji":"🧑🏼‍🤝‍🧑🏻","text":"","type":1,"order":2504,"group":1,"subgroup":29,"version":12,"tone":[2,1]},{"annotation":"手拉手的两个人: 中等-浅肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D1-1F3FC-200D-1F91D-200D-1F9D1-1F3FC","shortcodes":["holding_hands_people_tone2"],"emoji":"🧑🏼‍🤝‍🧑🏼","text":"","type":1,"order":2505,"group":1,"subgroup":29,"version":12,"tone":2},{"annotation":"手拉手的两个人: 中等-浅肤色中等肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D1-1F3FC-200D-1F91D-200D-1F9D1-1F3FD","shortcodes":["holding_hands_people_tone2-3"],"emoji":"🧑🏼‍🤝‍🧑🏽","text":"","type":1,"order":2506,"group":1,"subgroup":29,"version":12.1,"tone":[2,3]},{"annotation":"手拉手的两个人: 中等-浅肤色中等-深肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D1-1F3FC-200D-1F91D-200D-1F9D1-1F3FE","shortcodes":["holding_hands_people_tone2-4"],"emoji":"🧑🏼‍🤝‍🧑🏾","text":"","type":1,"order":2507,"group":1,"subgroup":29,"version":12.1,"tone":[2,4]},{"annotation":"手拉手的两个人: 中等-浅肤色较深肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D1-1F3FC-200D-1F91D-200D-1F9D1-1F3FF","shortcodes":["holding_hands_people_tone2-5"],"emoji":"🧑🏼‍🤝‍🧑🏿","text":"","type":1,"order":2508,"group":1,"subgroup":29,"version":12.1,"tone":[2,5]},{"annotation":"手拉手的两个人: 中等肤色较浅肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D1-1F3FD-200D-1F91D-200D-1F9D1-1F3FB","shortcodes":["holding_hands_people_tone3-1"],"emoji":"🧑🏽‍🤝‍🧑🏻","text":"","type":1,"order":2509,"group":1,"subgroup":29,"version":12,"tone":[3,1]},{"annotation":"手拉手的两个人: 中等肤色中等-浅肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D1-1F3FD-200D-1F91D-200D-1F9D1-1F3FC","shortcodes":["holding_hands_people_tone3-2"],"emoji":"🧑🏽‍🤝‍🧑🏼","text":"","type":1,"order":2510,"group":1,"subgroup":29,"version":12,"tone":[3,2]},{"annotation":"手拉手的两个人: 中等肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D1-1F3FD-200D-1F91D-200D-1F9D1-1F3FD","shortcodes":["holding_hands_people_tone3"],"emoji":"🧑🏽‍🤝‍🧑🏽","text":"","type":1,"order":2511,"group":1,"subgroup":29,"version":12,"tone":3},{"annotation":"手拉手的两个人: 中等肤色中等-深肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D1-1F3FD-200D-1F91D-200D-1F9D1-1F3FE","shortcodes":["holding_hands_people_tone3-4"],"emoji":"🧑🏽‍🤝‍🧑🏾","text":"","type":1,"order":2512,"group":1,"subgroup":29,"version":12.1,"tone":[3,4]},{"annotation":"手拉手的两个人: 中等肤色较深肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D1-1F3FD-200D-1F91D-200D-1F9D1-1F3FF","shortcodes":["holding_hands_people_tone3-5"],"emoji":"🧑🏽‍🤝‍🧑🏿","text":"","type":1,"order":2513,"group":1,"subgroup":29,"version":12.1,"tone":[3,5]},{"annotation":"手拉手的两个人: 中等-深肤色较浅肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D1-1F3FE-200D-1F91D-200D-1F9D1-1F3FB","shortcodes":["holding_hands_people_tone4-1"],"emoji":"🧑🏾‍🤝‍🧑🏻","text":"","type":1,"order":2514,"group":1,"subgroup":29,"version":12,"tone":[4,1]},{"annotation":"手拉手的两个人: 中等-深肤色中等-浅肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D1-1F3FE-200D-1F91D-200D-1F9D1-1F3FC","shortcodes":["holding_hands_people_tone4-2"],"emoji":"🧑🏾‍🤝‍🧑🏼","text":"","type":1,"order":2515,"group":1,"subgroup":29,"version":12,"tone":[4,2]},{"annotation":"手拉手的两个人: 中等-深肤色中等肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D1-1F3FE-200D-1F91D-200D-1F9D1-1F3FD","shortcodes":["holding_hands_people_tone4-3"],"emoji":"🧑🏾‍🤝‍🧑🏽","text":"","type":1,"order":2516,"group":1,"subgroup":29,"version":12,"tone":[4,3]},{"annotation":"手拉手的两个人: 中等-深肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D1-1F3FE-200D-1F91D-200D-1F9D1-1F3FE","shortcodes":["holding_hands_people_tone4"],"emoji":"🧑🏾‍🤝‍🧑🏾","text":"","type":1,"order":2517,"group":1,"subgroup":29,"version":12,"tone":4},{"annotation":"手拉手的两个人: 中等-深肤色较深肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D1-1F3FE-200D-1F91D-200D-1F9D1-1F3FF","shortcodes":["holding_hands_people_tone4-5"],"emoji":"🧑🏾‍🤝‍🧑🏿","text":"","type":1,"order":2518,"group":1,"subgroup":29,"version":12.1,"tone":[4,5]},{"annotation":"手拉手的两个人: 较深肤色较浅肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F9D1-1F3FF-200D-1F91D-200D-1F9D1-1F3FB","shortcodes":["holding_hands_people_tone5-1"],"emoji":"🧑🏿‍🤝‍🧑🏻","text":"","type":1,"order":2519,"group":1,"subgroup":29,"version":12,"tone":[5,1]},{"annotation":"手拉手的两个人: 较深肤色中等-浅肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F9D1-1F3FF-200D-1F91D-200D-1F9D1-1F3FC","shortcodes":["holding_hands_people_tone5-2"],"emoji":"🧑🏿‍🤝‍🧑🏼","text":"","type":1,"order":2520,"group":1,"subgroup":29,"version":12,"tone":[5,2]},{"annotation":"手拉手的两个人: 较深肤色中等肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F9D1-1F3FF-200D-1F91D-200D-1F9D1-1F3FD","shortcodes":["holding_hands_people_tone5-3"],"emoji":"🧑🏿‍🤝‍🧑🏽","text":"","type":1,"order":2521,"group":1,"subgroup":29,"version":12,"tone":[5,3]},{"annotation":"手拉手的两个人: 较深肤色中等-深肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F9D1-1F3FF-200D-1F91D-200D-1F9D1-1F3FE","shortcodes":["holding_hands_people_tone5-4"],"emoji":"🧑🏿‍🤝‍🧑🏾","text":"","type":1,"order":2522,"group":1,"subgroup":29,"version":12,"tone":[5,4]},{"annotation":"手拉手的两个人: 较深肤色","name":"ADULT, HANDSHAKE, ADULT, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F9D1-1F3FF-200D-1F91D-200D-1F9D1-1F3FF","shortcodes":["holding_hands_people_tone5"],"emoji":"🧑🏿‍🤝‍🧑🏿","text":"","type":1,"order":2523,"group":1,"subgroup":29,"version":12,"tone":5}]},{"annotation":"手拉手的两个女人","name":"TWO WOMEN HOLDING HANDS","hexcode":"1F46D","shortcodes":["holding_hands_ww"],"tags":["两个女人","情侣","手拉手"],"emoji":"👭","text":"","type":1,"order":2524,"group":1,"subgroup":29,"version":1,"skins":[{"annotation":"手拉手的两个女人: 较浅肤色","name":"TWO WOMEN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F46D-1F3FB","shortcodes":["holding_hands_ww_tone1"],"emoji":"👭🏻","text":"","type":1,"order":2525,"group":1,"subgroup":29,"version":12,"tone":1},{"annotation":"手拉手的两个女人: 中等-浅肤色","name":"TWO WOMEN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F46D-1F3FC","shortcodes":["holding_hands_ww_tone2"],"emoji":"👭🏼","text":"","type":1,"order":2531,"group":1,"subgroup":29,"version":12,"tone":2},{"annotation":"手拉手的两个女人: 中等肤色","name":"TWO WOMEN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F46D-1F3FD","shortcodes":["holding_hands_ww_tone3"],"emoji":"👭🏽","text":"","type":1,"order":2537,"group":1,"subgroup":29,"version":12,"tone":3},{"annotation":"手拉手的两个女人: 中等-深肤色","name":"TWO WOMEN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F46D-1F3FE","shortcodes":["holding_hands_ww_tone4"],"emoji":"👭🏾","text":"","type":1,"order":2543,"group":1,"subgroup":29,"version":12,"tone":4},{"annotation":"手拉手的两个女人: 较深肤色","name":"TWO WOMEN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F46D-1F3FF","shortcodes":["holding_hands_ww_tone5"],"emoji":"👭🏿","text":"","type":1,"order":2549,"group":1,"subgroup":29,"version":12,"tone":5},{"annotation":"手拉手的两个女人: 较浅肤色中等-浅肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FB-200D-1F91D-200D-1F469-1F3FC","shortcodes":["holding_hands_ww_tone1-2"],"emoji":"👩🏻‍🤝‍👩🏼","text":"","type":1,"order":2526,"group":1,"subgroup":29,"version":12.1,"tone":[1,2]},{"annotation":"手拉手的两个女人: 较浅肤色中等肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FB-200D-1F91D-200D-1F469-1F3FD","shortcodes":["holding_hands_ww_tone1-3"],"emoji":"👩🏻‍🤝‍👩🏽","text":"","type":1,"order":2527,"group":1,"subgroup":29,"version":12.1,"tone":[1,3]},{"annotation":"手拉手的两个女人: 较浅肤色中等-深肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FB-200D-1F91D-200D-1F469-1F3FE","shortcodes":["holding_hands_ww_tone1-4"],"emoji":"👩🏻‍🤝‍👩🏾","text":"","type":1,"order":2528,"group":1,"subgroup":29,"version":12.1,"tone":[1,4]},{"annotation":"手拉手的两个女人: 较浅肤色较深肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FB-200D-1F91D-200D-1F469-1F3FF","shortcodes":["holding_hands_ww_tone1-5"],"emoji":"👩🏻‍🤝‍👩🏿","text":"","type":1,"order":2529,"group":1,"subgroup":29,"version":12.1,"tone":[1,5]},{"annotation":"手拉手的两个女人: 中等-浅肤色较浅肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FC-200D-1F91D-200D-1F469-1F3FB","shortcodes":["holding_hands_ww_tone2-1"],"emoji":"👩🏼‍🤝‍👩🏻","text":"","type":1,"order":2530,"group":1,"subgroup":29,"version":12,"tone":[2,1]},{"annotation":"手拉手的两个女人: 中等-浅肤色中等肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FC-200D-1F91D-200D-1F469-1F3FD","shortcodes":["holding_hands_ww_tone2-3"],"emoji":"👩🏼‍🤝‍👩🏽","text":"","type":1,"order":2532,"group":1,"subgroup":29,"version":12.1,"tone":[2,3]},{"annotation":"手拉手的两个女人: 中等-浅肤色中等-深肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FC-200D-1F91D-200D-1F469-1F3FE","shortcodes":["holding_hands_ww_tone2-4"],"emoji":"👩🏼‍🤝‍👩🏾","text":"","type":1,"order":2533,"group":1,"subgroup":29,"version":12.1,"tone":[2,4]},{"annotation":"手拉手的两个女人: 中等-浅肤色较深肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FC-200D-1F91D-200D-1F469-1F3FF","shortcodes":["holding_hands_ww_tone2-5"],"emoji":"👩🏼‍🤝‍👩🏿","text":"","type":1,"order":2534,"group":1,"subgroup":29,"version":12.1,"tone":[2,5]},{"annotation":"手拉手的两个女人: 中等肤色较浅肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FD-200D-1F91D-200D-1F469-1F3FB","shortcodes":["holding_hands_ww_tone3-1"],"emoji":"👩🏽‍🤝‍👩🏻","text":"","type":1,"order":2535,"group":1,"subgroup":29,"version":12,"tone":[3,1]},{"annotation":"手拉手的两个女人: 中等肤色中等-浅肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FD-200D-1F91D-200D-1F469-1F3FC","shortcodes":["holding_hands_ww_tone3-2"],"emoji":"👩🏽‍🤝‍👩🏼","text":"","type":1,"order":2536,"group":1,"subgroup":29,"version":12,"tone":[3,2]},{"annotation":"手拉手的两个女人: 中等肤色中等-深肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FD-200D-1F91D-200D-1F469-1F3FE","shortcodes":["holding_hands_ww_tone3-4"],"emoji":"👩🏽‍🤝‍👩🏾","text":"","type":1,"order":2538,"group":1,"subgroup":29,"version":12.1,"tone":[3,4]},{"annotation":"手拉手的两个女人: 中等肤色较深肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FD-200D-1F91D-200D-1F469-1F3FF","shortcodes":["holding_hands_ww_tone3-5"],"emoji":"👩🏽‍🤝‍👩🏿","text":"","type":1,"order":2539,"group":1,"subgroup":29,"version":12.1,"tone":[3,5]},{"annotation":"手拉手的两个女人: 中等-深肤色较浅肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FE-200D-1F91D-200D-1F469-1F3FB","shortcodes":["holding_hands_ww_tone4-1"],"emoji":"👩🏾‍🤝‍👩🏻","text":"","type":1,"order":2540,"group":1,"subgroup":29,"version":12,"tone":[4,1]},{"annotation":"手拉手的两个女人: 中等-深肤色中等-浅肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FE-200D-1F91D-200D-1F469-1F3FC","shortcodes":["holding_hands_ww_tone4-2"],"emoji":"👩🏾‍🤝‍👩🏼","text":"","type":1,"order":2541,"group":1,"subgroup":29,"version":12,"tone":[4,2]},{"annotation":"手拉手的两个女人: 中等-深肤色中等肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FE-200D-1F91D-200D-1F469-1F3FD","shortcodes":["holding_hands_ww_tone4-3"],"emoji":"👩🏾‍🤝‍👩🏽","text":"","type":1,"order":2542,"group":1,"subgroup":29,"version":12,"tone":[4,3]},{"annotation":"手拉手的两个女人: 中等-深肤色较深肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FE-200D-1F91D-200D-1F469-1F3FF","shortcodes":["holding_hands_ww_tone4-5"],"emoji":"👩🏾‍🤝‍👩🏿","text":"","type":1,"order":2544,"group":1,"subgroup":29,"version":12.1,"tone":[4,5]},{"annotation":"手拉手的两个女人: 较深肤色较浅肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FF-200D-1F91D-200D-1F469-1F3FB","shortcodes":["holding_hands_ww_tone5-1"],"emoji":"👩🏿‍🤝‍👩🏻","text":"","type":1,"order":2545,"group":1,"subgroup":29,"version":12,"tone":[5,1]},{"annotation":"手拉手的两个女人: 较深肤色中等-浅肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FF-200D-1F91D-200D-1F469-1F3FC","shortcodes":["holding_hands_ww_tone5-2"],"emoji":"👩🏿‍🤝‍👩🏼","text":"","type":1,"order":2546,"group":1,"subgroup":29,"version":12,"tone":[5,2]},{"annotation":"手拉手的两个女人: 较深肤色中等肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FF-200D-1F91D-200D-1F469-1F3FD","shortcodes":["holding_hands_ww_tone5-3"],"emoji":"👩🏿‍🤝‍👩🏽","text":"","type":1,"order":2547,"group":1,"subgroup":29,"version":12,"tone":[5,3]},{"annotation":"手拉手的两个女人: 较深肤色中等-深肤色","name":"WOMAN, HANDSHAKE, WOMAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FF-200D-1F91D-200D-1F469-1F3FE","shortcodes":["holding_hands_ww_tone5-4"],"emoji":"👩🏿‍🤝‍👩🏾","text":"","type":1,"order":2548,"group":1,"subgroup":29,"version":12,"tone":[5,4]}]},{"annotation":"手拉手的一男一女","name":"MAN AND WOMAN HOLDING HANDS","hexcode":"1F46B","shortcodes":["holding_hands_mw","holding_hands_wm"],"tags":["一男一女","情侣","手拉手"],"emoji":"👫","text":"","type":1,"order":2550,"group":1,"subgroup":29,"version":0.6,"skins":[{"annotation":"手拉手的一男一女: 较浅肤色","name":"MAN AND WOMAN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F46B-1F3FB","shortcodes":["holding_hands_mw_tone1","holding_hands_wm_tone1"],"emoji":"👫🏻","text":"","type":1,"order":2551,"group":1,"subgroup":29,"version":12,"tone":1},{"annotation":"手拉手的一男一女: 中等-浅肤色","name":"MAN AND WOMAN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F46B-1F3FC","shortcodes":["holding_hands_mw_tone2","holding_hands_wm_tone2"],"emoji":"👫🏼","text":"","type":1,"order":2557,"group":1,"subgroup":29,"version":12,"tone":2},{"annotation":"手拉手的一男一女: 中等肤色","name":"MAN AND WOMAN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F46B-1F3FD","shortcodes":["holding_hands_mw_tone3","holding_hands_wm_tone3"],"emoji":"👫🏽","text":"","type":1,"order":2563,"group":1,"subgroup":29,"version":12,"tone":3},{"annotation":"手拉手的一男一女: 中等-深肤色","name":"MAN AND WOMAN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F46B-1F3FE","shortcodes":["holding_hands_mw_tone4","holding_hands_wm_tone4"],"emoji":"👫🏾","text":"","type":1,"order":2569,"group":1,"subgroup":29,"version":12,"tone":4},{"annotation":"手拉手的一男一女: 较深肤色","name":"MAN AND WOMAN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F46B-1F3FF","shortcodes":["holding_hands_mw_tone5","holding_hands_wm_tone5"],"emoji":"👫🏿","text":"","type":1,"order":2575,"group":1,"subgroup":29,"version":12,"tone":5},{"annotation":"手拉手的一男一女: 较浅肤色中等-浅肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FB-200D-1F91D-200D-1F468-1F3FC","shortcodes":["holding_hands_mw_tone1-2","holding_hands_wm_tone1-2"],"emoji":"👩🏻‍🤝‍👨🏼","text":"","type":1,"order":2552,"group":1,"subgroup":29,"version":12,"tone":[1,2]},{"annotation":"手拉手的一男一女: 较浅肤色中等肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FB-200D-1F91D-200D-1F468-1F3FD","shortcodes":["holding_hands_mw_tone1-3","holding_hands_wm_tone1-3"],"emoji":"👩🏻‍🤝‍👨🏽","text":"","type":1,"order":2553,"group":1,"subgroup":29,"version":12,"tone":[1,3]},{"annotation":"手拉手的一男一女: 较浅肤色中等-深肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FB-200D-1F91D-200D-1F468-1F3FE","shortcodes":["holding_hands_mw_tone1-4","holding_hands_wm_tone1-4"],"emoji":"👩🏻‍🤝‍👨🏾","text":"","type":1,"order":2554,"group":1,"subgroup":29,"version":12,"tone":[1,4]},{"annotation":"手拉手的一男一女: 较浅肤色较深肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FB-200D-1F91D-200D-1F468-1F3FF","shortcodes":["holding_hands_mw_tone1-5","holding_hands_wm_tone1-5"],"emoji":"👩🏻‍🤝‍👨🏿","text":"","type":1,"order":2555,"group":1,"subgroup":29,"version":12,"tone":[1,5]},{"annotation":"手拉手的一男一女: 中等-浅肤色较浅肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FC-200D-1F91D-200D-1F468-1F3FB","shortcodes":["holding_hands_mw_tone2-1","holding_hands_wm_tone2-1"],"emoji":"👩🏼‍🤝‍👨🏻","text":"","type":1,"order":2556,"group":1,"subgroup":29,"version":12,"tone":[2,1]},{"annotation":"手拉手的一男一女: 中等-浅肤色中等肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FC-200D-1F91D-200D-1F468-1F3FD","shortcodes":["holding_hands_mw_tone2-3","holding_hands_wm_tone2-3"],"emoji":"👩🏼‍🤝‍👨🏽","text":"","type":1,"order":2558,"group":1,"subgroup":29,"version":12,"tone":[2,3]},{"annotation":"手拉手的一男一女: 中等-浅肤色中等-深肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FC-200D-1F91D-200D-1F468-1F3FE","shortcodes":["holding_hands_mw_tone2-4","holding_hands_wm_tone2-4"],"emoji":"👩🏼‍🤝‍👨🏾","text":"","type":1,"order":2559,"group":1,"subgroup":29,"version":12,"tone":[2,4]},{"annotation":"手拉手的一男一女: 中等-浅肤色较深肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FC-200D-1F91D-200D-1F468-1F3FF","shortcodes":["holding_hands_mw_tone2-5","holding_hands_wm_tone2-5"],"emoji":"👩🏼‍🤝‍👨🏿","text":"","type":1,"order":2560,"group":1,"subgroup":29,"version":12,"tone":[2,5]},{"annotation":"手拉手的一男一女: 中等肤色较浅肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FD-200D-1F91D-200D-1F468-1F3FB","shortcodes":["holding_hands_mw_tone3-1","holding_hands_wm_tone3-1"],"emoji":"👩🏽‍🤝‍👨🏻","text":"","type":1,"order":2561,"group":1,"subgroup":29,"version":12,"tone":[3,1]},{"annotation":"手拉手的一男一女: 中等肤色中等-浅肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FD-200D-1F91D-200D-1F468-1F3FC","shortcodes":["holding_hands_mw_tone3-2","holding_hands_wm_tone3-2"],"emoji":"👩🏽‍🤝‍👨🏼","text":"","type":1,"order":2562,"group":1,"subgroup":29,"version":12,"tone":[3,2]},{"annotation":"手拉手的一男一女: 中等肤色中等-深肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FD-200D-1F91D-200D-1F468-1F3FE","shortcodes":["holding_hands_mw_tone3-4","holding_hands_wm_tone3-4"],"emoji":"👩🏽‍🤝‍👨🏾","text":"","type":1,"order":2564,"group":1,"subgroup":29,"version":12,"tone":[3,4]},{"annotation":"手拉手的一男一女: 中等肤色较深肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FD-200D-1F91D-200D-1F468-1F3FF","shortcodes":["holding_hands_mw_tone3-5","holding_hands_wm_tone3-5"],"emoji":"👩🏽‍🤝‍👨🏿","text":"","type":1,"order":2565,"group":1,"subgroup":29,"version":12,"tone":[3,5]},{"annotation":"手拉手的一男一女: 中等-深肤色较浅肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FE-200D-1F91D-200D-1F468-1F3FB","shortcodes":["holding_hands_mw_tone4-1","holding_hands_wm_tone4-1"],"emoji":"👩🏾‍🤝‍👨🏻","text":"","type":1,"order":2566,"group":1,"subgroup":29,"version":12,"tone":[4,1]},{"annotation":"手拉手的一男一女: 中等-深肤色中等-浅肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FE-200D-1F91D-200D-1F468-1F3FC","shortcodes":["holding_hands_mw_tone4-2","holding_hands_wm_tone4-2"],"emoji":"👩🏾‍🤝‍👨🏼","text":"","type":1,"order":2567,"group":1,"subgroup":29,"version":12,"tone":[4,2]},{"annotation":"手拉手的一男一女: 中等-深肤色中等肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FE-200D-1F91D-200D-1F468-1F3FD","shortcodes":["holding_hands_mw_tone4-3","holding_hands_wm_tone4-3"],"emoji":"👩🏾‍🤝‍👨🏽","text":"","type":1,"order":2568,"group":1,"subgroup":29,"version":12,"tone":[4,3]},{"annotation":"手拉手的一男一女: 中等-深肤色较深肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F469-1F3FE-200D-1F91D-200D-1F468-1F3FF","shortcodes":["holding_hands_mw_tone4-5","holding_hands_wm_tone4-5"],"emoji":"👩🏾‍🤝‍👨🏿","text":"","type":1,"order":2570,"group":1,"subgroup":29,"version":12,"tone":[4,5]},{"annotation":"手拉手的一男一女: 较深肤色较浅肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F469-1F3FF-200D-1F91D-200D-1F468-1F3FB","shortcodes":["holding_hands_mw_tone5-1","holding_hands_wm_tone5-1"],"emoji":"👩🏿‍🤝‍👨🏻","text":"","type":1,"order":2571,"group":1,"subgroup":29,"version":12,"tone":[5,1]},{"annotation":"手拉手的一男一女: 较深肤色中等-浅肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F469-1F3FF-200D-1F91D-200D-1F468-1F3FC","shortcodes":["holding_hands_mw_tone5-2","holding_hands_wm_tone5-2"],"emoji":"👩🏿‍🤝‍👨🏼","text":"","type":1,"order":2572,"group":1,"subgroup":29,"version":12,"tone":[5,2]},{"annotation":"手拉手的一男一女: 较深肤色中等肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F469-1F3FF-200D-1F91D-200D-1F468-1F3FD","shortcodes":["holding_hands_mw_tone5-3","holding_hands_wm_tone5-3"],"emoji":"👩🏿‍🤝‍👨🏽","text":"","type":1,"order":2573,"group":1,"subgroup":29,"version":12,"tone":[5,3]},{"annotation":"手拉手的一男一女: 较深肤色中等-深肤色","name":"WOMAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F469-1F3FF-200D-1F91D-200D-1F468-1F3FE","shortcodes":["holding_hands_mw_tone5-4","holding_hands_wm_tone5-4"],"emoji":"👩🏿‍🤝‍👨🏾","text":"","type":1,"order":2574,"group":1,"subgroup":29,"version":12,"tone":[5,4]}]},{"annotation":"手拉手的两个男人","name":"TWO MEN HOLDING HANDS","hexcode":"1F46C","shortcodes":["holding_hands_mm"],"tags":["两个男人","双子座","情侣","手拉手","黄道十二宫"],"emoji":"👬","text":"","type":1,"order":2576,"group":1,"subgroup":29,"version":1,"skins":[{"annotation":"手拉手的两个男人: 较浅肤色","name":"TWO MEN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F46C-1F3FB","shortcodes":["holding_hands_mm_tone1"],"emoji":"👬🏻","text":"","type":1,"order":2577,"group":1,"subgroup":29,"version":12,"tone":1},{"annotation":"手拉手的两个男人: 中等-浅肤色","name":"TWO MEN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F46C-1F3FC","shortcodes":["holding_hands_mm_tone2"],"emoji":"👬🏼","text":"","type":1,"order":2583,"group":1,"subgroup":29,"version":12,"tone":2},{"annotation":"手拉手的两个男人: 中等肤色","name":"TWO MEN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F46C-1F3FD","shortcodes":["holding_hands_mm_tone3"],"emoji":"👬🏽","text":"","type":1,"order":2589,"group":1,"subgroup":29,"version":12,"tone":3},{"annotation":"手拉手的两个男人: 中等-深肤色","name":"TWO MEN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F46C-1F3FE","shortcodes":["holding_hands_mm_tone4"],"emoji":"👬🏾","text":"","type":1,"order":2595,"group":1,"subgroup":29,"version":12,"tone":4},{"annotation":"手拉手的两个男人: 较深肤色","name":"TWO MEN HOLDING HANDS, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F46C-1F3FF","shortcodes":["holding_hands_mm_tone5"],"emoji":"👬🏿","text":"","type":1,"order":2601,"group":1,"subgroup":29,"version":12,"tone":5},{"annotation":"手拉手的两个男人: 较浅肤色中等-浅肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F468-1F3FB-200D-1F91D-200D-1F468-1F3FC","shortcodes":["holding_hands_mm_tone1-2"],"emoji":"👨🏻‍🤝‍👨🏼","text":"","type":1,"order":2578,"group":1,"subgroup":29,"version":12.1,"tone":[1,2]},{"annotation":"手拉手的两个男人: 较浅肤色中等肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F468-1F3FB-200D-1F91D-200D-1F468-1F3FD","shortcodes":["holding_hands_mm_tone1-3"],"emoji":"👨🏻‍🤝‍👨🏽","text":"","type":1,"order":2579,"group":1,"subgroup":29,"version":12.1,"tone":[1,3]},{"annotation":"手拉手的两个男人: 较浅肤色中等-深肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F468-1F3FB-200D-1F91D-200D-1F468-1F3FE","shortcodes":["holding_hands_mm_tone1-4"],"emoji":"👨🏻‍🤝‍👨🏾","text":"","type":1,"order":2580,"group":1,"subgroup":29,"version":12.1,"tone":[1,4]},{"annotation":"手拉手的两个男人: 较浅肤色较深肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F468-1F3FB-200D-1F91D-200D-1F468-1F3FF","shortcodes":["holding_hands_mm_tone1-5"],"emoji":"👨🏻‍🤝‍👨🏿","text":"","type":1,"order":2581,"group":1,"subgroup":29,"version":12.1,"tone":[1,5]},{"annotation":"手拉手的两个男人: 中等-浅肤色较浅肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F468-1F3FC-200D-1F91D-200D-1F468-1F3FB","shortcodes":["holding_hands_mm_tone2-1"],"emoji":"👨🏼‍🤝‍👨🏻","text":"","type":1,"order":2582,"group":1,"subgroup":29,"version":12,"tone":[2,1]},{"annotation":"手拉手的两个男人: 中等-浅肤色中等肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F468-1F3FC-200D-1F91D-200D-1F468-1F3FD","shortcodes":["holding_hands_mm_tone2-3"],"emoji":"👨🏼‍🤝‍👨🏽","text":"","type":1,"order":2584,"group":1,"subgroup":29,"version":12.1,"tone":[2,3]},{"annotation":"手拉手的两个男人: 中等-浅肤色中等-深肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F468-1F3FC-200D-1F91D-200D-1F468-1F3FE","shortcodes":["holding_hands_mm_tone2-4"],"emoji":"👨🏼‍🤝‍👨🏾","text":"","type":1,"order":2585,"group":1,"subgroup":29,"version":12.1,"tone":[2,4]},{"annotation":"手拉手的两个男人: 中等-浅肤色较深肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F468-1F3FC-200D-1F91D-200D-1F468-1F3FF","shortcodes":["holding_hands_mm_tone2-5"],"emoji":"👨🏼‍🤝‍👨🏿","text":"","type":1,"order":2586,"group":1,"subgroup":29,"version":12.1,"tone":[2,5]},{"annotation":"手拉手的两个男人: 中等肤色较浅肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F468-1F3FD-200D-1F91D-200D-1F468-1F3FB","shortcodes":["holding_hands_mm_tone3-1"],"emoji":"👨🏽‍🤝‍👨🏻","text":"","type":1,"order":2587,"group":1,"subgroup":29,"version":12,"tone":[3,1]},{"annotation":"手拉手的两个男人: 中等肤色中等-浅肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F468-1F3FD-200D-1F91D-200D-1F468-1F3FC","shortcodes":["holding_hands_mm_tone3-2"],"emoji":"👨🏽‍🤝‍👨🏼","text":"","type":1,"order":2588,"group":1,"subgroup":29,"version":12,"tone":[3,2]},{"annotation":"手拉手的两个男人: 中等肤色中等-深肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F468-1F3FD-200D-1F91D-200D-1F468-1F3FE","shortcodes":["holding_hands_mm_tone3-4"],"emoji":"👨🏽‍🤝‍👨🏾","text":"","type":1,"order":2590,"group":1,"subgroup":29,"version":12.1,"tone":[3,4]},{"annotation":"手拉手的两个男人: 中等肤色较深肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F468-1F3FD-200D-1F91D-200D-1F468-1F3FF","shortcodes":["holding_hands_mm_tone3-5"],"emoji":"👨🏽‍🤝‍👨🏿","text":"","type":1,"order":2591,"group":1,"subgroup":29,"version":12.1,"tone":[3,5]},{"annotation":"手拉手的两个男人: 中等-深肤色较浅肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F468-1F3FE-200D-1F91D-200D-1F468-1F3FB","shortcodes":["holding_hands_mm_tone4-1"],"emoji":"👨🏾‍🤝‍👨🏻","text":"","type":1,"order":2592,"group":1,"subgroup":29,"version":12,"tone":[4,1]},{"annotation":"手拉手的两个男人: 中等-深肤色中等-浅肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F468-1F3FE-200D-1F91D-200D-1F468-1F3FC","shortcodes":["holding_hands_mm_tone4-2"],"emoji":"👨🏾‍🤝‍👨🏼","text":"","type":1,"order":2593,"group":1,"subgroup":29,"version":12,"tone":[4,2]},{"annotation":"手拉手的两个男人: 中等-深肤色中等肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F468-1F3FE-200D-1F91D-200D-1F468-1F3FD","shortcodes":["holding_hands_mm_tone4-3"],"emoji":"👨🏾‍🤝‍👨🏽","text":"","type":1,"order":2594,"group":1,"subgroup":29,"version":12,"tone":[4,3]},{"annotation":"手拉手的两个男人: 中等-深肤色较深肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F468-1F3FE-200D-1F91D-200D-1F468-1F3FF","shortcodes":["holding_hands_mm_tone4-5"],"emoji":"👨🏾‍🤝‍👨🏿","text":"","type":1,"order":2596,"group":1,"subgroup":29,"version":12.1,"tone":[4,5]},{"annotation":"手拉手的两个男人: 较深肤色较浅肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F468-1F3FF-200D-1F91D-200D-1F468-1F3FB","shortcodes":["holding_hands_mm_tone5-1"],"emoji":"👨🏿‍🤝‍👨🏻","text":"","type":1,"order":2597,"group":1,"subgroup":29,"version":12,"tone":[5,1]},{"annotation":"手拉手的两个男人: 较深肤色中等-浅肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F468-1F3FF-200D-1F91D-200D-1F468-1F3FC","shortcodes":["holding_hands_mm_tone5-2"],"emoji":"👨🏿‍🤝‍👨🏼","text":"","type":1,"order":2598,"group":1,"subgroup":29,"version":12,"tone":[5,2]},{"annotation":"手拉手的两个男人: 较深肤色中等肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F468-1F3FF-200D-1F91D-200D-1F468-1F3FD","shortcodes":["holding_hands_mm_tone5-3"],"emoji":"👨🏿‍🤝‍👨🏽","text":"","type":1,"order":2599,"group":1,"subgroup":29,"version":12,"tone":[5,3]},{"annotation":"手拉手的两个男人: 较深肤色中等-深肤色","name":"MAN, HANDSHAKE, MAN, EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F468-1F3FF-200D-1F91D-200D-1F468-1F3FE","shortcodes":["holding_hands_mm_tone5-4"],"emoji":"👨🏿‍🤝‍👨🏾","text":"","type":1,"order":2600,"group":1,"subgroup":29,"version":12,"tone":[5,4]}]},{"annotation":"亲吻","name":"KISS","hexcode":"1F48F","shortcodes":["couple"],"tags":["情侣","接吻","浪漫"],"emoji":"💏","text":"","type":1,"order":2602,"group":1,"subgroup":29,"version":0.6},{"annotation":"亲吻: 女人男人","name":"WOMAN, HEAVY BLACK HEART, KISS MARK, MAN","hexcode":"1F469-200D-2764-FE0F-200D-1F48B-200D-1F468","shortcodes":["kiss_mw","kiss_wm"],"tags":["亲吻","女人","情侣","接吻","浪漫","男人"],"emoji":"👩‍❤️‍💋‍👨","text":"","type":1,"order":2603,"group":1,"subgroup":29,"version":2},{"annotation":"亲吻: 男人男人","name":"MAN, HEAVY BLACK HEART, KISS MARK, MAN","hexcode":"1F468-200D-2764-FE0F-200D-1F48B-200D-1F468","shortcodes":["kiss_mm"],"tags":["亲吻","情侣","接吻","浪漫","男人"],"emoji":"👨‍❤️‍💋‍👨","text":"","type":1,"order":2605,"group":1,"subgroup":29,"version":2},{"annotation":"亲吻: 女人女人","name":"WOMAN, HEAVY BLACK HEART, KISS MARK, WOMAN","hexcode":"1F469-200D-2764-FE0F-200D-1F48B-200D-1F469","shortcodes":["kiss_ww"],"tags":["亲吻","女人","情侣","接吻","浪漫"],"emoji":"👩‍❤️‍💋‍👩","text":"","type":1,"order":2607,"group":1,"subgroup":29,"version":2},{"annotation":"情侣","name":"COUPLE WITH HEART","hexcode":"1F491","shortcodes":["couple_heart"],"tags":["恋爱","浪漫","红心"],"emoji":"💑","text":"","type":1,"order":2609,"group":1,"subgroup":29,"version":0.6},{"annotation":"情侣: 女人男人","name":"WOMAN, HEAVY BLACK HEART, MAN","hexcode":"1F469-200D-2764-FE0F-200D-1F468","shortcodes":["couple_mw","couple_wm"],"tags":["女人","恋爱","情侣","浪漫","男人","红心"],"emoji":"👩‍❤️‍👨","text":"","type":1,"order":2610,"group":1,"subgroup":29,"version":2},{"annotation":"情侣: 男人男人","name":"MAN, HEAVY BLACK HEART, MAN","hexcode":"1F468-200D-2764-FE0F-200D-1F468","shortcodes":["couple_mm"],"tags":["恋爱","情侣","浪漫","男人","红心"],"emoji":"👨‍❤️‍👨","text":"","type":1,"order":2612,"group":1,"subgroup":29,"version":2},{"annotation":"情侣: 女人女人","name":"WOMAN, HEAVY BLACK HEART, WOMAN","hexcode":"1F469-200D-2764-FE0F-200D-1F469","shortcodes":["couple_ww"],"tags":["女人","恋爱","情侣","浪漫","红心"],"emoji":"👩‍❤️‍👩","text":"","type":1,"order":2614,"group":1,"subgroup":29,"version":2},{"annotation":"家庭","name":"FAMILY","hexcode":"1F46A","shortcodes":["family"],"tags":["家庭"],"emoji":"👪️","text":"👪︎","type":1,"order":2616,"group":1,"subgroup":29,"version":0.6},{"annotation":"家庭: 男人女人男孩","name":"MAN, WOMAN, BOY","hexcode":"1F468-200D-1F469-200D-1F466","shortcodes":["family_mwb"],"tags":["女人","家庭","男人","男孩"],"emoji":"👨‍👩‍👦","text":"","type":1,"order":2617,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 男人女人女孩","name":"MAN, WOMAN, GIRL","hexcode":"1F468-200D-1F469-200D-1F467","shortcodes":["family_mwg"],"tags":["女人","女孩","家庭","男人"],"emoji":"👨‍👩‍👧","text":"","type":1,"order":2618,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 男人女人女孩男孩","name":"MAN, WOMAN, GIRL, BOY","hexcode":"1F468-200D-1F469-200D-1F467-200D-1F466","shortcodes":["family_mwgb"],"tags":["女人","女孩","家庭","男人","男孩"],"emoji":"👨‍👩‍👧‍👦","text":"","type":1,"order":2619,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 男人女人男孩男孩","name":"MAN, WOMAN, BOY, BOY","hexcode":"1F468-200D-1F469-200D-1F466-200D-1F466","shortcodes":["family_mwbb"],"tags":["女人","家庭","男人","男孩"],"emoji":"👨‍👩‍👦‍👦","text":"","type":1,"order":2620,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 男人女人女孩女孩","name":"MAN, WOMAN, GIRL, GIRL","hexcode":"1F468-200D-1F469-200D-1F467-200D-1F467","shortcodes":["family_mwgg"],"tags":["女人","女孩","家庭","男人"],"emoji":"👨‍👩‍👧‍👧","text":"","type":1,"order":2621,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 男人男人男孩","name":"MAN, MAN, BOY","hexcode":"1F468-200D-1F468-200D-1F466","shortcodes":["family_mmb"],"tags":["家庭","男人","男孩"],"emoji":"👨‍👨‍👦","text":"","type":1,"order":2622,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 男人男人女孩","name":"MAN, MAN, GIRL","hexcode":"1F468-200D-1F468-200D-1F467","shortcodes":["family_mmg"],"tags":["女孩","家庭","男人"],"emoji":"👨‍👨‍👧","text":"","type":1,"order":2623,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 男人男人女孩男孩","name":"MAN, MAN, GIRL, BOY","hexcode":"1F468-200D-1F468-200D-1F467-200D-1F466","shortcodes":["family_mmgb"],"tags":["女孩","家庭","男人","男孩"],"emoji":"👨‍👨‍👧‍👦","text":"","type":1,"order":2624,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 男人男人男孩男孩","name":"MAN, MAN, BOY, BOY","hexcode":"1F468-200D-1F468-200D-1F466-200D-1F466","shortcodes":["family_mmbb"],"tags":["家庭","男人","男孩"],"emoji":"👨‍👨‍👦‍👦","text":"","type":1,"order":2625,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 男人男人女孩女孩","name":"MAN, MAN, GIRL, GIRL","hexcode":"1F468-200D-1F468-200D-1F467-200D-1F467","shortcodes":["family_mmgg"],"tags":["女孩","家庭","男人"],"emoji":"👨‍👨‍👧‍👧","text":"","type":1,"order":2626,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 女人女人男孩","name":"WOMAN, WOMAN, BOY","hexcode":"1F469-200D-1F469-200D-1F466","shortcodes":["family_wwb"],"tags":["女人","家庭","男孩"],"emoji":"👩‍👩‍👦","text":"","type":1,"order":2627,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 女人女人女孩","name":"WOMAN, WOMAN, GIRL","hexcode":"1F469-200D-1F469-200D-1F467","shortcodes":["family_wwg"],"tags":["女人","女孩","家庭"],"emoji":"👩‍👩‍👧","text":"","type":1,"order":2628,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 女人女人女孩男孩","name":"WOMAN, WOMAN, GIRL, BOY","hexcode":"1F469-200D-1F469-200D-1F467-200D-1F466","shortcodes":["family_wwgb"],"tags":["女人","女孩","家庭","男孩"],"emoji":"👩‍👩‍👧‍👦","text":"","type":1,"order":2629,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 女人女人男孩男孩","name":"WOMAN, WOMAN, BOY, BOY","hexcode":"1F469-200D-1F469-200D-1F466-200D-1F466","shortcodes":["family_wwbb"],"tags":["女人","家庭","男孩"],"emoji":"👩‍👩‍👦‍👦","text":"","type":1,"order":2630,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 女人女人女孩女孩","name":"WOMAN, WOMAN, GIRL, GIRL","hexcode":"1F469-200D-1F469-200D-1F467-200D-1F467","shortcodes":["family_wwgg"],"tags":["女人","女孩","家庭"],"emoji":"👩‍👩‍👧‍👧","text":"","type":1,"order":2631,"group":1,"subgroup":29,"version":2},{"annotation":"家庭: 男人男孩","name":"MAN, BOY","hexcode":"1F468-200D-1F466","shortcodes":["family_mb"],"tags":["家庭","男人","男孩"],"emoji":"👨‍👦","text":"","type":1,"order":2632,"group":1,"subgroup":29,"version":4},{"annotation":"家庭: 男人男孩男孩","name":"MAN, BOY, BOY","hexcode":"1F468-200D-1F466-200D-1F466","shortcodes":["family_mbb"],"tags":["家庭","男人","男孩"],"emoji":"👨‍👦‍👦","text":"","type":1,"order":2633,"group":1,"subgroup":29,"version":4},{"annotation":"家庭: 男人女孩","name":"MAN, GIRL","hexcode":"1F468-200D-1F467","shortcodes":["family_mg"],"tags":["女孩","家庭","男人"],"emoji":"👨‍👧","text":"","type":1,"order":2634,"group":1,"subgroup":29,"version":4},{"annotation":"家庭: 男人女孩男孩","name":"MAN, GIRL, BOY","hexcode":"1F468-200D-1F467-200D-1F466","shortcodes":["family_mgb"],"tags":["女孩","家庭","男人","男孩"],"emoji":"👨‍👧‍👦","text":"","type":1,"order":2635,"group":1,"subgroup":29,"version":4},{"annotation":"家庭: 男人女孩女孩","name":"MAN, GIRL, GIRL","hexcode":"1F468-200D-1F467-200D-1F467","shortcodes":["family_mgg"],"tags":["女孩","家庭","男人"],"emoji":"👨‍👧‍👧","text":"","type":1,"order":2636,"group":1,"subgroup":29,"version":4},{"annotation":"家庭: 女人男孩","name":"WOMAN, BOY","hexcode":"1F469-200D-1F466","shortcodes":["family_wb"],"tags":["女人","家庭","男孩"],"emoji":"👩‍👦","text":"","type":1,"order":2637,"group":1,"subgroup":29,"version":4},{"annotation":"家庭: 女人男孩男孩","name":"WOMAN, BOY, BOY","hexcode":"1F469-200D-1F466-200D-1F466","shortcodes":["family_wbb"],"tags":["女人","家庭","男孩"],"emoji":"👩‍👦‍👦","text":"","type":1,"order":2638,"group":1,"subgroup":29,"version":4},{"annotation":"家庭: 女人女孩","name":"WOMAN, GIRL","hexcode":"1F469-200D-1F467","shortcodes":["family_wg"],"tags":["女人","女孩","家庭"],"emoji":"👩‍👧","text":"","type":1,"order":2639,"group":1,"subgroup":29,"version":4},{"annotation":"家庭: 女人女孩男孩","name":"WOMAN, GIRL, BOY","hexcode":"1F469-200D-1F467-200D-1F466","shortcodes":["family_wgb"],"tags":["女人","女孩","家庭","男孩"],"emoji":"👩‍👧‍👦","text":"","type":1,"order":2640,"group":1,"subgroup":29,"version":4},{"annotation":"家庭: 女人女孩女孩","name":"WOMAN, GIRL, GIRL","hexcode":"1F469-200D-1F467-200D-1F467","shortcodes":["family_wgg"],"tags":["女人","女孩","家庭"],"emoji":"👩‍👧‍👧","text":"","type":1,"order":2641,"group":1,"subgroup":29,"version":4},{"annotation":"说话","name":"SPEAKING HEAD IN SILHOUETTE","hexcode":"1F5E3","shortcodes":["speaking_head"],"tags":["剪影","头","讲话"],"emoji":"🗣️","text":"🗣︎","type":0,"order":2643,"group":1,"subgroup":30,"version":0.7},{"annotation":"人像","name":"BUST IN SILHOUETTE","hexcode":"1F464","shortcodes":["bust_silhouette"],"tags":["剪影","半身像"],"emoji":"👤","text":"","type":1,"order":2644,"group":1,"subgroup":30,"version":0.6},{"annotation":"双人像","name":"BUSTS IN SILHOUETTE","hexcode":"1F465","shortcodes":["busts_silhouette"],"tags":["剪影","半身像"],"emoji":"👥","text":"","type":1,"order":2645,"group":1,"subgroup":30,"version":1},{"annotation":"人的拥抱","name":"PEOPLE HUGGING","hexcode":"1FAC2","shortcodes":["people_hugging"],"tags":["再见","您好","感谢","拥抱"],"emoji":"🫂","text":"","type":1,"order":2646,"group":1,"subgroup":30,"version":13},{"annotation":"脚印","name":"FOOTPRINTS","hexcode":"1F463","shortcodes":["footprints"],"tags":["足迹"],"emoji":"👣","text":"","type":1,"order":2647,"group":1,"subgroup":30,"version":0.6},{"annotation":"较浅肤色","name":"EMOJI MODIFIER FITZPATRICK TYPE-1-2","hexcode":"1F3FB","shortcodes":["tone_light","tone1"],"tags":["肤色"],"emoji":"🏻","text":"","type":1,"order":2648,"group":2,"subgroup":31,"version":1},{"annotation":"中等-浅肤色","name":"EMOJI MODIFIER FITZPATRICK TYPE-3","hexcode":"1F3FC","shortcodes":["tone_medium_light","tone2"],"tags":["肤色"],"emoji":"🏼","text":"","type":1,"order":2649,"group":2,"subgroup":31,"version":1},{"annotation":"中等肤色","name":"EMOJI MODIFIER FITZPATRICK TYPE-4","hexcode":"1F3FD","shortcodes":["tone_medium","tone3"],"tags":["肤色"],"emoji":"🏽","text":"","type":1,"order":2650,"group":2,"subgroup":31,"version":1},{"annotation":"中等-深肤色","name":"EMOJI MODIFIER FITZPATRICK TYPE-5","hexcode":"1F3FE","shortcodes":["tone_medium_dark","tone4"],"tags":["肤色"],"emoji":"🏾","text":"","type":1,"order":2651,"group":2,"subgroup":31,"version":1},{"annotation":"较深肤色","name":"EMOJI MODIFIER FITZPATRICK TYPE-6","hexcode":"1F3FF","shortcodes":["tone_dark","tone5"],"tags":["肤色"],"emoji":"🏿","text":"","type":1,"order":2652,"group":2,"subgroup":31,"version":1},{"annotation":"红发","name":"EMOJI COMPONENT RED HAIR","hexcode":"1F9B0","shortcodes":["red_hair"],"tags":["姜黄色"],"emoji":"🦰","text":"","type":1,"order":2653,"group":2,"subgroup":32,"version":11},{"annotation":"卷发","name":"EMOJI COMPONENT CURLY HAIR","hexcode":"1F9B1","shortcodes":["curly_hair"],"tags":["蓬松发","鬈发"],"emoji":"🦱","text":"","type":1,"order":2654,"group":2,"subgroup":32,"version":11},{"annotation":"白发","name":"EMOJI COMPONENT WHITE HAIR","hexcode":"1F9B3","shortcodes":["white_hair"],"tags":["头发","年老","灰色","白色"],"emoji":"🦳","text":"","type":1,"order":2655,"group":2,"subgroup":32,"version":11},{"annotation":"秃顶","name":"EMOJI COMPONENT BALD","hexcode":"1F9B2","shortcodes":["bald"],"tags":["光头","化疗"],"emoji":"🦲","text":"","type":1,"order":2656,"group":2,"subgroup":32,"version":11},{"annotation":"猴头","name":"MONKEY FACE","hexcode":"1F435","shortcodes":["monkey_face"],"tags":["猴"],"emoji":"🐵","text":"","type":1,"order":2657,"group":3,"subgroup":33,"version":0.6},{"annotation":"猴子","name":"MONKEY","hexcode":"1F412","shortcodes":["monkey"],"tags":["猴"],"emoji":"🐒","text":"","type":1,"order":2658,"group":3,"subgroup":33,"version":0.6},{"annotation":"大猩猩","name":"GORILLA","hexcode":"1F98D","shortcodes":["gorilla"],"tags":["大猩猩"],"emoji":"🦍","text":"","type":1,"order":2659,"group":3,"subgroup":33,"version":3},{"annotation":"红毛猩猩","name":"ORANGUTAN","hexcode":"1F9A7","shortcodes":["orangutan"],"tags":["猩猩","猴","猿"],"emoji":"🦧","text":"","type":1,"order":2660,"group":3,"subgroup":33,"version":12},{"annotation":"狗脸","name":"DOG FACE","hexcode":"1F436","shortcodes":["dog_face"],"tags":["宠物","狗","脸"],"emoji":"🐶","text":"","type":1,"order":2661,"group":3,"subgroup":33,"version":0.6},{"annotation":"狗","name":"DOG","hexcode":"1F415","shortcodes":["dog"],"tags":["宠物"],"emoji":"🐕️","text":"🐕︎","type":1,"order":2662,"group":3,"subgroup":33,"version":0.7},{"annotation":"导盲犬","name":"GUIDE DOG","hexcode":"1F9AE","shortcodes":["guide_dog"],"tags":["指引","无障碍","盲"],"emoji":"🦮","text":"","type":1,"order":2663,"group":3,"subgroup":33,"version":12},{"annotation":"服务犬","name":"DOG, SAFETY VEST","hexcode":"1F415-200D-1F9BA","shortcodes":["service_dog"],"tags":["工作犬","无障碍","犬","狗","辅助"],"emoji":"🐕‍🦺","text":"","type":1,"order":2664,"group":3,"subgroup":33,"version":12},{"annotation":"贵宾犬","name":"POODLE","hexcode":"1F429","shortcodes":["poodle"],"tags":["卷毛狗","狗"],"emoji":"🐩","text":"","type":1,"order":2665,"group":3,"subgroup":33,"version":0.6},{"annotation":"狼","name":"WOLF FACE","hexcode":"1F43A","shortcodes":["wolf_face"],"tags":["头","脸"],"emoji":"🐺","text":"","type":1,"order":2666,"group":3,"subgroup":33,"version":0.6},{"annotation":"狐狸","name":"FOX FACE","hexcode":"1F98A","shortcodes":["fox_face"],"tags":["头","脸"],"emoji":"🦊","text":"","type":1,"order":2667,"group":3,"subgroup":33,"version":3},{"annotation":"浣熊","name":"RACCOON","hexcode":"1F99D","shortcodes":["raccoon"],"tags":["好奇","淘气"],"emoji":"🦝","text":"","type":1,"order":2668,"group":3,"subgroup":33,"version":11},{"annotation":"猫脸","name":"CAT FACE","hexcode":"1F431","shortcodes":["cat_face"],"tags":["宠物","猫","脸"],"emoji":"🐱","text":"","type":1,"order":2669,"group":3,"subgroup":33,"version":0.6},{"annotation":"猫","name":"CAT","hexcode":"1F408","shortcodes":["cat"],"tags":["宠物"],"emoji":"🐈️","text":"🐈︎","type":1,"order":2670,"group":3,"subgroup":33,"version":0.7},{"annotation":"黑猫","name":"CAT, BLACK LARGE SQUARE","hexcode":"1F408-200D-2B1B","shortcodes":["black_cat"],"tags":["不吉利","猫","黑色"],"emoji":"🐈‍⬛","text":"","type":1,"order":2671,"group":3,"subgroup":33,"version":13},{"annotation":"狮子","name":"LION FACE","hexcode":"1F981","shortcodes":["lion_face"],"tags":["狮子座","脸","黄道十二宫"],"emoji":"🦁","text":"","type":1,"order":2672,"group":3,"subgroup":33,"version":1},{"annotation":"老虎头","name":"TIGER FACE","hexcode":"1F42F","shortcodes":["tiger_face"],"tags":["老虎","脸"],"emoji":"🐯","text":"","type":1,"order":2673,"group":3,"subgroup":33,"version":0.6},{"annotation":"老虎","name":"TIGER","hexcode":"1F405","shortcodes":["tiger"],"tags":["虎"],"emoji":"🐅","text":"","type":1,"order":2674,"group":3,"subgroup":33,"version":1},{"annotation":"豹子","name":"LEOPARD","hexcode":"1F406","shortcodes":["leopard"],"tags":["猎豹","豹"],"emoji":"🐆","text":"","type":1,"order":2675,"group":3,"subgroup":33,"version":1},{"annotation":"马头","name":"HORSE FACE","hexcode":"1F434","shortcodes":["horse_face"],"tags":["马"],"emoji":"🐴","text":"","type":1,"order":2676,"group":3,"subgroup":33,"version":0.6},{"annotation":"马","name":"HORSE","hexcode":"1F40E","shortcodes":["horse"],"tags":["比赛","赛马","骑马"],"emoji":"🐎","text":"","type":1,"order":2677,"group":3,"subgroup":33,"version":0.6},{"annotation":"独角兽","name":"UNICORN FACE","hexcode":"1F984","shortcodes":["unicorn_face"],"tags":["头","脸"],"emoji":"🦄","text":"","type":1,"order":2678,"group":3,"subgroup":33,"version":1},{"annotation":"斑马","name":"ZEBRA FACE","hexcode":"1F993","shortcodes":["zebra"],"tags":["条纹"],"emoji":"🦓","text":"","type":1,"order":2679,"group":3,"subgroup":33,"version":5},{"annotation":"鹿","name":"DEER","hexcode":"1F98C","shortcodes":["deer"],"tags":["鹿"],"emoji":"🦌","text":"","type":1,"order":2680,"group":3,"subgroup":33,"version":3},{"annotation":"大野牛","name":"BISON","hexcode":"1F9AC","shortcodes":["bison"],"tags":["欧洲野牛","水牛","畜群"],"emoji":"🦬","text":"","type":1,"order":2681,"group":3,"subgroup":33,"version":13},{"annotation":"奶牛头","name":"COW FACE","hexcode":"1F42E","shortcodes":["cow_face"],"tags":["奶牛","脸"],"emoji":"🐮","text":"","type":1,"order":2682,"group":3,"subgroup":33,"version":0.6},{"annotation":"公牛","name":"OX","hexcode":"1F402","shortcodes":["ox"],"tags":["牛","金牛座","黄道十二宫"],"emoji":"🐂","text":"","type":1,"order":2683,"group":3,"subgroup":33,"version":1},{"annotation":"水牛","name":"WATER BUFFALO","hexcode":"1F403","shortcodes":["water_buffalo"],"tags":["水牛"],"emoji":"🐃","text":"","type":1,"order":2684,"group":3,"subgroup":33,"version":1},{"annotation":"奶牛","name":"COW","hexcode":"1F404","shortcodes":["cow"],"tags":["牛"],"emoji":"🐄","text":"","type":1,"order":2685,"group":3,"subgroup":33,"version":1},{"annotation":"猪头","name":"PIG FACE","hexcode":"1F437","shortcodes":["pig_face"],"tags":["猪","脸"],"emoji":"🐷","text":"","type":1,"order":2686,"group":3,"subgroup":33,"version":0.6},{"annotation":"猪","name":"PIG","hexcode":"1F416","shortcodes":["pig"],"tags":["猪"],"emoji":"🐖","text":"","type":1,"order":2687,"group":3,"subgroup":33,"version":1},{"annotation":"野猪","name":"BOAR","hexcode":"1F417","shortcodes":["boar"],"tags":["猪"],"emoji":"🐗","text":"","type":1,"order":2688,"group":3,"subgroup":33,"version":0.6},{"annotation":"猪鼻子","name":"PIG NOSE","hexcode":"1F43D","shortcodes":["pig_nose"],"tags":["猪","脸","鼻子"],"emoji":"🐽","text":"","type":1,"order":2689,"group":3,"subgroup":33,"version":0.6},{"annotation":"公羊","name":"RAM","hexcode":"1F40F","shortcodes":["ram"],"tags":["白羊座","羊","雄性","黄道十二宫"],"emoji":"🐏","text":"","type":1,"order":2690,"group":3,"subgroup":33,"version":1},{"annotation":"母羊","name":"SHEEP","hexcode":"1F411","shortcodes":["sheep"],"tags":["羊","雌性"],"emoji":"🐑","text":"","type":1,"order":2691,"group":3,"subgroup":33,"version":0.6},{"annotation":"山羊","name":"GOAT","hexcode":"1F410","shortcodes":["goat"],"tags":["摩羯座","黄道十二宫"],"emoji":"🐐","text":"","type":1,"order":2692,"group":3,"subgroup":33,"version":1},{"annotation":"骆驼","name":"DROMEDARY CAMEL","hexcode":"1F42A","shortcodes":["camel"],"tags":["单峰"],"emoji":"🐪","text":"","type":1,"order":2693,"group":3,"subgroup":33,"version":1},{"annotation":"双峰骆驼","name":"BACTRIAN CAMEL","hexcode":"1F42B","shortcodes":["two_hump_camel"],"tags":["双峰","骆驼"],"emoji":"🐫","text":"","type":1,"order":2694,"group":3,"subgroup":33,"version":0.6},{"annotation":"美洲鸵","name":"LLAMA","hexcode":"1F999","shortcodes":["llama"],"tags":["原驼","小羊驼","羊毛","羊驼"],"emoji":"🦙","text":"","type":1,"order":2695,"group":3,"subgroup":33,"version":11},{"annotation":"长颈鹿","name":"GIRAFFE FACE","hexcode":"1F992","shortcodes":["giraffe"],"tags":["斑点"],"emoji":"🦒","text":"","type":1,"order":2696,"group":3,"subgroup":33,"version":5},{"annotation":"大象","name":"ELEPHANT","hexcode":"1F418","shortcodes":["elephant"],"tags":["象"],"emoji":"🐘","text":"","type":1,"order":2697,"group":3,"subgroup":33,"version":0.6},{"annotation":"猛犸","name":"MAMMOTH","hexcode":"1F9A3","shortcodes":["mammoth"],"tags":["大型","有绒毛的","灭绝","长牙"],"emoji":"🦣","text":"","type":1,"order":2698,"group":3,"subgroup":33,"version":13},{"annotation":"犀牛","name":"RHINOCEROS","hexcode":"1F98F","shortcodes":["rhino"],"tags":["犀牛"],"emoji":"🦏","text":"","type":1,"order":2699,"group":3,"subgroup":33,"version":3},{"annotation":"河马","name":"HIPPOPOTAMUS","hexcode":"1F99B","shortcodes":["hippo"],"tags":["河马"],"emoji":"🦛","text":"","type":1,"order":2700,"group":3,"subgroup":33,"version":11},{"annotation":"老鼠头","name":"MOUSE FACE","hexcode":"1F42D","shortcodes":["mouse_face"],"tags":["鼠"],"emoji":"🐭","text":"","type":1,"order":2701,"group":3,"subgroup":33,"version":0.6},{"annotation":"老鼠","name":"MOUSE","hexcode":"1F401","shortcodes":["mouse"],"tags":["耗子","鼠"],"emoji":"🐁","text":"","type":1,"order":2702,"group":3,"subgroup":33,"version":1},{"annotation":"耗子","name":"RAT","hexcode":"1F400","shortcodes":["rat"],"tags":["鼠"],"emoji":"🐀","text":"","type":1,"order":2703,"group":3,"subgroup":33,"version":1},{"annotation":"仓鼠","name":"HAMSTER FACE","hexcode":"1F439","shortcodes":["hamster_face"],"tags":["啮齿","头","脸"],"emoji":"🐹","text":"","type":1,"order":2704,"group":3,"subgroup":33,"version":0.6},{"annotation":"兔子头","name":"RABBIT FACE","hexcode":"1F430","shortcodes":["rabbit_face"],"tags":["兔"],"emoji":"🐰","text":"","type":1,"order":2705,"group":3,"subgroup":33,"version":0.6},{"annotation":"兔子","name":"RABBIT","hexcode":"1F407","shortcodes":["rabbit"],"tags":["兔"],"emoji":"🐇","text":"","type":1,"order":2706,"group":3,"subgroup":33,"version":1},{"annotation":"松鼠","name":"CHIPMUNK","hexcode":"1F43F","shortcodes":["chipmunk"],"tags":["花栗鼠"],"emoji":"🐿️","text":"🐿︎","type":0,"order":2708,"group":3,"subgroup":33,"version":0.7},{"annotation":"海狸","name":"BEAVER","hexcode":"1F9AB","shortcodes":["beaver"],"tags":["母畜"],"emoji":"🦫","text":"","type":1,"order":2709,"group":3,"subgroup":33,"version":13},{"annotation":"刺猬","name":"HEDGEHOG","hexcode":"1F994","shortcodes":["hedgehog"],"tags":["刺猬"],"emoji":"🦔","text":"","type":1,"order":2710,"group":3,"subgroup":33,"version":5},{"annotation":"蝙蝠","name":"BAT","hexcode":"1F987","shortcodes":["bat"],"tags":["吸血鬼"],"emoji":"🦇","text":"","type":1,"order":2711,"group":3,"subgroup":33,"version":3},{"annotation":"熊","name":"BEAR FACE","hexcode":"1F43B","shortcodes":["bear_face"],"tags":["头","脸"],"emoji":"🐻","text":"","type":1,"order":2712,"group":3,"subgroup":33,"version":0.6},{"annotation":"北极熊","name":"BEAR FACE, SNOWFLAKE","hexcode":"1F43B-200D-2744-FE0F","shortcodes":["polar_bear_face"],"tags":["北极","熊","白色"],"emoji":"🐻‍❄️","text":"","type":1,"order":2713,"group":3,"subgroup":33,"version":13},{"annotation":"考拉","name":"KOALA","hexcode":"1F428","shortcodes":["koala_face"],"tags":["澳大利亚"],"emoji":"🐨","text":"","type":1,"order":2715,"group":3,"subgroup":33,"version":0.6},{"annotation":"熊猫","name":"PANDA FACE","hexcode":"1F43C","shortcodes":["panda_face"],"tags":["头","胖达","脸"],"emoji":"🐼","text":"","type":1,"order":2716,"group":3,"subgroup":33,"version":0.6},{"annotation":"树懒","name":"SLOTH","hexcode":"1F9A5","shortcodes":["sloth"],"tags":["慢","懒","爬树","迟缓"],"emoji":"🦥","text":"","type":1,"order":2717,"group":3,"subgroup":33,"version":12},{"annotation":"水獭","name":"OTTER","hexcode":"1F9A6","shortcodes":["otter"],"tags":["动物","捕鱼","獭","鼬"],"emoji":"🦦","text":"","type":1,"order":2718,"group":3,"subgroup":33,"version":12},{"annotation":"臭鼬","name":"SKUNK","hexcode":"1F9A8","shortcodes":["skunk"],"tags":["熏","臭","鼬"],"emoji":"🦨","text":"","type":1,"order":2719,"group":3,"subgroup":33,"version":12},{"annotation":"袋鼠","name":"KANGAROO","hexcode":"1F998","shortcodes":["kangaroo"],"tags":["小袋鼠","有袋类动物","澳大利亚","跳"],"emoji":"🦘","text":"","type":1,"order":2720,"group":3,"subgroup":33,"version":11},{"annotation":"獾","name":"BADGER","hexcode":"1F9A1","shortcodes":["badger"],"tags":["纠缠","蜜獾"],"emoji":"🦡","text":"","type":1,"order":2721,"group":3,"subgroup":33,"version":11},{"annotation":"爪印","name":"PAW PRINTS","hexcode":"1F43E","shortcodes":["feet"],"tags":["爪子","足迹"],"emoji":"🐾","text":"","type":1,"order":2722,"group":3,"subgroup":33,"version":0.6},{"annotation":"火鸡","name":"TURKEY","hexcode":"1F983","shortcodes":["turkey"],"tags":["火鸡"],"emoji":"🦃","text":"","type":1,"order":2723,"group":3,"subgroup":34,"version":1},{"annotation":"鸡","name":"CHICKEN","hexcode":"1F414","shortcodes":["chicken"],"tags":["鸡"],"emoji":"🐔","text":"","type":1,"order":2724,"group":3,"subgroup":34,"version":0.6},{"annotation":"公鸡","name":"ROOSTER","hexcode":"1F413","shortcodes":["rooster"],"tags":["鸡"],"emoji":"🐓","text":"","type":1,"order":2725,"group":3,"subgroup":34,"version":1},{"annotation":"小鸡破壳","name":"HATCHING CHICK","hexcode":"1F423","shortcodes":["hatching_chick"],"tags":["小鸡","破壳"],"emoji":"🐣","text":"","type":1,"order":2726,"group":3,"subgroup":34,"version":0.6},{"annotation":"小鸡","name":"BABY CHICK","hexcode":"1F424","shortcodes":["baby_chick"],"tags":["鸡"],"emoji":"🐤","text":"","type":1,"order":2727,"group":3,"subgroup":34,"version":0.6},{"annotation":"正面朝向的小鸡","name":"FRONT-FACING BABY CHICK","hexcode":"1F425","shortcodes":["hatched_chick"],"tags":["小鸡"],"emoji":"🐥","text":"","type":1,"order":2728,"group":3,"subgroup":34,"version":0.6},{"annotation":"鸟","name":"BIRD","hexcode":"1F426","shortcodes":["bird"],"tags":["鸟"],"emoji":"🐦️","text":"🐦︎","type":1,"order":2729,"group":3,"subgroup":34,"version":0.6},{"annotation":"企鹅","name":"PENGUIN","hexcode":"1F427","shortcodes":["penguin"],"tags":["企鹅"],"emoji":"🐧","text":"","type":1,"order":2730,"group":3,"subgroup":34,"version":0.6},{"annotation":"鸽","name":"DOVE OF PEACE","hexcode":"1F54A","shortcodes":["dove"],"tags":["和平象征","飞翔","鸟","鸽子"],"emoji":"🕊️","text":"🕊︎","type":0,"order":2732,"group":3,"subgroup":34,"version":0.7},{"annotation":"鹰","name":"EAGLE","hexcode":"1F985","shortcodes":["eagle"],"tags":["老鹰","鸟"],"emoji":"🦅","text":"","type":1,"order":2733,"group":3,"subgroup":34,"version":3},{"annotation":"鸭子","name":"DUCK","hexcode":"1F986","shortcodes":["duck"],"tags":["鸟","鸭"],"emoji":"🦆","text":"","type":1,"order":2734,"group":3,"subgroup":34,"version":3},{"annotation":"天鹅","name":"SWAN","hexcode":"1F9A2","shortcodes":["swan"],"tags":["丑小鸭","小天鹅","鸟"],"emoji":"🦢","text":"","type":1,"order":2735,"group":3,"subgroup":34,"version":11},{"annotation":"猫头鹰","name":"OWL","hexcode":"1F989","shortcodes":["owl"],"tags":["睿智","鸟"],"emoji":"🦉","text":"","type":1,"order":2736,"group":3,"subgroup":34,"version":3},{"annotation":"渡渡鸟","name":"DODO","hexcode":"1F9A4","shortcodes":["dodo"],"tags":["毛里求斯","灭绝"],"emoji":"🦤","text":"","type":1,"order":2737,"group":3,"subgroup":34,"version":13},{"annotation":"羽毛","name":"FEATHER","hexcode":"1FAB6","shortcodes":["feather"],"tags":["轻","飞","鸟"],"emoji":"🪶","text":"","type":1,"order":2738,"group":3,"subgroup":34,"version":13},{"annotation":"火烈鸟","name":"FLAMINGO","hexcode":"1F9A9","shortcodes":["flamingo"],"tags":["热带","艳丽"],"emoji":"🦩","text":"","type":1,"order":2739,"group":3,"subgroup":34,"version":12},{"annotation":"孔雀","name":"PEACOCK","hexcode":"1F99A","shortcodes":["peacock"],"tags":["招摇","雌孔雀","骄傲","鸟"],"emoji":"🦚","text":"","type":1,"order":2740,"group":3,"subgroup":34,"version":11},{"annotation":"鹦鹉","name":"PARROT","hexcode":"1F99C","shortcodes":["parrot"],"tags":["剽窃","模仿","说话","鸟"],"emoji":"🦜","text":"","type":1,"order":2741,"group":3,"subgroup":34,"version":11},{"annotation":"青蛙","name":"FROG FACE","hexcode":"1F438","shortcodes":["frog_face"],"tags":["头","脸"],"emoji":"🐸","text":"","type":1,"order":2742,"group":3,"subgroup":35,"version":0.6},{"annotation":"鳄鱼","name":"CROCODILE","hexcode":"1F40A","shortcodes":["crocodile"],"tags":["鳄鱼"],"emoji":"🐊","text":"","type":1,"order":2743,"group":3,"subgroup":36,"version":1},{"annotation":"龟","name":"TURTLE","hexcode":"1F422","shortcodes":["turtle"],"tags":["乌龟","海龟"],"emoji":"🐢","text":"","type":1,"order":2744,"group":3,"subgroup":36,"version":0.6},{"annotation":"蜥蜴","name":"LIZARD","hexcode":"1F98E","shortcodes":["lizard"],"tags":["爬行动物"],"emoji":"🦎","text":"","type":1,"order":2745,"group":3,"subgroup":36,"version":3},{"annotation":"蛇","name":"SNAKE","hexcode":"1F40D","shortcodes":["snake"],"tags":["持票人","狡猾的人","蛇夫座","黄道十二宫"],"emoji":"🐍","text":"","type":1,"order":2746,"group":3,"subgroup":36,"version":0.6},{"annotation":"龙头","name":"DRAGON FACE","hexcode":"1F432","shortcodes":["dragon_face"],"tags":["龙"],"emoji":"🐲","text":"","type":1,"order":2747,"group":3,"subgroup":36,"version":0.6},{"annotation":"龙","name":"DRAGON","hexcode":"1F409","shortcodes":["dragon"],"tags":["龙"],"emoji":"🐉","text":"","type":1,"order":2748,"group":3,"subgroup":36,"version":1},{"annotation":"蜥蜴类","name":"SAUROPOD","hexcode":"1F995","shortcodes":["sauropod"],"tags":["梁龙","腕龙","雷龙"],"emoji":"🦕","text":"","type":1,"order":2749,"group":3,"subgroup":36,"version":5},{"annotation":"霸王龙","name":"T-REX","hexcode":"1F996","shortcodes":["trex"],"tags":["暴龙君主"],"emoji":"🦖","text":"","type":1,"order":2750,"group":3,"subgroup":36,"version":5},{"annotation":"喷水的鲸","name":"SPOUTING WHALE","hexcode":"1F433","shortcodes":["spouting_whale"],"tags":["喷水","鲸"],"emoji":"🐳","text":"","type":1,"order":2751,"group":3,"subgroup":37,"version":0.6},{"annotation":"鲸鱼","name":"WHALE","hexcode":"1F40B","shortcodes":["whale"],"tags":["鲸鱼"],"emoji":"🐋","text":"","type":1,"order":2752,"group":3,"subgroup":37,"version":1},{"annotation":"海豚","name":"DOLPHIN","hexcode":"1F42C","shortcodes":["dolphin"],"tags":["鸭脚板"],"emoji":"🐬","text":"","type":1,"order":2753,"group":3,"subgroup":37,"version":0.6},{"annotation":"海豹","name":"SEAL","hexcode":"1F9AD","shortcodes":["seal"],"tags":["海狮"],"emoji":"🦭","text":"","type":1,"order":2754,"group":3,"subgroup":37,"version":13},{"annotation":"鱼","name":"FISH","hexcode":"1F41F","shortcodes":["fish"],"tags":["双鱼座","黄道十二宫"],"emoji":"🐟️","text":"🐟︎","type":1,"order":2755,"group":3,"subgroup":37,"version":0.6},{"annotation":"热带鱼","name":"TROPICAL FISH","hexcode":"1F420","shortcodes":["tropical_fish"],"tags":["热带","鱼"],"emoji":"🐠","text":"","type":1,"order":2756,"group":3,"subgroup":37,"version":0.6},{"annotation":"河豚","name":"BLOWFISH","hexcode":"1F421","shortcodes":["blowfish"],"tags":["鱼"],"emoji":"🐡","text":"","type":1,"order":2757,"group":3,"subgroup":37,"version":0.6},{"annotation":"鲨鱼","name":"SHARK","hexcode":"1F988","shortcodes":["shark"],"tags":["鱼","鲨"],"emoji":"🦈","text":"","type":1,"order":2758,"group":3,"subgroup":37,"version":3},{"annotation":"章鱼","name":"OCTOPUS","hexcode":"1F419","shortcodes":["octopus"],"tags":["八爪","鱼"],"emoji":"🐙","text":"","type":1,"order":2759,"group":3,"subgroup":37,"version":0.6},{"annotation":"海螺","name":"SPIRAL SHELL","hexcode":"1F41A","shortcodes":["shell"],"tags":["螺"],"emoji":"🐚","text":"","type":1,"order":2760,"group":3,"subgroup":37,"version":0.6},{"annotation":"蜗牛","name":"SNAIL","hexcode":"1F40C","shortcodes":["snail"],"tags":["蜗牛"],"emoji":"🐌","text":"","type":1,"order":2761,"group":3,"subgroup":38,"version":0.6},{"annotation":"蝴蝶","name":"BUTTERFLY","hexcode":"1F98B","shortcodes":["butterfly"],"tags":["昆虫","漂亮","美丽"],"emoji":"🦋","text":"","type":1,"order":2762,"group":3,"subgroup":38,"version":3},{"annotation":"毛毛虫","name":"BUG","hexcode":"1F41B","shortcodes":["bug"],"tags":["毛虫"],"emoji":"🐛","text":"","type":1,"order":2763,"group":3,"subgroup":38,"version":0.6},{"annotation":"蚂蚁","name":"ANT","hexcode":"1F41C","shortcodes":["ant"],"tags":["蚂蚁"],"emoji":"🐜","text":"","type":1,"order":2764,"group":3,"subgroup":38,"version":0.6},{"annotation":"蜜蜂","name":"HONEYBEE","hexcode":"1F41D","shortcodes":["bee"],"tags":["勤劳"],"emoji":"🐝","text":"","type":1,"order":2765,"group":3,"subgroup":38,"version":0.6},{"annotation":"甲虫","name":"BEETLE","hexcode":"1FAB2","shortcodes":["beetle"],"tags":["昆虫"],"emoji":"🪲","text":"","type":1,"order":2766,"group":3,"subgroup":38,"version":13},{"annotation":"瓢虫","name":"LADY BEETLE","hexcode":"1F41E","shortcodes":["lady_bug"],"tags":["昆虫","母"],"emoji":"🐞","text":"","type":1,"order":2767,"group":3,"subgroup":38,"version":0.6},{"annotation":"蟋蟀","name":"CRICKET","hexcode":"1F997","shortcodes":["cricket"],"tags":["蛐蛐"],"emoji":"🦗","text":"","type":1,"order":2768,"group":3,"subgroup":38,"version":5},{"annotation":"蟑螂","name":"COCKROACH","hexcode":"1FAB3","shortcodes":["cockroach"],"tags":["害虫","昆虫"],"emoji":"🪳","text":"","type":1,"order":2769,"group":3,"subgroup":38,"version":13},{"annotation":"蜘蛛","name":"SPIDER","hexcode":"1F577","shortcodes":["spider"],"tags":["蜘蛛"],"emoji":"🕷️","text":"🕷︎","type":0,"order":2771,"group":3,"subgroup":38,"version":0.7},{"annotation":"蜘蛛网","name":"SPIDER WEB","hexcode":"1F578","shortcodes":["spider_web"],"tags":["蛛网"],"emoji":"🕸️","text":"🕸︎","type":0,"order":2773,"group":3,"subgroup":38,"version":0.7},{"annotation":"蝎子","name":"SCORPION","hexcode":"1F982","shortcodes":["scorpion"],"tags":["天蝎宫","天蝎座","黄道十二宫"],"emoji":"🦂","text":"","type":1,"order":2774,"group":3,"subgroup":38,"version":1},{"annotation":"蚊子","name":"MOSQUITO","hexcode":"1F99F","shortcodes":["mosquito"],"tags":["发热","昆虫","疟疾","疾病","病毒"],"emoji":"🦟","text":"","type":1,"order":2775,"group":3,"subgroup":38,"version":11},{"annotation":"苍蝇","name":"FLY","hexcode":"1FAB0","shortcodes":["fly"],"tags":["害虫","疾病","腐烂","蛆"],"emoji":"🪰","text":"","type":1,"order":2776,"group":3,"subgroup":38,"version":13},{"annotation":"蠕虫","name":"WORM","hexcode":"1FAB1","shortcodes":["worm"],"tags":["寄生虫","环节动物","蚯蚓"],"emoji":"🪱","text":"","type":1,"order":2777,"group":3,"subgroup":38,"version":13},{"annotation":"细菌","name":"MICROBE","hexcode":"1F9A0","shortcodes":["microbe","germ"],"tags":["变形虫","病毒"],"emoji":"🦠","text":"","type":1,"order":2778,"group":3,"subgroup":38,"version":11},{"annotation":"花束","name":"BOUQUET","hexcode":"1F490","shortcodes":["bouquet"],"tags":["鲜花"],"emoji":"💐","text":"","type":1,"order":2779,"group":3,"subgroup":39,"version":0.6},{"annotation":"樱花","name":"CHERRY BLOSSOM","hexcode":"1F338","shortcodes":["cherry_blossom"],"tags":["花"],"emoji":"🌸","text":"","type":1,"order":2780,"group":3,"subgroup":39,"version":0.6},{"annotation":"白花","name":"WHITE FLOWER","hexcode":"1F4AE","shortcodes":["white_flower"],"tags":["花"],"emoji":"💮","text":"","type":1,"order":2781,"group":3,"subgroup":39,"version":0.6},{"annotation":"圆形花饰","name":"ROSETTE","hexcode":"1F3F5","shortcodes":["rosette"],"tags":["花"],"emoji":"🏵️","text":"🏵︎","type":0,"order":2783,"group":3,"subgroup":39,"version":0.7},{"annotation":"玫瑰","name":"ROSE","hexcode":"1F339","shortcodes":["rose"],"tags":["花"],"emoji":"🌹","text":"","type":1,"order":2784,"group":3,"subgroup":39,"version":0.6},{"annotation":"枯萎的花","name":"WILTED FLOWER","hexcode":"1F940","shortcodes":["wilted_rose"],"tags":["花"],"emoji":"🥀","text":"","type":1,"order":2785,"group":3,"subgroup":39,"version":3},{"annotation":"芙蓉","name":"HIBISCUS","hexcode":"1F33A","shortcodes":["hibiscus"],"tags":["木槿","花"],"emoji":"🌺","text":"","type":1,"order":2786,"group":3,"subgroup":39,"version":0.6},{"annotation":"向日葵","name":"SUNFLOWER","hexcode":"1F33B","shortcodes":["sunflower"],"tags":["太阳花","花"],"emoji":"🌻","text":"","type":1,"order":2787,"group":3,"subgroup":39,"version":0.6},{"annotation":"开花","name":"BLOSSOM","hexcode":"1F33C","shortcodes":["blossom"],"tags":["花"],"emoji":"🌼","text":"","type":1,"order":2788,"group":3,"subgroup":39,"version":0.6},{"annotation":"郁金香","name":"TULIP","hexcode":"1F337","shortcodes":["tulip"],"tags":["花"],"emoji":"🌷","text":"","type":1,"order":2789,"group":3,"subgroup":39,"version":0.6},{"annotation":"幼苗","name":"SEEDLING","hexcode":"1F331","shortcodes":["seedling"],"tags":["发芽","芽","苗"],"emoji":"🌱","text":"","type":1,"order":2790,"group":3,"subgroup":40,"version":0.6},{"annotation":"盆栽植物","name":"POTTED PLANT","hexcode":"1FAB4","shortcodes":["potted_plant"],"tags":["培育","房子","枯燥","植物","生长"],"emoji":"🪴","text":"","type":1,"order":2791,"group":3,"subgroup":40,"version":13},{"annotation":"松树","name":"EVERGREEN TREE","hexcode":"1F332","shortcodes":["evergreen_tree"],"tags":["常青树","树"],"emoji":"🌲","text":"","type":1,"order":2792,"group":3,"subgroup":40,"version":1},{"annotation":"落叶树","name":"DECIDUOUS TREE","hexcode":"1F333","shortcodes":["deciduous_tree"],"tags":["树","落叶","落叶植物"],"emoji":"🌳","text":"","type":1,"order":2793,"group":3,"subgroup":40,"version":1},{"annotation":"棕榈树","name":"PALM TREE","hexcode":"1F334","shortcodes":["palm_tree"],"tags":["棕榈树"],"emoji":"🌴","text":"","type":1,"order":2794,"group":3,"subgroup":40,"version":0.6},{"annotation":"仙人掌","name":"CACTUS","hexcode":"1F335","shortcodes":["cactus"],"tags":["沙漠"],"emoji":"🌵","text":"","type":1,"order":2795,"group":3,"subgroup":40,"version":0.6},{"annotation":"稻子","name":"EAR OF RICE","hexcode":"1F33E","shortcodes":["ear_of_rice"],"tags":["稻","米","粮食"],"emoji":"🌾","text":"","type":1,"order":2796,"group":3,"subgroup":40,"version":0.6},{"annotation":"药草","name":"HERB","hexcode":"1F33F","shortcodes":["herb"],"tags":["草药","香草"],"emoji":"🌿","text":"","type":1,"order":2797,"group":3,"subgroup":40,"version":0.6},{"annotation":"三叶草","name":"SHAMROCK","hexcode":"2618","shortcodes":["shamrock"],"tags":["苜蓿","酢浆草"],"emoji":"☘️","text":"☘︎","type":0,"order":2799,"group":3,"subgroup":40,"version":1},{"annotation":"四叶草","name":"FOUR LEAF CLOVER","hexcode":"1F340","shortcodes":["four_leaf_clover"],"tags":["幸运"],"emoji":"🍀","text":"","type":1,"order":2800,"group":3,"subgroup":40,"version":0.6},{"annotation":"枫叶","name":"MAPLE LEAF","hexcode":"1F341","shortcodes":["maple_leaf"],"tags":["加拿大","秋"],"emoji":"🍁","text":"","type":1,"order":2801,"group":3,"subgroup":40,"version":0.6},{"annotation":"落叶","name":"FALLEN LEAF","hexcode":"1F342","shortcodes":["fallen_leaf"],"tags":["叶","秋"],"emoji":"🍂","text":"","type":1,"order":2802,"group":3,"subgroup":40,"version":0.6},{"annotation":"风吹叶落","name":"LEAF FLUTTERING IN WIND","hexcode":"1F343","shortcodes":["leaves"],"tags":["叶子","树叶","随风飘舞"],"emoji":"🍃","text":"","type":1,"order":2803,"group":3,"subgroup":40,"version":0.6},{"annotation":"葡萄","name":"GRAPES","hexcode":"1F347","shortcodes":["grapes"],"tags":["水果"],"emoji":"🍇","text":"","type":1,"order":2804,"group":4,"subgroup":41,"version":0.6},{"annotation":"甜瓜","name":"MELON","hexcode":"1F348","shortcodes":["melon"],"tags":["水果","蜜瓜","香瓜"],"emoji":"🍈","text":"","type":1,"order":2805,"group":4,"subgroup":41,"version":0.6},{"annotation":"西瓜","name":"WATERMELON","hexcode":"1F349","shortcodes":["watermelon"],"tags":["水果"],"emoji":"🍉","text":"","type":1,"order":2806,"group":4,"subgroup":41,"version":0.6},{"annotation":"橘子","name":"TANGERINE","hexcode":"1F34A","shortcodes":["tangerine"],"tags":["柑桔","桔子","水果"],"emoji":"🍊","text":"","type":1,"order":2807,"group":4,"subgroup":41,"version":0.6},{"annotation":"柠檬","name":"LEMON","hexcode":"1F34B","shortcodes":["lemon"],"tags":["水果"],"emoji":"🍋","text":"","type":1,"order":2808,"group":4,"subgroup":41,"version":1},{"annotation":"香蕉","name":"BANANA","hexcode":"1F34C","shortcodes":["banana"],"tags":["水果"],"emoji":"🍌","text":"","type":1,"order":2809,"group":4,"subgroup":41,"version":0.6},{"annotation":"菠萝","name":"PINEAPPLE","hexcode":"1F34D","shortcodes":["pineapple"],"tags":["水果"],"emoji":"🍍","text":"","type":1,"order":2810,"group":4,"subgroup":41,"version":0.6},{"annotation":"芒果","name":"MANGO","hexcode":"1F96D","shortcodes":["mango"],"tags":["水果","热带"],"emoji":"🥭","text":"","type":1,"order":2811,"group":4,"subgroup":41,"version":11},{"annotation":"红苹果","name":"RED APPLE","hexcode":"1F34E","shortcodes":["apple"],"tags":["水果","红","苹果"],"emoji":"🍎","text":"","type":1,"order":2812,"group":4,"subgroup":41,"version":0.6},{"annotation":"青苹果","name":"GREEN APPLE","hexcode":"1F34F","shortcodes":["green_apple"],"tags":["水果","苹果","青"],"emoji":"🍏","text":"","type":1,"order":2813,"group":4,"subgroup":41,"version":0.6},{"annotation":"梨","name":"PEAR","hexcode":"1F350","shortcodes":["pear"],"tags":["水果"],"emoji":"🍐","text":"","type":1,"order":2814,"group":4,"subgroup":41,"version":1},{"annotation":"桃","name":"PEACH","hexcode":"1F351","shortcodes":["peach"],"tags":["水果"],"emoji":"🍑","text":"","type":1,"order":2815,"group":4,"subgroup":41,"version":0.6},{"annotation":"樱桃","name":"CHERRIES","hexcode":"1F352","shortcodes":["cherries"],"tags":["水果"],"emoji":"🍒","text":"","type":1,"order":2816,"group":4,"subgroup":41,"version":0.6},{"annotation":"草莓","name":"STRAWBERRY","hexcode":"1F353","shortcodes":["strawberry"],"tags":["水果"],"emoji":"🍓","text":"","type":1,"order":2817,"group":4,"subgroup":41,"version":0.6},{"annotation":"蓝莓","name":"BLUEBERRIES","hexcode":"1FAD0","shortcodes":["blueberry"],"tags":["越桔"],"emoji":"🫐","text":"","type":1,"order":2818,"group":4,"subgroup":41,"version":13},{"annotation":"猕猴桃","name":"KIWIFRUIT","hexcode":"1F95D","shortcodes":["kiwi"],"tags":["奇异果","水果","食物"],"emoji":"🥝","text":"","type":1,"order":2819,"group":4,"subgroup":41,"version":3},{"annotation":"西红柿","name":"TOMATO","hexcode":"1F345","shortcodes":["tomato"],"tags":["番茄","蔬菜"],"emoji":"🍅","text":"","type":1,"order":2820,"group":4,"subgroup":41,"version":0.6},{"annotation":"橄榄","name":"OLIVE","hexcode":"1FAD2","shortcodes":["olive"],"tags":["食物"],"emoji":"🫒","text":"","type":1,"order":2821,"group":4,"subgroup":41,"version":13},{"annotation":"椰子","name":"COCONUT","hexcode":"1F965","shortcodes":["coconut"],"tags":["棕榈"],"emoji":"🥥","text":"","type":1,"order":2822,"group":4,"subgroup":41,"version":5},{"annotation":"鳄梨","name":"AVOCADO","hexcode":"1F951","shortcodes":["avocado"],"tags":["水果","牛油果","食物"],"emoji":"🥑","text":"","type":1,"order":2823,"group":4,"subgroup":42,"version":3},{"annotation":"茄子","name":"AUBERGINE","hexcode":"1F346","shortcodes":["eggplant"],"tags":["蔬菜"],"emoji":"🍆","text":"","type":1,"order":2824,"group":4,"subgroup":42,"version":0.6},{"annotation":"土豆","name":"POTATO","hexcode":"1F954","shortcodes":["potato"],"tags":["蔬菜","食物","马铃薯"],"emoji":"🥔","text":"","type":1,"order":2825,"group":4,"subgroup":42,"version":3},{"annotation":"胡萝卜","name":"CARROT","hexcode":"1F955","shortcodes":["carrot"],"tags":["蔬菜","食物"],"emoji":"🥕","text":"","type":1,"order":2826,"group":4,"subgroup":42,"version":3},{"annotation":"玉米","name":"EAR OF MAIZE","hexcode":"1F33D","shortcodes":["corn"],"tags":["苞米"],"emoji":"🌽","text":"","type":1,"order":2827,"group":4,"subgroup":42,"version":0.6},{"annotation":"红辣椒","name":"HOT PEPPER","hexcode":"1F336","shortcodes":["hot_pepper"],"tags":["辣椒"],"emoji":"🌶️","text":"🌶︎","type":0,"order":2829,"group":4,"subgroup":42,"version":0.7},{"annotation":"灯笼椒","name":"BELL PEPPER","hexcode":"1FAD1","shortcodes":["bell_pepper"],"tags":["蔬菜","辣椒"],"emoji":"🫑","text":"","type":1,"order":2830,"group":4,"subgroup":42,"version":13},{"annotation":"黄瓜","name":"CUCUMBER","hexcode":"1F952","shortcodes":["cucumber"],"tags":["泡菜","蔬菜","食物"],"emoji":"🥒","text":"","type":1,"order":2831,"group":4,"subgroup":42,"version":3},{"annotation":"绿叶蔬菜","name":"LEAFY GREEN","hexcode":"1F96C","shortcodes":["leafy_green"],"tags":["圆白菜","小白菜","甘蓝","莴苣"],"emoji":"🥬","text":"","type":1,"order":2832,"group":4,"subgroup":42,"version":11},{"annotation":"西兰花","name":"BROCCOLI","hexcode":"1F966","shortcodes":["broccoli"],"tags":["甘蓝"],"emoji":"🥦","text":"","type":1,"order":2833,"group":4,"subgroup":42,"version":5},{"annotation":"蒜","name":"GARLIC","hexcode":"1F9C4","shortcodes":["garlic"],"tags":["佐料","大蒜","蒜头","调味"],"emoji":"🧄","text":"","type":1,"order":2834,"group":4,"subgroup":42,"version":12},{"annotation":"洋葱","name":"ONION","hexcode":"1F9C5","shortcodes":["onion"],"tags":["佐料","调味"],"emoji":"🧅","text":"","type":1,"order":2835,"group":4,"subgroup":42,"version":12},{"annotation":"蘑菇","name":"MUSHROOM","hexcode":"1F344","shortcodes":["mushroom"],"tags":["蘑菇"],"emoji":"🍄","text":"","type":1,"order":2836,"group":4,"subgroup":42,"version":0.6},{"annotation":"花生","name":"PEANUTS","hexcode":"1F95C","shortcodes":["peanuts"],"tags":["坚果","蔬菜","食物"],"emoji":"🥜","text":"","type":1,"order":2837,"group":4,"subgroup":42,"version":3},{"annotation":"栗子","name":"CHESTNUT","hexcode":"1F330","shortcodes":["chestnut"],"tags":["栗子"],"emoji":"🌰","text":"","type":1,"order":2838,"group":4,"subgroup":42,"version":0.6},{"annotation":"面包","name":"BREAD","hexcode":"1F35E","shortcodes":["bread"],"tags":["面包"],"emoji":"🍞","text":"","type":1,"order":2839,"group":4,"subgroup":43,"version":0.6},{"annotation":"羊角面包","name":"CROISSANT","hexcode":"1F950","shortcodes":["croissant"],"tags":["新月形面包","法式","面包","食物"],"emoji":"🥐","text":"","type":1,"order":2840,"group":4,"subgroup":43,"version":3},{"annotation":"法式长棍面包","name":"BAGUETTE BREAD","hexcode":"1F956","shortcodes":["french_bread"],"tags":["法式","面包","食物"],"emoji":"🥖","text":"","type":1,"order":2841,"group":4,"subgroup":43,"version":3},{"annotation":"扁面包","name":"FLATBREAD","hexcode":"1FAD3","shortcodes":["flatbread"],"tags":["圆盘状烤饼","玉米饼","皮塔饼","薄脆饼"],"emoji":"🫓","text":"","type":1,"order":2842,"group":4,"subgroup":43,"version":13},{"annotation":"椒盐卷饼","name":"PRETZEL","hexcode":"1F968","shortcodes":["pretzel"],"tags":["扭曲食品"],"emoji":"🥨","text":"","type":1,"order":2843,"group":4,"subgroup":43,"version":5},{"annotation":"面包圈","name":"BAGEL","hexcode":"1F96F","shortcodes":["bagel"],"tags":["奶酪酱","烘烤食品"],"emoji":"🥯","text":"","type":1,"order":2844,"group":4,"subgroup":43,"version":11},{"annotation":"烙饼","name":"PANCAKES","hexcode":"1F95E","shortcodes":["pancakes"],"tags":["煎饼","食物"],"emoji":"🥞","text":"","type":1,"order":2845,"group":4,"subgroup":43,"version":3},{"annotation":"华夫饼","name":"WAFFLE","hexcode":"1F9C7","shortcodes":["waffle"],"tags":["格子饼","点心","烤","窝夫饼"],"emoji":"🧇","text":"","type":1,"order":2846,"group":4,"subgroup":43,"version":12},{"annotation":"芝士","name":"CHEESE WEDGE","hexcode":"1F9C0","shortcodes":["cheese"],"tags":["奶酪","起司"],"emoji":"🧀","text":"","type":1,"order":2847,"group":4,"subgroup":43,"version":1},{"annotation":"排骨","name":"MEAT ON BONE","hexcode":"1F356","shortcodes":["meat_on_bone"],"tags":["肉","骨"],"emoji":"🍖","text":"","type":1,"order":2848,"group":4,"subgroup":43,"version":0.6},{"annotation":"家禽的腿","name":"POULTRY LEG","hexcode":"1F357","shortcodes":["poultry_leg"],"tags":["家禽","鸡肉","鸡腿"],"emoji":"🍗","text":"","type":1,"order":2849,"group":4,"subgroup":43,"version":0.6},{"annotation":"肉块","name":"CUT OF MEAT","hexcode":"1F969","shortcodes":["cut_of_meat"],"tags":["排骨","牛排","猪排","羊排"],"emoji":"🥩","text":"","type":1,"order":2850,"group":4,"subgroup":43,"version":5},{"annotation":"培根","name":"BACON","hexcode":"1F953","shortcodes":["bacon"],"tags":["熏肉","肉","食物"],"emoji":"🥓","text":"","type":1,"order":2851,"group":4,"subgroup":43,"version":3},{"annotation":"汉堡","name":"HAMBURGER","hexcode":"1F354","shortcodes":["hamburger"],"tags":["汉堡包"],"emoji":"🍔","text":"","type":1,"order":2852,"group":4,"subgroup":43,"version":0.6},{"annotation":"薯条","name":"FRENCH FRIES","hexcode":"1F35F","shortcodes":["fries"],"tags":["油炸"],"emoji":"🍟","text":"","type":1,"order":2853,"group":4,"subgroup":43,"version":0.6},{"annotation":"披萨","name":"SLICE OF PIZZA","hexcode":"1F355","shortcodes":["pizza"],"tags":["披萨"],"emoji":"🍕","text":"","type":1,"order":2854,"group":4,"subgroup":43,"version":0.6},{"annotation":"热狗","name":"HOT DOG","hexcode":"1F32D","shortcodes":["hotdog"],"tags":["热狗"],"emoji":"🌭","text":"","type":1,"order":2855,"group":4,"subgroup":43,"version":1},{"annotation":"三明治","name":"SANDWICH","hexcode":"1F96A","shortcodes":["sandwich"],"tags":["面包"],"emoji":"🥪","text":"","type":1,"order":2856,"group":4,"subgroup":43,"version":5},{"annotation":"墨西哥卷饼","name":"TACO","hexcode":"1F32E","shortcodes":["taco"],"tags":["卷饼","墨西哥"],"emoji":"🌮","text":"","type":1,"order":2857,"group":4,"subgroup":43,"version":1},{"annotation":"墨西哥玉米煎饼","name":"BURRITO","hexcode":"1F32F","shortcodes":["burrito"],"tags":["卷饼","墨西哥","玉米煎饼"],"emoji":"🌯","text":"","type":1,"order":2858,"group":4,"subgroup":43,"version":1},{"annotation":"墨西哥粽子","name":"TAMALE","hexcode":"1FAD4","shortcodes":["tamale"],"tags":["墨西哥","粽子"],"emoji":"🫔","text":"","type":1,"order":2859,"group":4,"subgroup":43,"version":13},{"annotation":"夹心饼","name":"STUFFED FLATBREAD","hexcode":"1F959","shortcodes":["stuffed_flatbread"],"tags":["夹心","沙拉三明治","肉夹馍","食物"],"emoji":"🥙","text":"","type":1,"order":2860,"group":4,"subgroup":43,"version":3},{"annotation":"炸豆丸子","name":"FALAFEL","hexcode":"1F9C6","shortcodes":["falafel"],"tags":["中东蔬菜球","油炸鹰嘴豆饼","肉丸","鹰嘴豆"],"emoji":"🧆","text":"","type":1,"order":2861,"group":4,"subgroup":43,"version":12},{"annotation":"蛋","name":"EGG","hexcode":"1F95A","shortcodes":["egg"],"tags":["食物"],"emoji":"🥚","text":"","type":1,"order":2862,"group":4,"subgroup":43,"version":3},{"annotation":"煎蛋","name":"COOKING","hexcode":"1F373","shortcodes":["cooking"],"tags":["平底锅","煎","蛋"],"emoji":"🍳","text":"","type":1,"order":2863,"group":4,"subgroup":43,"version":0.6},{"annotation":"装有食物的浅底锅","name":"SHALLOW PAN OF FOOD","hexcode":"1F958","shortcodes":["shallow_pan_of_food"],"tags":["浅底","煎锅","食物"],"emoji":"🥘","text":"","type":1,"order":2864,"group":4,"subgroup":43,"version":3},{"annotation":"一锅食物","name":"POT OF FOOD","hexcode":"1F372","shortcodes":["stew"],"tags":["食物"],"emoji":"🍲","text":"","type":1,"order":2865,"group":4,"subgroup":43,"version":0.6},{"annotation":"奶酪火锅","name":"FONDUE","hexcode":"1FAD5","shortcodes":["fondue"],"tags":["奶酪","巧克力","瑞士","融化","锅"],"emoji":"🫕","text":"","type":1,"order":2866,"group":4,"subgroup":43,"version":13},{"annotation":"碗勺","name":"BOWL WITH SPOON","hexcode":"1F963","shortcodes":["bowl_spoon"],"tags":["早餐","粥","谷物"],"emoji":"🥣","text":"","type":1,"order":2867,"group":4,"subgroup":43,"version":5},{"annotation":"绿色沙拉","name":"GREEN SALAD","hexcode":"1F957","shortcodes":["salad"],"tags":["沙拉","食物"],"emoji":"🥗","text":"","type":1,"order":2868,"group":4,"subgroup":43,"version":3},{"annotation":"爆米花","name":"POPCORN","hexcode":"1F37F","shortcodes":["popcorn"],"tags":["爆米花"],"emoji":"🍿","text":"","type":1,"order":2869,"group":4,"subgroup":43,"version":1},{"annotation":"黄油","name":"BUTTER","hexcode":"1F9C8","shortcodes":["butter"],"tags":["乳制品","牛奶"],"emoji":"🧈","text":"","type":1,"order":2870,"group":4,"subgroup":43,"version":12},{"annotation":"盐","name":"SALT SHAKER","hexcode":"1F9C2","shortcodes":["salt"],"tags":["佐料瓶","调味品"],"emoji":"🧂","text":"","type":1,"order":2871,"group":4,"subgroup":43,"version":11},{"annotation":"罐头食品","name":"CANNED FOOD","hexcode":"1F96B","shortcodes":["canned_food"],"tags":["罐头"],"emoji":"🥫","text":"","type":1,"order":2872,"group":4,"subgroup":43,"version":5},{"annotation":"盒饭","name":"BENTO BOX","hexcode":"1F371","shortcodes":["bento"],"tags":["便当"],"emoji":"🍱","text":"","type":1,"order":2873,"group":4,"subgroup":44,"version":0.6},{"annotation":"米饼","name":"RICE CRACKER","hexcode":"1F358","shortcodes":["rice_cracker"],"tags":["米果"],"emoji":"🍘","text":"","type":1,"order":2874,"group":4,"subgroup":44,"version":0.6},{"annotation":"饭团","name":"RICE BALL","hexcode":"1F359","shortcodes":["rice_ball"],"tags":["日本"],"emoji":"🍙","text":"","type":1,"order":2875,"group":4,"subgroup":44,"version":0.6},{"annotation":"米饭","name":"COOKED RICE","hexcode":"1F35A","shortcodes":["rice"],"tags":["米","饭"],"emoji":"🍚","text":"","type":1,"order":2876,"group":4,"subgroup":44,"version":0.6},{"annotation":"咖喱饭","name":"CURRY AND RICE","hexcode":"1F35B","shortcodes":["curry"],"tags":["咖喱","饭"],"emoji":"🍛","text":"","type":1,"order":2877,"group":4,"subgroup":44,"version":0.6},{"annotation":"面条","name":"STEAMING BOWL","hexcode":"1F35C","shortcodes":["ramen"],"tags":["拉面","热气腾腾","碗"],"emoji":"🍜","text":"","type":1,"order":2878,"group":4,"subgroup":44,"version":0.6},{"annotation":"意粉","name":"SPAGHETTI","hexcode":"1F35D","shortcodes":["spaghetti"],"tags":["意大利面","意面"],"emoji":"🍝","text":"","type":1,"order":2879,"group":4,"subgroup":44,"version":0.6},{"annotation":"烤红薯","name":"ROASTED SWEET POTATO","hexcode":"1F360","shortcodes":["sweet_potato"],"tags":["地瓜","烤地瓜","红薯"],"emoji":"🍠","text":"","type":1,"order":2880,"group":4,"subgroup":44,"version":0.6},{"annotation":"关东煮","name":"ODEN","hexcode":"1F362","shortcodes":["oden"],"tags":["串","海鲜"],"emoji":"🍢","text":"","type":1,"order":2881,"group":4,"subgroup":44,"version":0.6},{"annotation":"寿司","name":"SUSHI","hexcode":"1F363","shortcodes":["sushi"],"tags":["寿司"],"emoji":"🍣","text":"","type":1,"order":2882,"group":4,"subgroup":44,"version":0.6},{"annotation":"天妇罗","name":"FRIED SHRIMP","hexcode":"1F364","shortcodes":["fried_shrimp"],"tags":["炸虾"],"emoji":"🍤","text":"","type":1,"order":2883,"group":4,"subgroup":44,"version":0.6},{"annotation":"鱼板","name":"FISH CAKE WITH SWIRL DESIGN","hexcode":"1F365","shortcodes":["fish_cake"],"tags":["鱼板"],"emoji":"🍥","text":"","type":1,"order":2884,"group":4,"subgroup":44,"version":0.6},{"annotation":"月饼","name":"MOON CAKE","hexcode":"1F96E","shortcodes":["moon_cake"],"tags":["秋天","节日"],"emoji":"🥮","text":"","type":1,"order":2885,"group":4,"subgroup":44,"version":11},{"annotation":"团子","name":"DANGO","hexcode":"1F361","shortcodes":["dango"],"tags":["串","日本","甜点"],"emoji":"🍡","text":"","type":1,"order":2886,"group":4,"subgroup":44,"version":0.6},{"annotation":"饺子","name":"DUMPLING","hexcode":"1F95F","shortcodes":["dumpling"],"tags":["水饺","煎饺"],"emoji":"🥟","text":"","type":1,"order":2887,"group":4,"subgroup":44,"version":5},{"annotation":"幸运饼干","name":"FORTUNE COOKIE","hexcode":"1F960","shortcodes":["fortune_cookie"],"tags":["预言"],"emoji":"🥠","text":"","type":1,"order":2888,"group":4,"subgroup":44,"version":5},{"annotation":"外卖盒","name":"TAKEOUT BOX","hexcode":"1F961","shortcodes":["takeout_box"],"tags":["外卖包装","外卖桶","牡蛎桶"],"emoji":"🥡","text":"","type":1,"order":2889,"group":4,"subgroup":44,"version":5},{"annotation":"蟹","name":"CRAB","hexcode":"1F980","shortcodes":["crab"],"tags":["巨蟹座","螃蟹","黄道十二宫"],"emoji":"🦀","text":"","type":1,"order":2890,"group":4,"subgroup":45,"version":1},{"annotation":"龙虾","name":"LOBSTER","hexcode":"1F99E","shortcodes":["lobster"],"tags":["浓汤","海鲜","钳"],"emoji":"🦞","text":"","type":1,"order":2891,"group":4,"subgroup":45,"version":11},{"annotation":"虾","name":"SHRIMP","hexcode":"1F990","shortcodes":["shrimp"],"tags":["甲壳","食物"],"emoji":"🦐","text":"","type":1,"order":2892,"group":4,"subgroup":45,"version":3},{"annotation":"乌贼","name":"SQUID","hexcode":"1F991","shortcodes":["squid"],"tags":["墨鱼","软体动物","食物","鱿鱼"],"emoji":"🦑","text":"","type":1,"order":2893,"group":4,"subgroup":45,"version":3},{"annotation":"牡蛎","name":"OYSTER","hexcode":"1F9AA","shortcodes":["oyster"],"tags":["海鲜","珍珠","生蚝"],"emoji":"🦪","text":"","type":1,"order":2894,"group":4,"subgroup":45,"version":12},{"annotation":"圆筒冰激凌","name":"SOFT ICE CREAM","hexcode":"1F366","shortcodes":["icecream"],"tags":["圆筒冰淇淋"],"emoji":"🍦","text":"","type":1,"order":2895,"group":4,"subgroup":46,"version":0.6},{"annotation":"刨冰","name":"SHAVED ICE","hexcode":"1F367","shortcodes":["shaved_ice"],"tags":["冰","冰沙","甜点"],"emoji":"🍧","text":"","type":1,"order":2896,"group":4,"subgroup":46,"version":0.6},{"annotation":"冰淇淋","name":"ICE CREAM","hexcode":"1F368","shortcodes":["ice_cream"],"tags":["冰","冰激凌","甜点"],"emoji":"🍨","text":"","type":1,"order":2897,"group":4,"subgroup":46,"version":0.6},{"annotation":"甜甜圈","name":"DOUGHNUT","hexcode":"1F369","shortcodes":["doughnut"],"tags":["甜点"],"emoji":"🍩","text":"","type":1,"order":2898,"group":4,"subgroup":46,"version":0.6},{"annotation":"饼干","name":"COOKIE","hexcode":"1F36A","shortcodes":["cookie"],"tags":["曲奇"],"emoji":"🍪","text":"","type":1,"order":2899,"group":4,"subgroup":46,"version":0.6},{"annotation":"生日蛋糕","name":"BIRTHDAY CAKE","hexcode":"1F382","shortcodes":["birthday"],"tags":["庆祝","生日","蛋糕"],"emoji":"🎂","text":"","type":1,"order":2900,"group":4,"subgroup":46,"version":0.6},{"annotation":"水果蛋糕","name":"SHORTCAKE","hexcode":"1F370","shortcodes":["cake"],"tags":["甜点","蛋糕"],"emoji":"🍰","text":"","type":1,"order":2901,"group":4,"subgroup":46,"version":0.6},{"annotation":"纸杯蛋糕","name":"CUPCAKE","hexcode":"1F9C1","shortcodes":["cupcake"],"tags":["烘焙食品","甜点"],"emoji":"🧁","text":"","type":1,"order":2902,"group":4,"subgroup":46,"version":11},{"annotation":"派","name":"PIE","hexcode":"1F967","shortcodes":["pie"],"tags":["油酥点心","糕点"],"emoji":"🥧","text":"","type":1,"order":2903,"group":4,"subgroup":46,"version":5},{"annotation":"巧克力","name":"CHOCOLATE BAR","hexcode":"1F36B","shortcodes":["chocolate_bar"],"tags":["甜品","甜点"],"emoji":"🍫","text":"","type":1,"order":2904,"group":4,"subgroup":46,"version":0.6},{"annotation":"糖","name":"CANDY","hexcode":"1F36C","shortcodes":["candy"],"tags":["糖果"],"emoji":"🍬","text":"","type":1,"order":2905,"group":4,"subgroup":46,"version":0.6},{"annotation":"棒棒糖","name":"LOLLIPOP","hexcode":"1F36D","shortcodes":["lollipop"],"tags":["糖"],"emoji":"🍭","text":"","type":1,"order":2906,"group":4,"subgroup":46,"version":0.6},{"annotation":"奶黄","name":"CUSTARD","hexcode":"1F36E","shortcodes":["custard"],"tags":["蛋奶冻","蛋奶沙司"],"emoji":"🍮","text":"","type":1,"order":2907,"group":4,"subgroup":46,"version":0.6},{"annotation":"蜂蜜","name":"HONEY POT","hexcode":"1F36F","shortcodes":["honey_pot"],"tags":["蜜罐"],"emoji":"🍯","text":"","type":1,"order":2908,"group":4,"subgroup":46,"version":0.6},{"annotation":"奶瓶","name":"BABY BOTTLE","hexcode":"1F37C","shortcodes":["baby_bottle"],"tags":["奶","婴儿"],"emoji":"🍼","text":"","type":1,"order":2909,"group":4,"subgroup":47,"version":1},{"annotation":"一杯奶","name":"GLASS OF MILK","hexcode":"1F95B","shortcodes":["milk"],"tags":["奶","杯"],"emoji":"🥛","text":"","type":1,"order":2910,"group":4,"subgroup":47,"version":3},{"annotation":"热饮","name":"HOT BEVERAGE","hexcode":"2615","shortcodes":["coffee"],"tags":["咖啡","茶","饮料"],"emoji":"☕️","text":"☕︎","type":1,"order":2911,"group":4,"subgroup":47,"version":0.6},{"annotation":"茶壶","name":"TEAPOT","hexcode":"1FAD6","shortcodes":["teapot"],"tags":["壶","茶"],"emoji":"🫖","text":"","type":1,"order":2912,"group":4,"subgroup":47,"version":13},{"annotation":"热茶","name":"TEACUP WITHOUT HANDLE","hexcode":"1F375","shortcodes":["tea"],"tags":["杯","没有把手的茶杯","茶","饮料"],"emoji":"🍵","text":"","type":1,"order":2913,"group":4,"subgroup":47,"version":0.6},{"annotation":"清酒","name":"SAKE BOTTLE AND CUP","hexcode":"1F376","shortcodes":["sake"],"tags":["瓶","酒杯","饮料"],"emoji":"🍶","text":"","type":1,"order":2914,"group":4,"subgroup":47,"version":0.6},{"annotation":"开香槟","name":"BOTTLE WITH POPPING CORK","hexcode":"1F37E","shortcodes":["champagne"],"tags":["庆祝","木塞","瓶子","香槟"],"emoji":"🍾","text":"","type":1,"order":2915,"group":4,"subgroup":47,"version":1},{"annotation":"葡萄酒","name":"WINE GLASS","hexcode":"1F377","shortcodes":["wine_glass"],"tags":["酒","酒杯"],"emoji":"🍷","text":"","type":1,"order":2916,"group":4,"subgroup":47,"version":0.6},{"annotation":"鸡尾酒","name":"COCKTAIL GLASS","hexcode":"1F378","shortcodes":["cocktail"],"tags":["杯","酒"],"emoji":"🍸️","text":"🍸︎","type":1,"order":2917,"group":4,"subgroup":47,"version":0.6},{"annotation":"热带水果饮料","name":"TROPICAL DRINK","hexcode":"1F379","shortcodes":["tropical_drink"],"tags":["饮料"],"emoji":"🍹","text":"","type":1,"order":2918,"group":4,"subgroup":47,"version":0.6},{"annotation":"啤酒","name":"BEER MUG","hexcode":"1F37A","shortcodes":["beer"],"tags":["杯","酒"],"emoji":"🍺","text":"","type":1,"order":2919,"group":4,"subgroup":47,"version":0.6},{"annotation":"干杯","name":"CLINKING BEER MUGS","hexcode":"1F37B","shortcodes":["beers"],"tags":["啤酒","碰杯","酒"],"emoji":"🍻","text":"","type":1,"order":2920,"group":4,"subgroup":47,"version":0.6},{"annotation":"碰杯","name":"CLINKING GLASSES","hexcode":"1F942","shortcodes":["champagne_glass"],"tags":["喝","庆祝","杯"],"emoji":"🥂","text":"","type":1,"order":2921,"group":4,"subgroup":47,"version":3},{"annotation":"平底杯","name":"TUMBLER GLASS","hexcode":"1F943","shortcodes":["tumbler_glass"],"tags":["威士忌","杯","酒"],"emoji":"🥃","text":"","type":1,"order":2922,"group":4,"subgroup":47,"version":3},{"annotation":"带吸管杯","name":"CUP WITH STRAW","hexcode":"1F964","shortcodes":["cup_straw"],"tags":["果汁","苏打"],"emoji":"🥤","text":"","type":1,"order":2923,"group":4,"subgroup":47,"version":5},{"annotation":"珍珠奶茶","name":"BUBBLE TEA","hexcode":"1F9CB","shortcodes":["bubble_tea","boba_drink"],"tags":["泡泡","牛奶","珍珠","茶"],"emoji":"🧋","text":"","type":1,"order":2924,"group":4,"subgroup":47,"version":13},{"annotation":"饮料盒","name":"BEVERAGE BOX","hexcode":"1F9C3","shortcodes":["beverage_box","juice_box"],"tags":["吸管","果汁盒","盒装"],"emoji":"🧃","text":"","type":1,"order":2925,"group":4,"subgroup":47,"version":12},{"annotation":"马黛茶","name":"MATE DRINK","hexcode":"1F9C9","shortcodes":["mate","yerba_mate"],"tags":["茶","饮料"],"emoji":"🧉","text":"","type":1,"order":2926,"group":4,"subgroup":47,"version":12},{"annotation":"冰块","name":"ICE CUBE","hexcode":"1F9CA","shortcodes":["ice"],"tags":["冰山","冷却","冷饮"],"emoji":"🧊","text":"","type":1,"order":2927,"group":4,"subgroup":47,"version":12},{"annotation":"筷子","name":"CHOPSTICKS","hexcode":"1F962","shortcodes":["chopsticks"],"tags":["箸"],"emoji":"🥢","text":"","type":1,"order":2928,"group":4,"subgroup":48,"version":5},{"annotation":"餐具","name":"FORK AND KNIFE WITH PLATE","hexcode":"1F37D","shortcodes":["fork_knife_plate"],"tags":["刀","叉","盘"],"emoji":"🍽️","text":"🍽︎","type":0,"order":2930,"group":4,"subgroup":48,"version":0.7},{"annotation":"刀叉","name":"FORK AND KNIFE","hexcode":"1F374","shortcodes":["utensils"],"tags":["刀","叉","餐具"],"emoji":"🍴","text":"","type":1,"order":2931,"group":4,"subgroup":48,"version":0.6},{"annotation":"匙","name":"SPOON","hexcode":"1F944","shortcodes":["spoon"],"tags":["匙子","汤匙","调羹","餐具"],"emoji":"🥄","text":"","type":1,"order":2932,"group":4,"subgroup":48,"version":3},{"annotation":"菜刀","name":"HOCHO","hexcode":"1F52A","shortcodes":["knife"],"tags":["刀","武器","烹饪"],"emoji":"🔪","text":"","type":1,"order":2933,"group":4,"subgroup":48,"version":0.6},{"annotation":"双耳瓶","name":"AMPHORA","hexcode":"1F3FA","shortcodes":["amphora"],"tags":["壶","罐"],"emoji":"🏺","text":"","type":1,"order":2934,"group":4,"subgroup":48,"version":1},{"annotation":"地球上的欧洲非洲","name":"EARTH GLOBE EUROPE-AFRICA","hexcode":"1F30D","shortcodes":["earth_africa"],"tags":["世界","地球","欧洲","非洲"],"emoji":"🌍️","text":"🌍︎","type":1,"order":2935,"group":5,"subgroup":49,"version":0.7},{"annotation":"地球上的美洲","name":"EARTH GLOBE AMERICAS","hexcode":"1F30E","shortcodes":["earth_americas"],"tags":["世界","地球","美洲"],"emoji":"🌎️","text":"🌎︎","type":1,"order":2936,"group":5,"subgroup":49,"version":0.7},{"annotation":"地球上的亚洲澳洲","name":"EARTH GLOBE ASIA-AUSTRALIA","hexcode":"1F30F","shortcodes":["earth_asia"],"tags":["世界","亚洲","地球","澳洲"],"emoji":"🌏️","text":"🌏︎","type":1,"order":2937,"group":5,"subgroup":49,"version":0.6},{"annotation":"带经纬线的地球","name":"GLOBE WITH MERIDIANS","hexcode":"1F310","shortcodes":["globe"],"tags":["世界","地球","子午线","经纬"],"emoji":"🌐","text":"","type":1,"order":2938,"group":5,"subgroup":49,"version":1},{"annotation":"世界地图","name":"WORLD MAP","hexcode":"1F5FA","shortcodes":["map"],"tags":["世界","地图"],"emoji":"🗺️","text":"🗺︎","type":0,"order":2940,"group":5,"subgroup":49,"version":0.7},{"annotation":"日本地图","name":"SILHOUETTE OF JAPAN","hexcode":"1F5FE","shortcodes":["japan"],"tags":["地图","日本"],"emoji":"🗾","text":"","type":1,"order":2941,"group":5,"subgroup":49,"version":0.6},{"annotation":"指南针","name":"COMPASS","hexcode":"1F9ED","shortcodes":["compass"],"tags":["定向","导航","磁性"],"emoji":"🧭","text":"","type":1,"order":2942,"group":5,"subgroup":49,"version":11},{"annotation":"雪山","name":"SNOW CAPPED MOUNTAIN","hexcode":"1F3D4","shortcodes":["snowy_mountain"],"tags":["冷","山","雪"],"emoji":"🏔️","text":"🏔︎","type":0,"order":2944,"group":5,"subgroup":50,"version":0.7},{"annotation":"山","name":"MOUNTAIN","hexcode":"26F0","shortcodes":["mountain"],"tags":["山"],"emoji":"⛰️","text":"⛰︎","type":0,"order":2946,"group":5,"subgroup":50,"version":0.7},{"annotation":"火山","name":"VOLCANO","hexcode":"1F30B","shortcodes":["volcano"],"tags":["喷发","山","爆发"],"emoji":"🌋","text":"","type":1,"order":2947,"group":5,"subgroup":50,"version":0.6},{"annotation":"富士山","name":"MOUNT FUJI","hexcode":"1F5FB","shortcodes":["mount_fuji"],"tags":["山"],"emoji":"🗻","text":"","type":1,"order":2948,"group":5,"subgroup":50,"version":0.6},{"annotation":"露营","name":"CAMPING","hexcode":"1F3D5","shortcodes":["camping"],"tags":["帐篷"],"emoji":"🏕️","text":"🏕︎","type":0,"order":2950,"group":5,"subgroup":50,"version":0.7},{"annotation":"沙滩伞","name":"BEACH WITH UMBRELLA","hexcode":"1F3D6","shortcodes":["beach"],"tags":["伞","沙滩"],"emoji":"🏖️","text":"🏖︎","type":0,"order":2952,"group":5,"subgroup":50,"version":0.7},{"annotation":"沙漠","name":"DESERT","hexcode":"1F3DC","shortcodes":["desert"],"tags":["荒漠"],"emoji":"🏜️","text":"🏜︎","type":0,"order":2954,"group":5,"subgroup":50,"version":0.7},{"annotation":"无人荒岛","name":"DESERT ISLAND","hexcode":"1F3DD","shortcodes":["island"],"tags":["荒岛"],"emoji":"🏝️","text":"🏝︎","type":0,"order":2956,"group":5,"subgroup":50,"version":0.7},{"annotation":"国家公园","name":"NATIONAL PARK","hexcode":"1F3DE","shortcodes":["park"],"tags":["公园","自然","风景"],"emoji":"🏞️","text":"🏞︎","type":0,"order":2958,"group":5,"subgroup":50,"version":0.7},{"annotation":"体育馆","name":"STADIUM","hexcode":"1F3DF","shortcodes":["stadium"],"tags":["体育馆"],"emoji":"🏟️","text":"🏟︎","type":0,"order":2960,"group":5,"subgroup":51,"version":0.7},{"annotation":"古典建筑","name":"CLASSICAL BUILDING","hexcode":"1F3DB","shortcodes":["classical_building"],"tags":["古典","古建筑"],"emoji":"🏛️","text":"🏛︎","type":0,"order":2962,"group":5,"subgroup":51,"version":0.7},{"annotation":"施工","name":"BUILDING CONSTRUCTION","hexcode":"1F3D7","shortcodes":["construction_site"],"tags":["施工"],"emoji":"🏗️","text":"🏗︎","type":0,"order":2964,"group":5,"subgroup":51,"version":0.7},{"annotation":"砖","name":"BRICK","hexcode":"1F9F1","shortcodes":["brick"],"tags":["墙","砂浆","黏土"],"emoji":"🧱","text":"","type":1,"order":2965,"group":5,"subgroup":51,"version":11},{"annotation":"岩石","name":"ROCK","hexcode":"1FAA8","shortcodes":["rock"],"tags":["固体","巨石","石头"],"emoji":"🪨","text":"","type":1,"order":2966,"group":5,"subgroup":51,"version":13},{"annotation":"木头","name":"WOOD","hexcode":"1FAB5","shortcodes":["wood"],"tags":["原木","木材"],"emoji":"🪵","text":"","type":1,"order":2967,"group":5,"subgroup":51,"version":13},{"annotation":"小屋","name":"HUT","hexcode":"1F6D6","shortcodes":["hut"],"tags":["圆屋","蒙古包"],"emoji":"🛖","text":"","type":1,"order":2968,"group":5,"subgroup":51,"version":13},{"annotation":"房屋建筑","name":"HOUSE BUILDINGS","hexcode":"1F3D8","shortcodes":["homes"],"tags":["住宅","房"],"emoji":"🏘️","text":"🏘︎","type":0,"order":2970,"group":5,"subgroup":51,"version":0.7},{"annotation":"废墟","name":"DERELICT HOUSE BUILDING","hexcode":"1F3DA","shortcodes":["house_abandoned"],"tags":["荒宅","荒废","鬼屋"],"emoji":"🏚️","text":"🏚︎","type":0,"order":2972,"group":5,"subgroup":51,"version":0.7},{"annotation":"房子","name":"HOUSE BUILDING","hexcode":"1F3E0","shortcodes":["house"],"tags":["家"],"emoji":"🏠️","text":"🏠︎","type":1,"order":2973,"group":5,"subgroup":51,"version":0.6},{"annotation":"别墅","name":"HOUSE WITH GARDEN","hexcode":"1F3E1","shortcodes":["house_garden"],"tags":["家","房子","花园"],"emoji":"🏡","text":"","type":1,"order":2974,"group":5,"subgroup":51,"version":0.6},{"annotation":"办公楼","name":"OFFICE BUILDING","hexcode":"1F3E2","shortcodes":["office"],"tags":["写字楼"],"emoji":"🏢","text":"","type":1,"order":2975,"group":5,"subgroup":51,"version":0.6},{"annotation":"日本邮局","name":"JAPANESE POST OFFICE","hexcode":"1F3E3","shortcodes":["ja_post_office"],"tags":["日本","邮局"],"emoji":"🏣","text":"","type":1,"order":2976,"group":5,"subgroup":51,"version":0.6},{"annotation":"邮局","name":"EUROPEAN POST OFFICE","hexcode":"1F3E4","shortcodes":["post_office"],"tags":["欧洲"],"emoji":"🏤","text":"","type":1,"order":2977,"group":5,"subgroup":51,"version":1},{"annotation":"医院","name":"HOSPITAL","hexcode":"1F3E5","shortcodes":["hospital"],"tags":["医生","看病"],"emoji":"🏥","text":"","type":1,"order":2978,"group":5,"subgroup":51,"version":0.6},{"annotation":"银行","name":"BANK","hexcode":"1F3E6","shortcodes":["bank"],"tags":["银行"],"emoji":"🏦","text":"","type":1,"order":2979,"group":5,"subgroup":51,"version":0.6},{"annotation":"酒店","name":"HOTEL","hexcode":"1F3E8","shortcodes":["hotel"],"tags":["旅馆"],"emoji":"🏨","text":"","type":1,"order":2980,"group":5,"subgroup":51,"version":0.6},{"annotation":"情人酒店","name":"LOVE HOTEL","hexcode":"1F3E9","shortcodes":["love_hotel"],"tags":["情人旅馆","情侣酒店"],"emoji":"🏩","text":"","type":1,"order":2981,"group":5,"subgroup":51,"version":0.6},{"annotation":"便利店","name":"CONVENIENCE STORE","hexcode":"1F3EA","shortcodes":["convenience_store"],"tags":["商店"],"emoji":"🏪","text":"","type":1,"order":2982,"group":5,"subgroup":51,"version":0.6},{"annotation":"学校","name":"SCHOOL","hexcode":"1F3EB","shortcodes":["school"],"tags":["教学楼"],"emoji":"🏫","text":"","type":1,"order":2983,"group":5,"subgroup":51,"version":0.6},{"annotation":"商场","name":"DEPARTMENT STORE","hexcode":"1F3EC","shortcodes":["department_store"],"tags":["百货商店"],"emoji":"🏬","text":"","type":1,"order":2984,"group":5,"subgroup":51,"version":0.6},{"annotation":"工厂","name":"FACTORY","hexcode":"1F3ED","shortcodes":["factory"],"tags":["工厂"],"emoji":"🏭️","text":"🏭︎","type":1,"order":2985,"group":5,"subgroup":51,"version":0.6},{"annotation":"日本城堡","name":"JAPANESE CASTLE","hexcode":"1F3EF","shortcodes":["japanese_castle"],"tags":["城堡","日本"],"emoji":"🏯","text":"","type":1,"order":2986,"group":5,"subgroup":51,"version":0.6},{"annotation":"欧洲城堡","name":"EUROPEAN CASTLE","hexcode":"1F3F0","shortcodes":["castle","european_castle"],"tags":["城堡","欧洲"],"emoji":"🏰","text":"","type":1,"order":2987,"group":5,"subgroup":51,"version":0.6},{"annotation":"婚礼","name":"WEDDING","hexcode":"1F492","shortcodes":["wedding"],"tags":["教堂","浪漫","结婚"],"emoji":"💒","text":"","type":1,"order":2988,"group":5,"subgroup":51,"version":0.6},{"annotation":"东京塔","name":"TOKYO TOWER","hexcode":"1F5FC","shortcodes":["tokyo_tower"],"tags":["东京","塔"],"emoji":"🗼","text":"","type":1,"order":2989,"group":5,"subgroup":51,"version":0.6},{"annotation":"自由女神像","name":"STATUE OF LIBERTY","hexcode":"1F5FD","shortcodes":["statue_of_liberty"],"tags":["自由","雕塑"],"emoji":"🗽","text":"","type":1,"order":2990,"group":5,"subgroup":51,"version":0.6},{"annotation":"教堂","name":"CHURCH","hexcode":"26EA","shortcodes":["church"],"tags":["基督","宗教"],"emoji":"⛪️","text":"⛪︎","type":1,"order":2991,"group":5,"subgroup":52,"version":0.6},{"annotation":"清真寺","name":"MOSQUE","hexcode":"1F54C","shortcodes":["mosque"],"tags":["伊斯兰","宗教","穆斯林"],"emoji":"🕌","text":"","type":1,"order":2992,"group":5,"subgroup":52,"version":1},{"annotation":"印度寺庙","name":"HINDU TEMPLE","hexcode":"1F6D5","shortcodes":["hindu_temple"],"tags":["佛寺","佛教","寺庙","寺院","庙宇"],"emoji":"🛕","text":"","type":1,"order":2993,"group":5,"subgroup":52,"version":12},{"annotation":"犹太教堂","name":"SYNAGOGUE","hexcode":"1F54D","shortcodes":["synagogue"],"tags":["会堂","宗教","犹太"],"emoji":"🕍","text":"","type":1,"order":2994,"group":5,"subgroup":52,"version":1},{"annotation":"神社","name":"SHINTO SHRINE","hexcode":"26E9","shortcodes":["shinto_shrine"],"tags":["宗教","日本","神道教"],"emoji":"⛩️","text":"⛩︎","type":0,"order":2996,"group":5,"subgroup":52,"version":0.7},{"annotation":"克尔白","name":"KAABA","hexcode":"1F54B","shortcodes":["kaaba"],"tags":["伊斯兰","天房","宗教","穆斯林"],"emoji":"🕋","text":"","type":1,"order":2997,"group":5,"subgroup":52,"version":1},{"annotation":"喷泉","name":"FOUNTAIN","hexcode":"26F2","shortcodes":["fountain"],"tags":["喷泉"],"emoji":"⛲️","text":"⛲︎","type":1,"order":2998,"group":5,"subgroup":53,"version":0.6},{"annotation":"帐篷","name":"TENT","hexcode":"26FA","shortcodes":["tent"],"tags":["露营"],"emoji":"⛺️","text":"⛺︎","type":1,"order":2999,"group":5,"subgroup":53,"version":0.6},{"annotation":"有雾","name":"FOGGY","hexcode":"1F301","shortcodes":["foggy"],"tags":["雾","霾"],"emoji":"🌁","text":"","type":1,"order":3000,"group":5,"subgroup":53,"version":0.6},{"annotation":"夜晚","name":"NIGHT WITH STARS","hexcode":"1F303","shortcodes":["night_stars"],"tags":["星空","晚上"],"emoji":"🌃","text":"","type":1,"order":3001,"group":5,"subgroup":53,"version":0.6},{"annotation":"城市风光","name":"CITYSCAPE","hexcode":"1F3D9","shortcodes":["cityscape"],"tags":["都市","都市景观","高楼大厦"],"emoji":"🏙️","text":"🏙︎","type":0,"order":3003,"group":5,"subgroup":53,"version":0.7},{"annotation":"山顶日出","name":"SUNRISE OVER MOUNTAINS","hexcode":"1F304","shortcodes":["sunrise_over_mountains"],"tags":["太阳","山","日出","清晨"],"emoji":"🌄","text":"","type":1,"order":3004,"group":5,"subgroup":53,"version":0.6},{"annotation":"日出","name":"SUNRISE","hexcode":"1F305","shortcodes":["sunrise"],"tags":["太阳","清晨"],"emoji":"🌅","text":"","type":1,"order":3005,"group":5,"subgroup":53,"version":0.6},{"annotation":"城市黄昏","name":"CITYSCAPE AT DUSK","hexcode":"1F306","shortcodes":["dusk"],"tags":["夜晚","日落","都市","黄昏"],"emoji":"🌆","text":"","type":1,"order":3006,"group":5,"subgroup":53,"version":0.6},{"annotation":"日落","name":"SUNSET OVER BUILDINGS","hexcode":"1F307","shortcodes":["sunset"],"tags":["夕阳"],"emoji":"🌇","text":"","type":1,"order":3007,"group":5,"subgroup":53,"version":0.6},{"annotation":"夜幕下的桥","name":"BRIDGE AT NIGHT","hexcode":"1F309","shortcodes":["bridge_at_night"],"tags":["晚上","桥"],"emoji":"🌉","text":"","type":1,"order":3008,"group":5,"subgroup":53,"version":0.6},{"annotation":"温泉","name":"HOT SPRINGS","hexcode":"2668","shortcodes":["hotsprings"],"tags":["水","泉","热气腾腾"],"emoji":"♨️","text":"♨︎","type":0,"order":3010,"group":5,"subgroup":53,"version":0.6},{"annotation":"旋转木马","name":"CAROUSEL HORSE","hexcode":"1F3A0","shortcodes":["carousel_horse"],"tags":["木马","游乐园"],"emoji":"🎠","text":"","type":1,"order":3011,"group":5,"subgroup":53,"version":0.6},{"annotation":"摩天轮","name":"FERRIS WHEEL","hexcode":"1F3A1","shortcodes":["ferris_wheel"],"tags":["游乐园"],"emoji":"🎡","text":"","type":1,"order":3012,"group":5,"subgroup":53,"version":0.6},{"annotation":"过山车","name":"ROLLER COASTER","hexcode":"1F3A2","shortcodes":["roller_coaster"],"tags":["游乐园"],"emoji":"🎢","text":"","type":1,"order":3013,"group":5,"subgroup":53,"version":0.6},{"annotation":"理发店","name":"BARBER POLE","hexcode":"1F488","shortcodes":["barber"],"tags":["旋转","柱","理发"],"emoji":"💈","text":"","type":1,"order":3014,"group":5,"subgroup":53,"version":0.6},{"annotation":"马戏团帐篷","name":"CIRCUS TENT","hexcode":"1F3AA","shortcodes":["circus_tent"],"tags":["帐篷","马戏团"],"emoji":"🎪","text":"","type":1,"order":3015,"group":5,"subgroup":53,"version":0.6},{"annotation":"蒸汽火车","name":"STEAM LOCOMOTIVE","hexcode":"1F682","shortcodes":["steam_locomotive"],"tags":["火车","蒸汽"],"emoji":"🚂","text":"","type":1,"order":3016,"group":5,"subgroup":54,"version":1},{"annotation":"轨道车","name":"RAILWAY CAR","hexcode":"1F683","shortcodes":["railway_car"],"tags":["电车"],"emoji":"🚃","text":"","type":1,"order":3017,"group":5,"subgroup":54,"version":0.6},{"annotation":"高速列车","name":"HIGH-SPEED TRAIN","hexcode":"1F684","shortcodes":["bullettrain_side"],"tags":["动车","新干线","火车","高铁"],"emoji":"🚄","text":"","type":1,"order":3018,"group":5,"subgroup":54,"version":0.6},{"annotation":"子弹头高速列车","name":"HIGH-SPEED TRAIN WITH BULLET NOSE","hexcode":"1F685","shortcodes":["bullettrain"],"tags":["动车","新干线","火车","高速","高铁"],"emoji":"🚅","text":"","type":1,"order":3019,"group":5,"subgroup":54,"version":0.6},{"annotation":"火车","name":"TRAIN","hexcode":"1F686","shortcodes":["train"],"tags":["铁路"],"emoji":"🚆","text":"","type":1,"order":3020,"group":5,"subgroup":54,"version":1},{"annotation":"地铁","name":"METRO","hexcode":"1F687","shortcodes":["metro"],"tags":["地铁"],"emoji":"🚇️","text":"🚇︎","type":1,"order":3021,"group":5,"subgroup":54,"version":0.6},{"annotation":"轻轨","name":"LIGHT RAIL","hexcode":"1F688","shortcodes":["light_rail"],"tags":["火车"],"emoji":"🚈","text":"","type":1,"order":3022,"group":5,"subgroup":54,"version":1},{"annotation":"车站","name":"STATION","hexcode":"1F689","shortcodes":["station"],"tags":["火车","铁路"],"emoji":"🚉","text":"","type":1,"order":3023,"group":5,"subgroup":54,"version":0.6},{"annotation":"路面电车","name":"TRAM","hexcode":"1F68A","shortcodes":["tram"],"tags":["电车"],"emoji":"🚊","text":"","type":1,"order":3024,"group":5,"subgroup":54,"version":1},{"annotation":"单轨","name":"MONORAIL","hexcode":"1F69D","shortcodes":["monorail"],"tags":["火车"],"emoji":"🚝","text":"","type":1,"order":3025,"group":5,"subgroup":54,"version":1},{"annotation":"山区铁路","name":"MOUNTAIN RAILWAY","hexcode":"1F69E","shortcodes":["mountain_railway"],"tags":["山区","火车","铁路"],"emoji":"🚞","text":"","type":1,"order":3026,"group":5,"subgroup":54,"version":1},{"annotation":"有轨电车","name":"TRAM CAR","hexcode":"1F68B","shortcodes":["tram_car"],"tags":["有轨电车"],"emoji":"🚋","text":"","type":1,"order":3027,"group":5,"subgroup":54,"version":1},{"annotation":"公交车","name":"BUS","hexcode":"1F68C","shortcodes":["bus"],"tags":["公共汽车","大巴"],"emoji":"🚌","text":"","type":1,"order":3028,"group":5,"subgroup":54,"version":0.6},{"annotation":"迎面驶来的公交车","name":"ONCOMING BUS","hexcode":"1F68D","shortcodes":["oncoming_bus"],"tags":["公共汽车","大巴","迎面驶来"],"emoji":"🚍️","text":"🚍︎","type":1,"order":3029,"group":5,"subgroup":54,"version":0.7},{"annotation":"无轨电车","name":"TROLLEYBUS","hexcode":"1F68E","shortcodes":["trolleybus"],"tags":["电车"],"emoji":"🚎","text":"","type":1,"order":3030,"group":5,"subgroup":54,"version":1},{"annotation":"小巴","name":"MINIBUS","hexcode":"1F690","shortcodes":["minibus"],"tags":["公共汽车"],"emoji":"🚐","text":"","type":1,"order":3031,"group":5,"subgroup":54,"version":1},{"annotation":"救护车","name":"AMBULANCE","hexcode":"1F691","shortcodes":["ambulance"],"tags":["急救"],"emoji":"🚑️","text":"🚑︎","type":1,"order":3032,"group":5,"subgroup":54,"version":0.6},{"annotation":"消防车","name":"FIRE ENGINE","hexcode":"1F692","shortcodes":["fire_engine"],"tags":["救火车"],"emoji":"🚒","text":"","type":1,"order":3033,"group":5,"subgroup":54,"version":0.6},{"annotation":"警车","name":"POLICE CAR","hexcode":"1F693","shortcodes":["police_car"],"tags":["巡逻","警察"],"emoji":"🚓","text":"","type":1,"order":3034,"group":5,"subgroup":54,"version":0.6},{"annotation":"迎面驶来的警车","name":"ONCOMING POLICE CAR","hexcode":"1F694","shortcodes":["oncoming_police_car"],"tags":["警察","警车"],"emoji":"🚔️","text":"🚔︎","type":1,"order":3035,"group":5,"subgroup":54,"version":0.7},{"annotation":"出租车","name":"TAXI","hexcode":"1F695","shortcodes":["taxi"],"tags":["的士"],"emoji":"🚕","text":"","type":1,"order":3036,"group":5,"subgroup":54,"version":0.6},{"annotation":"迎面驶来的出租车","name":"ONCOMING TAXI","hexcode":"1F696","shortcodes":["oncoming_taxi"],"tags":["出租车","的士"],"emoji":"🚖","text":"","type":1,"order":3037,"group":5,"subgroup":54,"version":1},{"annotation":"汽车","name":"AUTOMOBILE","hexcode":"1F697","shortcodes":["red_car"],"tags":["轿车"],"emoji":"🚗","text":"","type":1,"order":3038,"group":5,"subgroup":54,"version":0.6},{"annotation":"迎面驶来的汽车","name":"ONCOMING AUTOMOBILE","hexcode":"1F698","shortcodes":["oncoming_automobile"],"tags":["轿车"],"emoji":"🚘️","text":"🚘︎","type":1,"order":3039,"group":5,"subgroup":54,"version":0.7},{"annotation":"运动型多用途车","name":"RECREATIONAL VEHICLE","hexcode":"1F699","shortcodes":["blue_car"],"tags":["suv","休闲车"],"emoji":"🚙","text":"","type":1,"order":3040,"group":5,"subgroup":54,"version":0.6},{"annotation":"敞蓬小型载货卡车","name":"PICKUP TRUCK","hexcode":"1F6FB","shortcodes":["pickup_truck"],"tags":["卡车","载货"],"emoji":"🛻","text":"","type":1,"order":3041,"group":5,"subgroup":54,"version":13},{"annotation":"货车","name":"DELIVERY TRUCK","hexcode":"1F69A","shortcodes":["truck"],"tags":["卡车"],"emoji":"🚚","text":"","type":1,"order":3042,"group":5,"subgroup":54,"version":0.6},{"annotation":"铰接式货车","name":"ARTICULATED LORRY","hexcode":"1F69B","shortcodes":["lorry"],"tags":["卡车","拖车"],"emoji":"🚛","text":"","type":1,"order":3043,"group":5,"subgroup":54,"version":1},{"annotation":"拖拉机","name":"TRACTOR","hexcode":"1F69C","shortcodes":["tractor"],"tags":["拖拉机"],"emoji":"🚜","text":"","type":1,"order":3044,"group":5,"subgroup":54,"version":1},{"annotation":"赛车","name":"RACING CAR","hexcode":"1F3CE","shortcodes":["race_car"],"tags":["跑车"],"emoji":"🏎️","text":"🏎︎","type":0,"order":3046,"group":5,"subgroup":54,"version":0.7},{"annotation":"摩托车","name":"RACING MOTORCYCLE","hexcode":"1F3CD","shortcodes":["motorcycle"],"tags":["摩托"],"emoji":"🏍️","text":"🏍︎","type":0,"order":3048,"group":5,"subgroup":54,"version":0.7},{"annotation":"小型摩托车","name":"MOTOR SCOOTER","hexcode":"1F6F5","shortcodes":["motor_scooter"],"tags":["小型摩托车"],"emoji":"🛵","text":"","type":1,"order":3049,"group":5,"subgroup":54,"version":3},{"annotation":"手动轮椅","name":"MANUAL WHEELCHAIR","hexcode":"1F9BD","shortcodes":["wheelchair"],"tags":["无障碍","轮椅"],"emoji":"🦽","text":"","type":1,"order":3050,"group":5,"subgroup":54,"version":12},{"annotation":"电动轮椅","name":"MOTORIZED WHEELCHAIR","hexcode":"1F9BC","shortcodes":["motor_wheelchair"],"tags":["无障碍","轮椅"],"emoji":"🦼","text":"","type":1,"order":3051,"group":5,"subgroup":54,"version":12},{"annotation":"三轮摩托车","name":"AUTO RICKSHAW","hexcode":"1F6FA","shortcodes":["auto_rickshaw"],"tags":["三脚鸡","三蹦子","嘟嘟车","自动人力车"],"emoji":"🛺","text":"","type":1,"order":3052,"group":5,"subgroup":54,"version":12},{"annotation":"自行车","name":"BICYCLE","hexcode":"1F6B2","shortcodes":["bike"],"tags":["单车","脚踏车"],"emoji":"🚲️","text":"🚲︎","type":1,"order":3053,"group":5,"subgroup":54,"version":0.6},{"annotation":"滑板车","name":"SCOOTER","hexcode":"1F6F4","shortcodes":["scooter"],"tags":["滑板车"],"emoji":"🛴","text":"","type":1,"order":3054,"group":5,"subgroup":54,"version":3},{"annotation":"滑板","name":"SKATEBOARD","hexcode":"1F6F9","shortcodes":["skateboard"],"tags":["板"],"emoji":"🛹","text":"","type":1,"order":3055,"group":5,"subgroup":54,"version":11},{"annotation":"四轮滑冰鞋","name":"ROLLER SKATE","hexcode":"1F6FC","shortcodes":["roller_skate"],"tags":["滑冰","轮式"],"emoji":"🛼","text":"","type":1,"order":3056,"group":5,"subgroup":54,"version":13},{"annotation":"公交车站","name":"BUS STOP","hexcode":"1F68F","shortcodes":["bus_stop"],"tags":["公交站","公共汽车站"],"emoji":"🚏","text":"","type":1,"order":3057,"group":5,"subgroup":54,"version":0.6},{"annotation":"高速公路","name":"MOTORWAY","hexcode":"1F6E3","shortcodes":["motorway"],"tags":["公路"],"emoji":"🛣️","text":"🛣︎","type":0,"order":3059,"group":5,"subgroup":54,"version":0.7},{"annotation":"铁轨","name":"RAILWAY TRACK","hexcode":"1F6E4","shortcodes":["railway_track"],"tags":["火车","铁路"],"emoji":"🛤️","text":"🛤︎","type":0,"order":3061,"group":5,"subgroup":54,"version":0.7},{"annotation":"石油桶","name":"OIL DRUM","hexcode":"1F6E2","shortcodes":["oil_drum"],"tags":["桶"],"emoji":"🛢️","text":"🛢︎","type":0,"order":3063,"group":5,"subgroup":54,"version":0.7},{"annotation":"油泵","name":"FUEL PUMP","hexcode":"26FD","shortcodes":["fuel_pump"],"tags":["加油站","柴油","燃油"],"emoji":"⛽️","text":"⛽︎","type":1,"order":3064,"group":5,"subgroup":54,"version":0.6},{"annotation":"警车灯","name":"POLICE CARS REVOLVING LIGHT","hexcode":"1F6A8","shortcodes":["rotating_light","police_light"],"tags":["灯","警报","警灯","警示"],"emoji":"🚨","text":"","type":1,"order":3065,"group":5,"subgroup":54,"version":0.6},{"annotation":"横向的红绿灯","name":"HORIZONTAL TRAFFIC LIGHT","hexcode":"1F6A5","shortcodes":["traffic_light"],"tags":["交通灯","信号灯","红绿灯"],"emoji":"🚥","text":"","type":1,"order":3066,"group":5,"subgroup":54,"version":0.6},{"annotation":"纵向的红绿灯","name":"VERTICAL TRAFFIC LIGHT","hexcode":"1F6A6","shortcodes":["vertical_traffic_light"],"tags":["交通灯","信号灯","红绿灯"],"emoji":"🚦","text":"","type":1,"order":3067,"group":5,"subgroup":54,"version":1},{"annotation":"停止标志","name":"OCTAGONAL SIGN","hexcode":"1F6D1","shortcodes":["stop_sign","octagonal_sign"],"tags":["八边形","标志"],"emoji":"🛑","text":"","type":1,"order":3068,"group":5,"subgroup":54,"version":3},{"annotation":"路障","name":"CONSTRUCTION SIGN","hexcode":"1F6A7","shortcodes":["construction"],"tags":["施工"],"emoji":"🚧","text":"","type":1,"order":3069,"group":5,"subgroup":54,"version":0.6},{"annotation":"锚","name":"ANCHOR","hexcode":"2693","shortcodes":["anchor"],"tags":["停泊","船"],"emoji":"⚓️","text":"⚓︎","type":1,"order":3070,"group":5,"subgroup":55,"version":0.6},{"annotation":"帆船","name":"SAILBOAT","hexcode":"26F5","shortcodes":["sailboat"],"tags":["船"],"emoji":"⛵️","text":"⛵︎","type":1,"order":3071,"group":5,"subgroup":55,"version":0.6},{"annotation":"独木舟","name":"CANOE","hexcode":"1F6F6","shortcodes":["canoe"],"tags":["独木舟"],"emoji":"🛶","text":"","type":1,"order":3072,"group":5,"subgroup":55,"version":3},{"annotation":"快艇","name":"SPEEDBOAT","hexcode":"1F6A4","shortcodes":["speedboat"],"tags":["船"],"emoji":"🚤","text":"","type":1,"order":3073,"group":5,"subgroup":55,"version":0.6},{"annotation":"客轮","name":"PASSENGER SHIP","hexcode":"1F6F3","shortcodes":["cruise_ship"],"tags":["客船"],"emoji":"🛳️","text":"🛳︎","type":0,"order":3075,"group":5,"subgroup":55,"version":0.7},{"annotation":"渡轮","name":"FERRY","hexcode":"26F4","shortcodes":["ferry"],"tags":["渡船","轮船"],"emoji":"⛴️","text":"⛴︎","type":0,"order":3077,"group":5,"subgroup":55,"version":0.7},{"annotation":"摩托艇","name":"MOTOR BOAT","hexcode":"1F6E5","shortcodes":["motorboat"],"tags":["船"],"emoji":"🛥️","text":"🛥︎","type":0,"order":3079,"group":5,"subgroup":55,"version":0.7},{"annotation":"船","name":"SHIP","hexcode":"1F6A2","shortcodes":["ship"],"tags":["船"],"emoji":"🚢","text":"","type":1,"order":3080,"group":5,"subgroup":55,"version":0.6},{"annotation":"飞机","name":"AIRPLANE","hexcode":"2708","shortcodes":["airplane"],"tags":["飞机"],"emoji":"✈️","text":"✈︎","type":0,"order":3082,"group":5,"subgroup":56,"version":0.6},{"annotation":"小型飞机","name":"SMALL AIRPLANE","hexcode":"1F6E9","shortcodes":["small_airplane"],"tags":["飞机"],"emoji":"🛩️","text":"🛩︎","type":0,"order":3084,"group":5,"subgroup":56,"version":0.7},{"annotation":"航班起飞","name":"AIRPLANE DEPARTURE","hexcode":"1F6EB","shortcodes":["airplane_departure"],"tags":["值机","登机","起飞"],"emoji":"🛫","text":"","type":1,"order":3085,"group":5,"subgroup":56,"version":1},{"annotation":"航班降落","name":"AIRPLANE ARRIVING","hexcode":"1F6EC","shortcodes":["airplane_arriving"],"tags":["到达","降落"],"emoji":"🛬","text":"","type":1,"order":3086,"group":5,"subgroup":56,"version":1},{"annotation":"降落伞","name":"PARACHUTE","hexcode":"1FA82","shortcodes":["parachute"],"tags":["帆伞","悬挂滑翔","滑翔","滑翔伞","跳伞"],"emoji":"🪂","text":"","type":1,"order":3087,"group":5,"subgroup":56,"version":12},{"annotation":"座位","name":"SEAT","hexcode":"1F4BA","shortcodes":["seat"],"tags":["椅子"],"emoji":"💺","text":"","type":1,"order":3088,"group":5,"subgroup":56,"version":0.6},{"annotation":"直升机","name":"HELICOPTER","hexcode":"1F681","shortcodes":["helicopter"],"tags":["直升飞机"],"emoji":"🚁","text":"","type":1,"order":3089,"group":5,"subgroup":56,"version":1},{"annotation":"空轨","name":"SUSPENSION RAILWAY","hexcode":"1F69F","shortcodes":["suspension_railway"],"tags":["悬挂","空中轨道列车"],"emoji":"🚟","text":"","type":1,"order":3090,"group":5,"subgroup":56,"version":1},{"annotation":"缆车","name":"MOUNTAIN CABLEWAY","hexcode":"1F6A0","shortcodes":["mountain_cableway"],"tags":["空中","索道"],"emoji":"🚠","text":"","type":1,"order":3091,"group":5,"subgroup":56,"version":1},{"annotation":"索道","name":"AERIAL TRAMWAY","hexcode":"1F6A1","shortcodes":["aerial_tramway"],"tags":["空中","缆车"],"emoji":"🚡","text":"","type":1,"order":3092,"group":5,"subgroup":56,"version":1},{"annotation":"卫星","name":"SATELLITE","hexcode":"1F6F0","shortcodes":["satellite"],"tags":["太空"],"emoji":"🛰️","text":"🛰︎","type":0,"order":3094,"group":5,"subgroup":56,"version":0.7},{"annotation":"火箭","name":"ROCKET","hexcode":"1F680","shortcodes":["rocket"],"tags":["太空"],"emoji":"🚀","text":"","type":1,"order":3095,"group":5,"subgroup":56,"version":0.6},{"annotation":"飞碟","name":"FLYING SAUCER","hexcode":"1F6F8","shortcodes":["flying_saucer"],"tags":["ufo","不明飞行物"],"emoji":"🛸","text":"","type":1,"order":3096,"group":5,"subgroup":56,"version":5},{"annotation":"服务铃","name":"BELLHOP BELL","hexcode":"1F6CE","shortcodes":["bellhop"],"tags":["酒店","铃"],"emoji":"🛎️","text":"🛎︎","type":0,"order":3098,"group":5,"subgroup":57,"version":0.7},{"annotation":"行李箱","name":"LUGGAGE","hexcode":"1F9F3","shortcodes":["luggage"],"tags":["包装","旅行"],"emoji":"🧳","text":"","type":1,"order":3099,"group":5,"subgroup":57,"version":11},{"annotation":"沙漏","name":"HOURGLASS","hexcode":"231B","shortcodes":["hourglass"],"tags":["计时器"],"emoji":"⌛️","text":"⌛︎","type":1,"order":3100,"group":5,"subgroup":58,"version":0.6},{"annotation":"沙正往下流的沙漏","name":"HOURGLASS WITH FLOWING SAND","hexcode":"23F3","shortcodes":["hourglass_flowing"],"tags":["计时器"],"emoji":"⏳️","text":"⏳︎","type":1,"order":3101,"group":5,"subgroup":58,"version":0.6},{"annotation":"手表","name":"WATCH","hexcode":"231A","shortcodes":["watch"],"tags":["表"],"emoji":"⌚️","text":"⌚︎","type":1,"order":3102,"group":5,"subgroup":58,"version":0.6},{"annotation":"闹钟","name":"ALARM CLOCK","hexcode":"23F0","shortcodes":["alarm_clock"],"tags":["钟"],"emoji":"⏰","text":"","type":1,"order":3103,"group":5,"subgroup":58,"version":0.6},{"annotation":"秒表","name":"STOPWATCH","hexcode":"23F1","shortcodes":["stopwatch"],"tags":["码表","计时器"],"emoji":"⏱️","text":"⏱︎","type":0,"order":3105,"group":5,"subgroup":58,"version":1},{"annotation":"定时器","name":"TIMER CLOCK","hexcode":"23F2","shortcodes":["timer"],"tags":["计时器"],"emoji":"⏲️","text":"⏲︎","type":0,"order":3107,"group":5,"subgroup":58,"version":1},{"annotation":"座钟","name":"MANTELPIECE CLOCK","hexcode":"1F570","shortcodes":["clock"],"tags":["台钟","壁炉钟"],"emoji":"🕰️","text":"🕰︎","type":0,"order":3109,"group":5,"subgroup":58,"version":0.7},{"annotation":"十二点","name":"CLOCK FACE TWELVE OCLOCK","hexcode":"1F55B","shortcodes":["clock12"],"tags":["12:00"],"emoji":"🕛️","text":"🕛︎","type":1,"order":3110,"group":5,"subgroup":58,"version":0.6},{"annotation":"十二点半","name":"CLOCK FACE TWELVE-THIRTY","hexcode":"1F567","shortcodes":["clock1230"],"tags":["12:30"],"emoji":"🕧️","text":"🕧︎","type":1,"order":3111,"group":5,"subgroup":58,"version":0.7},{"annotation":"一点","name":"CLOCK FACE ONE OCLOCK","hexcode":"1F550","shortcodes":["clock1"],"tags":["1:00"],"emoji":"🕐️","text":"🕐︎","type":1,"order":3112,"group":5,"subgroup":58,"version":0.6},{"annotation":"一点半","name":"CLOCK FACE ONE-THIRTY","hexcode":"1F55C","shortcodes":["clock130"],"tags":["1:30"],"emoji":"🕜️","text":"🕜︎","type":1,"order":3113,"group":5,"subgroup":58,"version":0.7},{"annotation":"两点","name":"CLOCK FACE TWO OCLOCK","hexcode":"1F551","shortcodes":["clock2"],"tags":["2:00"],"emoji":"🕑️","text":"🕑︎","type":1,"order":3114,"group":5,"subgroup":58,"version":0.6},{"annotation":"两点半","name":"CLOCK FACE TWO-THIRTY","hexcode":"1F55D","shortcodes":["clock230"],"tags":["2:30"],"emoji":"🕝️","text":"🕝︎","type":1,"order":3115,"group":5,"subgroup":58,"version":0.7},{"annotation":"三点","name":"CLOCK FACE THREE OCLOCK","hexcode":"1F552","shortcodes":["clock3"],"tags":["3:00"],"emoji":"🕒️","text":"🕒︎","type":1,"order":3116,"group":5,"subgroup":58,"version":0.6},{"annotation":"三点半","name":"CLOCK FACE THREE-THIRTY","hexcode":"1F55E","shortcodes":["clock330"],"tags":["3:30"],"emoji":"🕞️","text":"🕞︎","type":1,"order":3117,"group":5,"subgroup":58,"version":0.7},{"annotation":"四点","name":"CLOCK FACE FOUR OCLOCK","hexcode":"1F553","shortcodes":["clock4"],"tags":["4:00"],"emoji":"🕓️","text":"🕓︎","type":1,"order":3118,"group":5,"subgroup":58,"version":0.6},{"annotation":"四点半","name":"CLOCK FACE FOUR-THIRTY","hexcode":"1F55F","shortcodes":["clock430"],"tags":["4:30"],"emoji":"🕟️","text":"🕟︎","type":1,"order":3119,"group":5,"subgroup":58,"version":0.7},{"annotation":"五点","name":"CLOCK FACE FIVE OCLOCK","hexcode":"1F554","shortcodes":["clock5"],"tags":["5:00"],"emoji":"🕔️","text":"🕔︎","type":1,"order":3120,"group":5,"subgroup":58,"version":0.6},{"annotation":"五点半","name":"CLOCK FACE FIVE-THIRTY","hexcode":"1F560","shortcodes":["clock530"],"tags":["5:30"],"emoji":"🕠️","text":"🕠︎","type":1,"order":3121,"group":5,"subgroup":58,"version":0.7},{"annotation":"六点","name":"CLOCK FACE SIX OCLOCK","hexcode":"1F555","shortcodes":["clock6"],"tags":["6:00"],"emoji":"🕕️","text":"🕕︎","type":1,"order":3122,"group":5,"subgroup":58,"version":0.6},{"annotation":"六点半","name":"CLOCK FACE SIX-THIRTY","hexcode":"1F561","shortcodes":["clock630"],"tags":["6:30"],"emoji":"🕡️","text":"🕡︎","type":1,"order":3123,"group":5,"subgroup":58,"version":0.7},{"annotation":"七点","name":"CLOCK FACE SEVEN OCLOCK","hexcode":"1F556","shortcodes":["clock7"],"tags":["7:00"],"emoji":"🕖️","text":"🕖︎","type":1,"order":3124,"group":5,"subgroup":58,"version":0.6},{"annotation":"七点半","name":"CLOCK FACE SEVEN-THIRTY","hexcode":"1F562","shortcodes":["clock730"],"tags":["7:30"],"emoji":"🕢️","text":"🕢︎","type":1,"order":3125,"group":5,"subgroup":58,"version":0.7},{"annotation":"八点","name":"CLOCK FACE EIGHT OCLOCK","hexcode":"1F557","shortcodes":["clock8"],"tags":["8:00"],"emoji":"🕗️","text":"🕗︎","type":1,"order":3126,"group":5,"subgroup":58,"version":0.6},{"annotation":"八点半","name":"CLOCK FACE EIGHT-THIRTY","hexcode":"1F563","shortcodes":["clock830"],"tags":["8:30"],"emoji":"🕣️","text":"🕣︎","type":1,"order":3127,"group":5,"subgroup":58,"version":0.7},{"annotation":"九点","name":"CLOCK FACE NINE OCLOCK","hexcode":"1F558","shortcodes":["clock9"],"tags":["9:00"],"emoji":"🕘️","text":"🕘︎","type":1,"order":3128,"group":5,"subgroup":58,"version":0.6},{"annotation":"九点半","name":"CLOCK FACE NINE-THIRTY","hexcode":"1F564","shortcodes":["clock930"],"tags":["9:30"],"emoji":"🕤️","text":"🕤︎","type":1,"order":3129,"group":5,"subgroup":58,"version":0.7},{"annotation":"十点","name":"CLOCK FACE TEN OCLOCK","hexcode":"1F559","shortcodes":["clock10"],"tags":["10:00"],"emoji":"🕙️","text":"🕙︎","type":1,"order":3130,"group":5,"subgroup":58,"version":0.6},{"annotation":"十点半","name":"CLOCK FACE TEN-THIRTY","hexcode":"1F565","shortcodes":["clock1030"],"tags":["10:30"],"emoji":"🕥️","text":"🕥︎","type":1,"order":3131,"group":5,"subgroup":58,"version":0.7},{"annotation":"十一点","name":"CLOCK FACE ELEVEN OCLOCK","hexcode":"1F55A","shortcodes":["clock11"],"tags":["11:00"],"emoji":"🕚️","text":"🕚︎","type":1,"order":3132,"group":5,"subgroup":58,"version":0.6},{"annotation":"十一点半","name":"CLOCK FACE ELEVEN-THIRTY","hexcode":"1F566","shortcodes":["clock1130"],"tags":["11:30"],"emoji":"🕦️","text":"🕦︎","type":1,"order":3133,"group":5,"subgroup":58,"version":0.7},{"annotation":"朔月","name":"NEW MOON SYMBOL","hexcode":"1F311","shortcodes":["new_moon"],"tags":["新月","月亮"],"emoji":"🌑","text":"","type":1,"order":3134,"group":5,"subgroup":59,"version":0.6},{"annotation":"娥眉月","name":"WAXING CRESCENT MOON SYMBOL","hexcode":"1F312","shortcodes":["waxing_crescent_moon"],"tags":["三日月","弯月","月亮","眉月"],"emoji":"🌒","text":"","type":1,"order":3135,"group":5,"subgroup":59,"version":1},{"annotation":"上弦月","name":"FIRST QUARTER MOON SYMBOL","hexcode":"1F313","shortcodes":["first_quarter_moon"],"tags":["月亮"],"emoji":"🌓","text":"","type":1,"order":3136,"group":5,"subgroup":59,"version":0.6},{"annotation":"盈凸月","name":"WAXING GIBBOUS MOON SYMBOL","hexcode":"1F314","shortcodes":["waxing_gibbous_moon"],"tags":["月亮"],"emoji":"🌔","text":"","type":1,"order":3137,"group":5,"subgroup":59,"version":0.6},{"annotation":"满月","name":"FULL MOON SYMBOL","hexcode":"1F315","shortcodes":["full_moon"],"tags":["月亮","望月"],"emoji":"🌕️","text":"🌕︎","type":1,"order":3138,"group":5,"subgroup":59,"version":0.6},{"annotation":"亏凸月","name":"WANING GIBBOUS MOON SYMBOL","hexcode":"1F316","shortcodes":["waning_gibbous_moon"],"tags":["月亮"],"emoji":"🌖","text":"","type":1,"order":3139,"group":5,"subgroup":59,"version":1},{"annotation":"下弦月","name":"LAST QUARTER MOON SYMBOL","hexcode":"1F317","shortcodes":["last_quarter_moon"],"tags":["月亮"],"emoji":"🌗","text":"","type":1,"order":3140,"group":5,"subgroup":59,"version":1},{"annotation":"残月","name":"WANING CRESCENT MOON SYMBOL","hexcode":"1F318","shortcodes":["waning_crescent_moon"],"tags":["亏眉月","弯月","月亮"],"emoji":"🌘","text":"","type":1,"order":3141,"group":5,"subgroup":59,"version":1},{"annotation":"弯月","name":"CRESCENT MOON","hexcode":"1F319","shortcodes":["crescent_moon"],"tags":["娥眉月","月亮"],"emoji":"🌙","text":"","type":1,"order":3142,"group":5,"subgroup":59,"version":0.6},{"annotation":"微笑的朔月","name":"NEW MOON WITH FACE","hexcode":"1F31A","shortcodes":["new_moon_face"],"tags":["月亮","朔月"],"emoji":"🌚","text":"","type":1,"order":3143,"group":5,"subgroup":59,"version":1},{"annotation":"微笑的上弦月","name":"FIRST QUARTER MOON WITH FACE","hexcode":"1F31B","shortcodes":["first_quarter_moon_face"],"tags":["月亮","蛾眉月"],"emoji":"🌛","text":"","type":1,"order":3144,"group":5,"subgroup":59,"version":0.6},{"annotation":"微笑的下弦月","name":"LAST QUARTER MOON WITH FACE","hexcode":"1F31C","shortcodes":["last_quarter_moon_face"],"tags":["月亮","残月"],"emoji":"🌜️","text":"🌜︎","type":1,"order":3145,"group":5,"subgroup":59,"version":0.7},{"annotation":"温度计","name":"THERMOMETER","hexcode":"1F321","shortcodes":["thermometer"],"tags":["天气","气温"],"emoji":"🌡️","text":"🌡︎","type":0,"order":3147,"group":5,"subgroup":59,"version":0.7},{"annotation":"太阳","name":"BLACK SUN WITH RAYS","hexcode":"2600","shortcodes":["sun"],"tags":["晴","晴天"],"emoji":"☀️","text":"☀︎","type":0,"order":3149,"group":5,"subgroup":59,"version":0.6},{"annotation":"微笑的月亮","name":"FULL MOON WITH FACE","hexcode":"1F31D","shortcodes":["full_moon_face"],"tags":["月亮","望月","满月"],"emoji":"🌝","text":"","type":1,"order":3150,"group":5,"subgroup":59,"version":1},{"annotation":"微笑的太阳","name":"SUN WITH FACE","hexcode":"1F31E","shortcodes":["sun_face"],"tags":["太阳"],"emoji":"🌞","text":"","type":1,"order":3151,"group":5,"subgroup":59,"version":1},{"annotation":"有环行星","name":"RINGED PLANET","hexcode":"1FA90","shortcodes":["ringed_planet","saturn"],"tags":["土星"],"emoji":"🪐","text":"","type":1,"order":3152,"group":5,"subgroup":59,"version":12},{"annotation":"星星","name":"WHITE MEDIUM STAR","hexcode":"2B50","shortcodes":["star"],"tags":["五角星"],"emoji":"⭐️","text":"⭐︎","type":1,"order":3153,"group":5,"subgroup":59,"version":0.6},{"annotation":"闪亮的星星","name":"GLOWING STAR","hexcode":"1F31F","shortcodes":["star2","glowing_star"],"tags":["发光","星星"],"emoji":"🌟","text":"","type":1,"order":3154,"group":5,"subgroup":59,"version":0.6},{"annotation":"流星","name":"SHOOTING STAR","hexcode":"1F320","shortcodes":["star3","shooting_star"],"tags":["流星"],"emoji":"🌠","text":"","type":1,"order":3155,"group":5,"subgroup":59,"version":0.6},{"annotation":"银河","name":"MILKY WAY","hexcode":"1F30C","shortcodes":["milky_way"],"tags":["星空"],"emoji":"🌌","text":"","type":1,"order":3156,"group":5,"subgroup":59,"version":0.6},{"annotation":"云","name":"CLOUD","hexcode":"2601","shortcodes":["cloud"],"tags":["阴"],"emoji":"☁️","text":"☁︎","type":0,"order":3158,"group":5,"subgroup":59,"version":0.6},{"annotation":"阴","name":"SUN BEHIND CLOUD","hexcode":"26C5","shortcodes":["partly_sunny"],"tags":["乌云蔽日","多云"],"emoji":"⛅️","text":"⛅︎","type":1,"order":3159,"group":5,"subgroup":59,"version":0.6},{"annotation":"雷阵雨","name":"THUNDER CLOUD AND RAIN","hexcode":"26C8","shortcodes":["storm"],"tags":["阵雨","雨"],"emoji":"⛈️","text":"⛈︎","type":0,"order":3161,"group":5,"subgroup":59,"version":0.7},{"annotation":"晴偶有云","name":"WHITE SUN WITH SMALL CLOUD","hexcode":"1F324","shortcodes":["overcast"],"tags":["云","太阳","少云"],"emoji":"🌤️","text":"🌤︎","type":0,"order":3163,"group":5,"subgroup":59,"version":0.7},{"annotation":"多云","name":"WHITE SUN BEHIND CLOUD","hexcode":"1F325","shortcodes":["cloudy"],"tags":["云","太阳"],"emoji":"🌥️","text":"🌥︎","type":0,"order":3165,"group":5,"subgroup":59,"version":0.7},{"annotation":"晴转雨","name":"WHITE SUN BEHIND CLOUD WITH RAIN","hexcode":"1F326","shortcodes":["sunshower"],"tags":["云","太阳","雨"],"emoji":"🌦️","text":"🌦︎","type":0,"order":3167,"group":5,"subgroup":59,"version":0.7},{"annotation":"下雨","name":"CLOUD WITH RAIN","hexcode":"1F327","shortcodes":["rain"],"tags":["云","雨"],"emoji":"🌧️","text":"🌧︎","type":0,"order":3169,"group":5,"subgroup":59,"version":0.7},{"annotation":"下雪","name":"CLOUD WITH SNOW","hexcode":"1F328","shortcodes":["snow"],"tags":["云","雪"],"emoji":"🌨️","text":"🌨︎","type":0,"order":3171,"group":5,"subgroup":59,"version":0.7},{"annotation":"打雷","name":"CLOUD WITH LIGHTNING","hexcode":"1F329","shortcodes":["lightning"],"tags":["云","闪电","雷"],"emoji":"🌩️","text":"🌩︎","type":0,"order":3173,"group":5,"subgroup":59,"version":0.7},{"annotation":"龙卷风","name":"CLOUD WITH TORNADO","hexcode":"1F32A","shortcodes":["tornado"],"tags":["云","旋风"],"emoji":"🌪️","text":"🌪︎","type":0,"order":3175,"group":5,"subgroup":59,"version":0.7},{"annotation":"雾","name":"FOG","hexcode":"1F32B","shortcodes":["fog"],"tags":["霾"],"emoji":"🌫️","text":"🌫︎","type":0,"order":3177,"group":5,"subgroup":59,"version":0.7},{"annotation":"大风","name":"WIND BLOWING FACE","hexcode":"1F32C","shortcodes":["wind_face"],"tags":["狂风"],"emoji":"🌬️","text":"🌬︎","type":0,"order":3179,"group":5,"subgroup":59,"version":0.7},{"annotation":"台风","name":"CYCLONE","hexcode":"1F300","shortcodes":["cyclone"],"tags":["旋风","飓风"],"emoji":"🌀","text":"","type":1,"order":3180,"group":5,"subgroup":59,"version":0.6},{"annotation":"彩虹","name":"RAINBOW","hexcode":"1F308","shortcodes":["rainbow"],"tags":["彩虹"],"emoji":"🌈","text":"","type":1,"order":3181,"group":5,"subgroup":59,"version":0.6},{"annotation":"收起的伞","name":"CLOSED UMBRELLA","hexcode":"1F302","shortcodes":["closed_umbrella"],"tags":["伞","雨","雨伞"],"emoji":"🌂","text":"","type":1,"order":3182,"group":5,"subgroup":59,"version":0.6},{"annotation":"伞","name":"UMBRELLA","hexcode":"2602","shortcodes":["umbrella"],"tags":["雨","雨伞"],"emoji":"☂️","text":"☂︎","type":0,"order":3184,"group":5,"subgroup":59,"version":0.7},{"annotation":"雨伞","name":"UMBRELLA WITH RAIN DROPS","hexcode":"2614","shortcodes":["umbrella_rain"],"tags":["下雨","雨滴"],"emoji":"☔️","text":"☔︎","type":1,"order":3185,"group":5,"subgroup":59,"version":0.6},{"annotation":"阳伞","name":"UMBRELLA ON GROUND","hexcode":"26F1","shortcodes":["beach_umbrella"],"tags":["伞"],"emoji":"⛱️","text":"⛱︎","type":0,"order":3187,"group":5,"subgroup":59,"version":0.7},{"annotation":"高压","name":"HIGH VOLTAGE SIGN","hexcode":"26A1","shortcodes":["zap","high_voltage"],"tags":["危险","有电","闪电"],"emoji":"⚡️","text":"⚡︎","type":1,"order":3188,"group":5,"subgroup":59,"version":0.6},{"annotation":"雪花","name":"SNOWFLAKE","hexcode":"2744","shortcodes":["snowflake"],"tags":["冷","雪"],"emoji":"❄️","text":"❄︎","type":0,"order":3190,"group":5,"subgroup":59,"version":0.6},{"annotation":"雪与雪人","name":"SNOWMAN","hexcode":"2603","shortcodes":["snowy_snowman"],"tags":["雪","雪人"],"emoji":"☃️","text":"☃︎","type":0,"order":3192,"group":5,"subgroup":59,"version":0.7},{"annotation":"雪人","name":"SNOWMAN WITHOUT SNOW","hexcode":"26C4","shortcodes":["snowman"],"tags":["雪人"],"emoji":"⛄️","text":"⛄︎","type":1,"order":3193,"group":5,"subgroup":59,"version":0.6},{"annotation":"彗星","name":"COMET","hexcode":"2604","shortcodes":["comet"],"tags":["太空"],"emoji":"☄️","text":"☄︎","type":0,"order":3195,"group":5,"subgroup":59,"version":1},{"annotation":"火焰","name":"FIRE","hexcode":"1F525","shortcodes":["fire"],"tags":["火"],"emoji":"🔥","text":"","type":1,"order":3196,"group":5,"subgroup":59,"version":0.6},{"annotation":"水滴","name":"DROPLET","hexcode":"1F4A7","shortcodes":["droplet"],"tags":["冷","水"],"emoji":"💧","text":"","type":1,"order":3197,"group":5,"subgroup":59,"version":0.6},{"annotation":"浪花","name":"WATER WAVE","hexcode":"1F30A","shortcodes":["ocean"],"tags":["波浪","海洋"],"emoji":"🌊","text":"","type":1,"order":3198,"group":5,"subgroup":59,"version":0.6},{"annotation":"南瓜灯","name":"JACK-O-LANTERN","hexcode":"1F383","shortcodes":["jack_o_lantern"],"tags":["万圣节","庆祝","灯笼"],"emoji":"🎃","text":"","type":1,"order":3199,"group":6,"subgroup":60,"version":0.6},{"annotation":"圣诞树","name":"CHRISTMAS TREE","hexcode":"1F384","shortcodes":["christmas_tree","xmas_tree"],"tags":["圣诞","庆祝","树"],"emoji":"🎄","text":"","type":1,"order":3200,"group":6,"subgroup":60,"version":0.6},{"annotation":"焰火","name":"FIREWORKS","hexcode":"1F386","shortcodes":["fireworks"],"tags":["庆祝","烟花"],"emoji":"🎆","text":"","type":1,"order":3201,"group":6,"subgroup":60,"version":0.6},{"annotation":"烟花","name":"FIREWORK SPARKLER","hexcode":"1F387","shortcodes":["sparkler"],"tags":["庆祝","火花","烟火","焰火"],"emoji":"🎇","text":"","type":1,"order":3202,"group":6,"subgroup":60,"version":0.6},{"annotation":"爆竹","name":"FIRECRACKER","hexcode":"1F9E8","shortcodes":["firecracker"],"tags":["炸药","烟花","爆炸"],"emoji":"🧨","text":"","type":1,"order":3203,"group":6,"subgroup":60,"version":11},{"annotation":"闪亮","name":"SPARKLES","hexcode":"2728","shortcodes":["sparkles"],"tags":["星星","火花","闪光","闪耀"],"emoji":"✨","text":"","type":1,"order":3204,"group":6,"subgroup":60,"version":0.6},{"annotation":"气球","name":"BALLOON","hexcode":"1F388","shortcodes":["balloon"],"tags":["庆祝"],"emoji":"🎈","text":"","type":1,"order":3205,"group":6,"subgroup":60,"version":0.6},{"annotation":"拉炮彩带","name":"PARTY POPPER","hexcode":"1F389","shortcodes":["tada","party"],"tags":["庆祝","彩带","派对","派对礼宾花"],"emoji":"🎉","text":"","type":1,"order":3206,"group":6,"subgroup":60,"version":0.6},{"annotation":"五彩纸屑球","name":"CONFETTI BALL","hexcode":"1F38A","shortcodes":["confetti_ball"],"tags":["庆祝","球"],"emoji":"🎊","text":"","type":1,"order":3207,"group":6,"subgroup":60,"version":0.6},{"annotation":"七夕树","name":"TANABATA TREE","hexcode":"1F38B","shortcodes":["tanabata_tree"],"tags":["七夕","庆祝","日本","树"],"emoji":"🎋","text":"","type":1,"order":3208,"group":6,"subgroup":60,"version":0.6},{"annotation":"门松","name":"PINE DECORATION","hexcode":"1F38D","shortcodes":["bamboo","pine_decor"],"tags":["庆祝","日本","松树","盆栽","竹"],"emoji":"🎍","text":"","type":1,"order":3209,"group":6,"subgroup":60,"version":0.6},{"annotation":"日本人形","name":"JAPANESE DOLLS","hexcode":"1F38E","shortcodes":["dolls"],"tags":["人偶","庆祝","节日"],"emoji":"🎎","text":"","type":1,"order":3210,"group":6,"subgroup":60,"version":0.6},{"annotation":"鲤鱼旗","name":"CARP STREAMER","hexcode":"1F38F","shortcodes":["carp_streamer"],"tags":["庆祝","日本","男孩节","长旗"],"emoji":"🎏","text":"","type":1,"order":3211,"group":6,"subgroup":60,"version":0.6},{"annotation":"风铃","name":"WIND CHIME","hexcode":"1F390","shortcodes":["wind_chime"],"tags":["庆祝","铃铛"],"emoji":"🎐","text":"","type":1,"order":3212,"group":6,"subgroup":60,"version":0.6},{"annotation":"赏月","name":"MOON VIEWING CEREMONY","hexcode":"1F391","shortcodes":["moon_ceremony","rice_scene"],"tags":["中秋","庆祝","月亮"],"emoji":"🎑","text":"","type":1,"order":3213,"group":6,"subgroup":60,"version":0.6},{"annotation":"红包","name":"RED GIFT ENVELOPE","hexcode":"1F9E7","shortcodes":["red_envelope"],"tags":["利是","礼物","运气","钱"],"emoji":"🧧","text":"","type":1,"order":3214,"group":6,"subgroup":60,"version":11},{"annotation":"蝴蝶结","name":"RIBBON","hexcode":"1F380","shortcodes":["ribbon"],"tags":["丝带","庆祝","缎带"],"emoji":"🎀","text":"","type":1,"order":3215,"group":6,"subgroup":60,"version":0.6},{"annotation":"礼物","name":"WRAPPED PRESENT","hexcode":"1F381","shortcodes":["gift"],"tags":["包装","庆祝","盒子","礼品"],"emoji":"🎁","text":"","type":1,"order":3216,"group":6,"subgroup":60,"version":0.6},{"annotation":"提示丝带","name":"REMINDER RIBBON","hexcode":"1F397","shortcodes":["reminder_ribbon"],"tags":["丝带","庆祝","暗示"],"emoji":"🎗️","text":"🎗︎","type":0,"order":3218,"group":6,"subgroup":60,"version":0.7},{"annotation":"入场券","name":"ADMISSION TICKETS","hexcode":"1F39F","shortcodes":["tickets","admission"],"tags":["票","门票"],"emoji":"🎟️","text":"🎟︎","type":0,"order":3220,"group":6,"subgroup":60,"version":0.7},{"annotation":"票","name":"TICKET","hexcode":"1F3AB","shortcodes":["ticket"],"tags":["入场券","电影票","车票","门票"],"emoji":"🎫","text":"","type":1,"order":3221,"group":6,"subgroup":60,"version":0.6},{"annotation":"军功章","name":"MILITARY MEDAL","hexcode":"1F396","shortcodes":["military_medal"],"tags":["军队","勋章","奖章"],"emoji":"🎖️","text":"🎖︎","type":0,"order":3223,"group":6,"subgroup":61,"version":0.7},{"annotation":"奖杯","name":"TROPHY","hexcode":"1F3C6","shortcodes":["trophy"],"tags":["奖励","奖品","奖赏"],"emoji":"🏆️","text":"🏆︎","type":1,"order":3224,"group":6,"subgroup":61,"version":0.6},{"annotation":"奖牌","name":"SPORTS MEDAL","hexcode":"1F3C5","shortcodes":["medal"],"tags":["运动会奖牌"],"emoji":"🏅","text":"","type":1,"order":3225,"group":6,"subgroup":61,"version":1},{"annotation":"金牌","name":"FIRST PLACE MEDAL","hexcode":"1F947","shortcodes":["first_place"],"tags":["奖牌","第一"],"emoji":"🥇","text":"","type":1,"order":3226,"group":6,"subgroup":61,"version":3},{"annotation":"银牌","name":"SECOND PLACE MEDAL","hexcode":"1F948","shortcodes":["second_place"],"tags":["奖牌","第二"],"emoji":"🥈","text":"","type":1,"order":3227,"group":6,"subgroup":61,"version":3},{"annotation":"铜牌","name":"THIRD PLACE MEDAL","hexcode":"1F949","shortcodes":["third_place"],"tags":["奖牌","第三"],"emoji":"🥉","text":"","type":1,"order":3228,"group":6,"subgroup":61,"version":3},{"annotation":"足球","name":"SOCCER BALL","hexcode":"26BD","shortcodes":["soccer"],"tags":["球","英式足球"],"emoji":"⚽️","text":"⚽︎","type":1,"order":3229,"group":6,"subgroup":62,"version":0.6},{"annotation":"棒球","name":"BASEBALL","hexcode":"26BE","shortcodes":["baseball"],"tags":["球"],"emoji":"⚾️","text":"⚾︎","type":1,"order":3230,"group":6,"subgroup":62,"version":0.6},{"annotation":"垒球","name":"SOFTBALL","hexcode":"1F94E","shortcodes":["softball"],"tags":["手套","球","腋下"],"emoji":"🥎","text":"","type":1,"order":3231,"group":6,"subgroup":62,"version":11},{"annotation":"篮球","name":"BASKETBALL AND HOOP","hexcode":"1F3C0","shortcodes":["basketball"],"tags":["球","篮筐"],"emoji":"🏀","text":"","type":1,"order":3232,"group":6,"subgroup":62,"version":0.6},{"annotation":"排球","name":"VOLLEYBALL","hexcode":"1F3D0","shortcodes":["volleyball"],"tags":["球"],"emoji":"🏐","text":"","type":1,"order":3233,"group":6,"subgroup":62,"version":1},{"annotation":"美式橄榄球","name":"AMERICAN FOOTBALL","hexcode":"1F3C8","shortcodes":["football"],"tags":["橄榄球","球"],"emoji":"🏈","text":"","type":1,"order":3234,"group":6,"subgroup":62,"version":0.6},{"annotation":"英式橄榄球","name":"RUGBY FOOTBALL","hexcode":"1F3C9","shortcodes":["rugby"],"tags":["橄榄球","球"],"emoji":"🏉","text":"","type":1,"order":3235,"group":6,"subgroup":62,"version":1},{"annotation":"网球","name":"TENNIS RACQUET AND BALL","hexcode":"1F3BE","shortcodes":["tennis"],"tags":["球","球拍"],"emoji":"🎾","text":"","type":1,"order":3236,"group":6,"subgroup":62,"version":0.6},{"annotation":"飞盘","name":"FLYING DISC","hexcode":"1F94F","shortcodes":["flying_disc"],"tags":["极限","极限运动","终极"],"emoji":"🥏","text":"","type":1,"order":3237,"group":6,"subgroup":62,"version":11},{"annotation":"保龄球","name":"BOWLING","hexcode":"1F3B3","shortcodes":["bowling"],"tags":["球"],"emoji":"🎳","text":"","type":1,"order":3238,"group":6,"subgroup":62,"version":0.6},{"annotation":"板球","name":"CRICKET BAT AND BALL","hexcode":"1F3CF","shortcodes":["cricket_game"],"tags":["球","球拍"],"emoji":"🏏","text":"","type":1,"order":3239,"group":6,"subgroup":62,"version":1},{"annotation":"曲棍球","name":"FIELD HOCKEY STICK AND BALL","hexcode":"1F3D1","shortcodes":["field_hockey"],"tags":["球","球棍"],"emoji":"🏑","text":"","type":1,"order":3240,"group":6,"subgroup":62,"version":1},{"annotation":"冰球","name":"ICE HOCKEY STICK AND PUCK","hexcode":"1F3D2","shortcodes":["hockey"],"tags":["球","球棍"],"emoji":"🏒","text":"","type":1,"order":3241,"group":6,"subgroup":62,"version":1},{"annotation":"袋棍球","name":"LACROSSE STICK AND BALL","hexcode":"1F94D","shortcodes":["lacrosse"],"tags":["球","球棍","球门"],"emoji":"🥍","text":"","type":1,"order":3242,"group":6,"subgroup":62,"version":11},{"annotation":"乒乓球","name":"TABLE TENNIS PADDLE AND BALL","hexcode":"1F3D3","shortcodes":["ping_pong"],"tags":["比赛","球","球拍"],"emoji":"🏓","text":"","type":1,"order":3243,"group":6,"subgroup":62,"version":1},{"annotation":"羽毛球","name":"BADMINTON RACQUET AND SHUTTLECOCK","hexcode":"1F3F8","shortcodes":["badminton"],"tags":["球拍"],"emoji":"🏸","text":"","type":1,"order":3244,"group":6,"subgroup":62,"version":1},{"annotation":"拳击手套","name":"BOXING GLOVE","hexcode":"1F94A","shortcodes":["boxing_glove"],"tags":["手套"],"emoji":"🥊","text":"","type":1,"order":3245,"group":6,"subgroup":62,"version":3},{"annotation":"练武服","name":"MARTIAL ARTS UNIFORM","hexcode":"1F94B","shortcodes":["gi","martial_arts_uniform"],"tags":["制服","柔道","武术","空手道","跆拳道"],"emoji":"🥋","text":"","type":1,"order":3246,"group":6,"subgroup":62,"version":3},{"annotation":"球门","name":"GOAL NET","hexcode":"1F945","shortcodes":["goal"],"tags":["球网"],"emoji":"🥅","text":"","type":1,"order":3247,"group":6,"subgroup":62,"version":3},{"annotation":"高尔夫球洞","name":"FLAG IN HOLE","hexcode":"26F3","shortcodes":["golf"],"tags":["高尔夫"],"emoji":"⛳️","text":"⛳︎","type":1,"order":3248,"group":6,"subgroup":62,"version":0.6},{"annotation":"滑冰","name":"ICE SKATE","hexcode":"26F8","shortcodes":["ice_skate"],"tags":["冰刀","溜冰"],"emoji":"⛸️","text":"⛸︎","type":0,"order":3250,"group":6,"subgroup":62,"version":0.7},{"annotation":"钓鱼竿","name":"FISHING POLE AND FISH","hexcode":"1F3A3","shortcodes":["fishing_pole"],"tags":["鱼杆"],"emoji":"🎣","text":"","type":1,"order":3251,"group":6,"subgroup":62,"version":0.6},{"annotation":"潜水面罩","name":"DIVING MASK","hexcode":"1F93F","shortcodes":["diving_mask","scuba_mask"],"tags":["浮潜","深潜","潜水"],"emoji":"🤿","text":"","type":1,"order":3252,"group":6,"subgroup":62,"version":12},{"annotation":"运动背心","name":"RUNNING SHIRT WITH SASH","hexcode":"1F3BD","shortcodes":["running_shirt"],"tags":["上衣","跑步"],"emoji":"🎽","text":"","type":1,"order":3253,"group":6,"subgroup":62,"version":0.6},{"annotation":"滑雪","name":"SKI AND SKI BOOT","hexcode":"1F3BF","shortcodes":["ski"],"tags":["雪"],"emoji":"🎿","text":"","type":1,"order":3254,"group":6,"subgroup":62,"version":0.6},{"annotation":"雪橇","name":"SLED","hexcode":"1F6F7","shortcodes":["sled"],"tags":["乘雪橇","驾雪橇"],"emoji":"🛷","text":"","type":1,"order":3255,"group":6,"subgroup":62,"version":5},{"annotation":"冰壶","name":"CURLING STONE","hexcode":"1F94C","shortcodes":["curling_stone"],"tags":["冰上溜石","比赛","游戏"],"emoji":"🥌","text":"","type":1,"order":3256,"group":6,"subgroup":62,"version":5},{"annotation":"正中靶心的飞镖","name":"DIRECT HIT","hexcode":"1F3AF","shortcodes":["dart"],"tags":["命中","靶心","飞镖"],"emoji":"🎯","text":"","type":1,"order":3257,"group":6,"subgroup":63,"version":0.6},{"annotation":"悠悠球","name":"YO-YO","hexcode":"1FA80","shortcodes":["yoyo"],"tags":["上下起落","玩具"],"emoji":"🪀","text":"","type":1,"order":3258,"group":6,"subgroup":63,"version":12},{"annotation":"风筝","name":"KITE","hexcode":"1FA81","shortcodes":["kite"],"tags":["翱翔","飞翔"],"emoji":"🪁","text":"","type":1,"order":3259,"group":6,"subgroup":63,"version":12},{"annotation":"台球","name":"BILLIARDS","hexcode":"1F3B1","shortcodes":["8ball"],"tags":["桌球"],"emoji":"🎱","text":"","type":1,"order":3260,"group":6,"subgroup":63,"version":0.6},{"annotation":"水晶球","name":"CRYSTAL BALL","hexcode":"1F52E","shortcodes":["crystal_ball"],"tags":["命运","工具","水晶","球","财富"],"emoji":"🔮","text":"","type":1,"order":3261,"group":6,"subgroup":63,"version":0.6},{"annotation":"魔棒","name":"MAGIC WAND","hexcode":"1FA84","shortcodes":["wand"],"tags":["女巫","巫师","魔法"],"emoji":"🪄","text":"","type":1,"order":3262,"group":6,"subgroup":63,"version":13},{"annotation":"纳扎尔护身符","name":"NAZAR AMULET","hexcode":"1F9FF","shortcodes":["nazar_amulet"],"tags":["小装饰品","恶魔之眼","护身符","珠子","纳扎尔"],"emoji":"🧿","text":"","type":1,"order":3263,"group":6,"subgroup":63,"version":11},{"annotation":"游戏手柄","name":"VIDEO GAME","hexcode":"1F3AE","shortcodes":["video_game"],"tags":["手柄","电子游戏"],"emoji":"🎮️","text":"🎮︎","type":1,"order":3264,"group":6,"subgroup":63,"version":0.6},{"annotation":"游戏操控杆","name":"JOYSTICK","hexcode":"1F579","shortcodes":["joystick"],"tags":["操控杆","电子游戏"],"emoji":"🕹️","text":"🕹︎","type":0,"order":3266,"group":6,"subgroup":63,"version":0.7},{"annotation":"老虎机","name":"SLOT MACHINE","hexcode":"1F3B0","shortcodes":["slot_machine"],"tags":["游戏","角子机","赌博"],"emoji":"🎰","text":"","type":1,"order":3267,"group":6,"subgroup":63,"version":0.6},{"annotation":"骰子","name":"GAME DIE","hexcode":"1F3B2","shortcodes":["game_die"],"tags":["色子"],"emoji":"🎲","text":"","type":1,"order":3268,"group":6,"subgroup":63,"version":0.6},{"annotation":"拼图","name":"JIGSAW PUZZLE PIECE","hexcode":"1F9E9","shortcodes":["jigsaw","puzzle_piece"],"tags":["图片","智力游戏","线索","联锁"],"emoji":"🧩","text":"","type":1,"order":3269,"group":6,"subgroup":63,"version":11},{"annotation":"泰迪熊","name":"TEDDY BEAR","hexcode":"1F9F8","shortcodes":["teddy_bear"],"tags":["填充","毛绒玩具","玩偶","玩具"],"emoji":"🧸","text":"","type":1,"order":3270,"group":6,"subgroup":63,"version":11},{"annotation":"彩罐","name":"PINATA","hexcode":"1FA85","shortcodes":["pinata"],"tags":["庆祝","聚会"],"emoji":"🪅","text":"","type":1,"order":3271,"group":6,"subgroup":63,"version":13},{"annotation":"套娃","name":"NESTING DOLLS","hexcode":"1FA86","shortcodes":["nesting_dolls"],"tags":["俄罗斯套娃","娃娃"],"emoji":"🪆","text":"","type":1,"order":3272,"group":6,"subgroup":63,"version":13},{"annotation":"黑桃","name":"BLACK SPADE SUIT","hexcode":"2660","shortcodes":["spades"],"tags":["扑克","牌","葵扇"],"emoji":"♠️","text":"♠︎","type":0,"order":3274,"group":6,"subgroup":63,"version":0.6},{"annotation":"红桃","name":"BLACK HEART SUIT","hexcode":"2665","shortcodes":["hearts"],"tags":["扑克","牌","红心"],"emoji":"♥️","text":"♥︎","type":0,"order":3276,"group":6,"subgroup":63,"version":0.6},{"annotation":"方片","name":"BLACK DIAMOND SUIT","hexcode":"2666","shortcodes":["diamonds"],"tags":["扑克","方块","牌"],"emoji":"♦️","text":"♦︎","type":0,"order":3278,"group":6,"subgroup":63,"version":0.6},{"annotation":"梅花","name":"BLACK CLUB SUIT","hexcode":"2663","shortcodes":["clubs"],"tags":["扑克","牌","草花"],"emoji":"♣️","text":"♣︎","type":0,"order":3280,"group":6,"subgroup":63,"version":0.6},{"annotation":"兵","name":"BLACK CHESS PAWN","hexcode":"265F","shortcodes":["chess_pawn"],"tags":["受骗者","国际象棋","牺牲品"],"emoji":"♟️","text":"♟︎","type":0,"order":3282,"group":6,"subgroup":63,"version":11},{"annotation":"大小王","name":"PLAYING CARD BLACK JOKER","hexcode":"1F0CF","shortcodes":["black_joker"],"tags":["大王","小王","扑克","牌","鬼牌"],"emoji":"🃏","text":"","type":1,"order":3283,"group":6,"subgroup":63,"version":0.6},{"annotation":"红中","name":"MAHJONG TILE RED DRAGON","hexcode":"1F004","shortcodes":["mahjong"],"tags":["麻将"],"emoji":"🀄️","text":"🀄︎","type":1,"order":3284,"group":6,"subgroup":63,"version":0.6},{"annotation":"花札","name":"FLOWER PLAYING CARDS","hexcode":"1F3B4","shortcodes":["flower_cards"],"tags":["花斗","花牌"],"emoji":"🎴","text":"","type":1,"order":3285,"group":6,"subgroup":63,"version":0.6},{"annotation":"面具","name":"PERFORMING ARTS","hexcode":"1F3AD","shortcodes":["performing_arts"],"tags":["剧院","戏剧","艺术","表演"],"emoji":"🎭️","text":"🎭︎","type":1,"order":3286,"group":6,"subgroup":64,"version":0.6},{"annotation":"带框的画","name":"FRAME WITH PICTURE","hexcode":"1F5BC","shortcodes":["frame_photo"],"tags":["博物馆","框","画","艺术"],"emoji":"🖼️","text":"🖼︎","type":0,"order":3288,"group":6,"subgroup":64,"version":0.7},{"annotation":"调色盘","name":"ARTIST PALETTE","hexcode":"1F3A8","shortcodes":["art","palette"],"tags":["博物馆","画画","艺术","调色板"],"emoji":"🎨","text":"","type":1,"order":3289,"group":6,"subgroup":64,"version":0.6},{"annotation":"线","name":"SPOOL OF THREAD","hexcode":"1F9F5","shortcodes":["spool"],"tags":["线轴","绳子","缝纫","针"],"emoji":"🧵","text":"","type":1,"order":3290,"group":6,"subgroup":64,"version":11},{"annotation":"缝合针","name":"SEWING NEEDLE","hexcode":"1FAA1","shortcodes":["sewing_needle"],"tags":["绣花针","缝合","缝纫","缝线","裁剪"],"emoji":"🪡","text":"","type":1,"order":3291,"group":6,"subgroup":64,"version":13},{"annotation":"毛线","name":"BALL OF YARN","hexcode":"1F9F6","shortcodes":["yarn"],"tags":["毛线球","编织","钩针编织物"],"emoji":"🧶","text":"","type":1,"order":3292,"group":6,"subgroup":64,"version":11},{"annotation":"结","name":"KNOT","hexcode":"1FAA2","shortcodes":["knot"],"tags":["结"],"emoji":"🪢","text":"","type":1,"order":3293,"group":6,"subgroup":64,"version":13},{"annotation":"眼镜","name":"EYEGLASSES","hexcode":"1F453","shortcodes":["glasses"],"tags":["眼镜"],"emoji":"👓️","text":"👓︎","type":1,"order":3294,"group":7,"subgroup":65,"version":0.6},{"annotation":"墨镜","name":"DARK SUNGLASSES","hexcode":"1F576","shortcodes":["sunglasses"],"tags":["太阳镜"],"emoji":"🕶️","text":"🕶︎","type":0,"order":3296,"group":7,"subgroup":65,"version":0.7},{"annotation":"护目镜","name":"GOGGLES","hexcode":"1F97D","shortcodes":["goggles"],"tags":["护眼","游泳","焊接"],"emoji":"🥽","text":"","type":1,"order":3297,"group":7,"subgroup":65,"version":11},{"annotation":"白大褂","name":"LAB COAT","hexcode":"1F97C","shortcodes":["lab_coat"],"tags":["医生","实验人员","科学家"],"emoji":"🥼","text":"","type":1,"order":3298,"group":7,"subgroup":65,"version":11},{"annotation":"救生衣","name":"SAFETY VEST","hexcode":"1F9BA","shortcodes":["safety_vest"],"tags":["安全","紧急","背心","逃生"],"emoji":"🦺","text":"","type":1,"order":3299,"group":7,"subgroup":65,"version":12},{"annotation":"领带","name":"NECKTIE","hexcode":"1F454","shortcodes":["necktie","tie"],"tags":["衬衫领带"],"emoji":"👔","text":"","type":1,"order":3300,"group":7,"subgroup":65,"version":0.6},{"annotation":"T恤","name":"T-SHIRT","hexcode":"1F455","shortcodes":["shirt"],"tags":["t恤","恤衫"],"emoji":"👕","text":"","type":1,"order":3301,"group":7,"subgroup":65,"version":0.6},{"annotation":"牛仔裤","name":"JEANS","hexcode":"1F456","shortcodes":["jeans"],"tags":["裤子"],"emoji":"👖","text":"","type":1,"order":3302,"group":7,"subgroup":65,"version":0.6},{"annotation":"围巾","name":"SCARF","hexcode":"1F9E3","shortcodes":["scarf"],"tags":["围巾"],"emoji":"🧣","text":"","type":1,"order":3303,"group":7,"subgroup":65,"version":5},{"annotation":"手套","name":"GLOVES","hexcode":"1F9E4","shortcodes":["gloves"],"tags":["手套"],"emoji":"🧤","text":"","type":1,"order":3304,"group":7,"subgroup":65,"version":5},{"annotation":"外套","name":"COAT","hexcode":"1F9E5","shortcodes":["coat"],"tags":["夹克"],"emoji":"🧥","text":"","type":1,"order":3305,"group":7,"subgroup":65,"version":5},{"annotation":"袜子","name":"SOCKS","hexcode":"1F9E6","shortcodes":["socks"],"tags":["短袜","长袜"],"emoji":"🧦","text":"","type":1,"order":3306,"group":7,"subgroup":65,"version":5},{"annotation":"连衣裙","name":"DRESS","hexcode":"1F457","shortcodes":["dress"],"tags":["衣服"],"emoji":"👗","text":"","type":1,"order":3307,"group":7,"subgroup":65,"version":0.6},{"annotation":"和服","name":"KIMONO","hexcode":"1F458","shortcodes":["kimono"],"tags":["日本"],"emoji":"👘","text":"","type":1,"order":3308,"group":7,"subgroup":65,"version":0.6},{"annotation":"纱丽","name":"SARI","hexcode":"1F97B","shortcodes":["sari"],"tags":["印度","披肩","衣服"],"emoji":"🥻","text":"","type":1,"order":3309,"group":7,"subgroup":65,"version":12},{"annotation":"连体泳衣","name":"ONE-PIECE SWIMSUIT","hexcode":"1FA71","shortcodes":["one_piece_swimsuit"],"tags":["一片式","泳衣","泳装","游泳"],"emoji":"🩱","text":"","type":1,"order":3310,"group":7,"subgroup":65,"version":12},{"annotation":"三角裤","name":"BRIEFS","hexcode":"1FA72","shortcodes":["briefs"],"tags":["一片式","内裤","泳衣","泳装","短裤"],"emoji":"🩲","text":"","type":1,"order":3311,"group":7,"subgroup":65,"version":12},{"annotation":"短裤","name":"SHORTS","hexcode":"1FA73","shortcodes":["shorts"],"tags":["内裤","四角裤","泳衣","泳装","裤子"],"emoji":"🩳","text":"","type":1,"order":3312,"group":7,"subgroup":65,"version":12},{"annotation":"比基尼","name":"BIKINI","hexcode":"1F459","shortcodes":["bikini"],"tags":["三点式","泳装"],"emoji":"👙","text":"","type":1,"order":3313,"group":7,"subgroup":65,"version":0.6},{"annotation":"女装","name":"WOMANS CLOTHES","hexcode":"1F45A","shortcodes":["blouse","womans_clothes"],"tags":["女","衣服"],"emoji":"👚","text":"","type":1,"order":3314,"group":7,"subgroup":65,"version":0.6},{"annotation":"钱包","name":"PURSE","hexcode":"1F45B","shortcodes":["purse"],"tags":["钱包"],"emoji":"👛","text":"","type":1,"order":3315,"group":7,"subgroup":65,"version":0.6},{"annotation":"手提包","name":"HANDBAG","hexcode":"1F45C","shortcodes":["handbag"],"tags":["挎包"],"emoji":"👜","text":"","type":1,"order":3316,"group":7,"subgroup":65,"version":0.6},{"annotation":"手袋","name":"POUCH","hexcode":"1F45D","shortcodes":["pouch","clutch_bag"],"tags":["包","手拿包"],"emoji":"👝","text":"","type":1,"order":3317,"group":7,"subgroup":65,"version":0.6},{"annotation":"购物袋","name":"SHOPPING BAGS","hexcode":"1F6CD","shortcodes":["shopping_bags"],"tags":["包","袋","逛街"],"emoji":"🛍️","text":"🛍︎","type":0,"order":3319,"group":7,"subgroup":65,"version":0.7},{"annotation":"书包","name":"SCHOOL SATCHEL","hexcode":"1F392","shortcodes":["backpack"],"tags":["包"],"emoji":"🎒","text":"","type":1,"order":3320,"group":7,"subgroup":65,"version":0.6},{"annotation":"夹趾凉鞋","name":"THONG SANDAL","hexcode":"1FA74","shortcodes":["sandal"],"tags":["凉鞋","沙滩凉鞋","草屡"],"emoji":"🩴","text":"","type":1,"order":3321,"group":7,"subgroup":65,"version":13},{"annotation":"男鞋","name":"MANS SHOE","hexcode":"1F45E","shortcodes":["dress_shoe","mans_shoe"],"tags":["鞋"],"emoji":"👞","text":"","type":1,"order":3322,"group":7,"subgroup":65,"version":0.6},{"annotation":"跑鞋","name":"ATHLETIC SHOE","hexcode":"1F45F","shortcodes":["sneaker","athletic_shoe"],"tags":["运动鞋","鞋"],"emoji":"👟","text":"","type":1,"order":3323,"group":7,"subgroup":65,"version":0.6},{"annotation":"登山鞋","name":"HIKING BOOT","hexcode":"1F97E","shortcodes":["hiking_boot"],"tags":["徒步","登山","远足野营","露营"],"emoji":"🥾","text":"","type":1,"order":3324,"group":7,"subgroup":65,"version":11},{"annotation":"平底鞋","name":"FLAT SHOE","hexcode":"1F97F","shortcodes":["flat_shoe"],"tags":["一脚蹬","便鞋","平底芭蕾舞鞋"],"emoji":"🥿","text":"","type":1,"order":3325,"group":7,"subgroup":65,"version":11},{"annotation":"高跟鞋","name":"HIGH-HEELED SHOE","hexcode":"1F460","shortcodes":["high_heel"],"tags":["女","鞋"],"emoji":"👠","text":"","type":1,"order":3326,"group":7,"subgroup":65,"version":0.6},{"annotation":"女式凉鞋","name":"WOMANS SANDAL","hexcode":"1F461","shortcodes":["womans_sandal"],"tags":["凉鞋","女"],"emoji":"👡","text":"","type":1,"order":3327,"group":7,"subgroup":65,"version":0.6},{"annotation":"芭蕾舞鞋","name":"BALLET SHOES","hexcode":"1FA70","shortcodes":["ballet_shoes"],"tags":["舞蹈","舞鞋","足尖鞋","跳舞"],"emoji":"🩰","text":"","type":1,"order":3328,"group":7,"subgroup":65,"version":12},{"annotation":"女靴","name":"WOMANS BOOTS","hexcode":"1F462","shortcodes":["womans_boot"],"tags":["女","靴子"],"emoji":"👢","text":"","type":1,"order":3329,"group":7,"subgroup":65,"version":0.6},{"annotation":"皇冠","name":"CROWN","hexcode":"1F451","shortcodes":["crown"],"tags":["王冠"],"emoji":"👑","text":"","type":1,"order":3330,"group":7,"subgroup":65,"version":0.6},{"annotation":"女帽","name":"WOMANS HAT","hexcode":"1F452","shortcodes":["womans_hat"],"tags":["女","帽子"],"emoji":"👒","text":"","type":1,"order":3331,"group":7,"subgroup":65,"version":0.6},{"annotation":"礼帽","name":"TOP HAT","hexcode":"1F3A9","shortcodes":["top_hat"],"tags":["帽子","高帽"],"emoji":"🎩","text":"","type":1,"order":3332,"group":7,"subgroup":65,"version":0.6},{"annotation":"毕业帽","name":"GRADUATION CAP","hexcode":"1F393","shortcodes":["graduation_cap"],"tags":["四方帽"],"emoji":"🎓️","text":"🎓︎","type":1,"order":3333,"group":7,"subgroup":65,"version":0.6},{"annotation":"鸭舌帽","name":"BILLED CAP","hexcode":"1F9E2","shortcodes":["billed_cap"],"tags":["棒球帽"],"emoji":"🧢","text":"","type":1,"order":3334,"group":7,"subgroup":65,"version":5},{"annotation":"军用头盔","name":"MILITARY HELMET","hexcode":"1FA96","shortcodes":["military_helmet"],"tags":["军用","军队","士兵","头盔","战士"],"emoji":"🪖","text":"","type":1,"order":3335,"group":7,"subgroup":65,"version":13},{"annotation":"白十字头盔","name":"HELMET WITH WHITE CROSS","hexcode":"26D1","shortcodes":["helmet_cross"],"tags":["十字","头盔","安全帽"],"emoji":"⛑️","text":"⛑︎","type":0,"order":3337,"group":7,"subgroup":65,"version":0.7},{"annotation":"念珠","name":"PRAYER BEADS","hexcode":"1F4FF","shortcodes":["prayer_beads"],"tags":["宗教","珠子","祈祷","项链"],"emoji":"📿","text":"","type":1,"order":3338,"group":7,"subgroup":65,"version":1},{"annotation":"唇膏","name":"LIPSTICK","hexcode":"1F484","shortcodes":["lipstick"],"tags":["化妆品","口红"],"emoji":"💄","text":"","type":1,"order":3339,"group":7,"subgroup":65,"version":0.6},{"annotation":"戒指","name":"RING","hexcode":"1F48D","shortcodes":["ring"],"tags":["钻戒"],"emoji":"💍","text":"","type":1,"order":3340,"group":7,"subgroup":65,"version":0.6},{"annotation":"宝石","name":"GEM STONE","hexcode":"1F48E","shortcodes":["gem"],"tags":["钻石"],"emoji":"💎","text":"","type":1,"order":3341,"group":7,"subgroup":65,"version":0.6},{"annotation":"已静音的扬声器","name":"SPEAKER WITH CANCELLATION STROKE","hexcode":"1F507","shortcodes":["mute","no_sound"],"tags":["安静","扬声器","扬声器关闭","无声","静音"],"emoji":"🔇","text":"","type":1,"order":3342,"group":7,"subgroup":66,"version":1},{"annotation":"低音量的扬声器","name":"SPEAKER","hexcode":"1F508","shortcodes":["speaker","low_sound"],"tags":["小声","小音量","扬声器","轻声"],"emoji":"🔈️","text":"🔈︎","type":1,"order":3343,"group":7,"subgroup":66,"version":0.7},{"annotation":"中等音量的扬声器","name":"SPEAKER WITH ONE SOUND WAVE","hexcode":"1F509","shortcodes":["sound"],"tags":["中等","中等音量","扬声器"],"emoji":"🔉","text":"","type":1,"order":3344,"group":7,"subgroup":66,"version":1},{"annotation":"高音量的扬声器","name":"SPEAKER WITH THREE SOUND WAVES","hexcode":"1F50A","shortcodes":["loud_sound"],"tags":["大声","大音量","扬声器"],"emoji":"🔊","text":"","type":1,"order":3345,"group":7,"subgroup":66,"version":0.6},{"annotation":"喇叭","name":"PUBLIC ADDRESS LOUDSPEAKER","hexcode":"1F4E2","shortcodes":["loudspeaker"],"tags":["公共广播","大声","广播","通知"],"emoji":"📢","text":"","type":1,"order":3346,"group":7,"subgroup":66,"version":0.6},{"annotation":"扩音器","name":"CHEERING MEGAPHONE","hexcode":"1F4E3","shortcodes":["megaphone"],"tags":["呼喊","喇叭筒","大声","通知"],"emoji":"📣","text":"","type":1,"order":3347,"group":7,"subgroup":66,"version":0.6},{"annotation":"邮号","name":"POSTAL HORN","hexcode":"1F4EF","shortcodes":["postal_horn"],"tags":["号","号角","喇叭","邮政"],"emoji":"📯","text":"","type":1,"order":3348,"group":7,"subgroup":66,"version":1},{"annotation":"铃铛","name":"BELL","hexcode":"1F514","shortcodes":["bell"],"tags":["叮当","响铃"],"emoji":"🔔","text":"","type":1,"order":3349,"group":7,"subgroup":66,"version":0.6},{"annotation":"禁止响铃","name":"BELL WITH CANCELLATION STROKE","hexcode":"1F515","shortcodes":["no_bell"],"tags":["响铃关闭","安静","无声","静音"],"emoji":"🔕","text":"","type":1,"order":3350,"group":7,"subgroup":66,"version":1},{"annotation":"乐谱","name":"MUSICAL SCORE","hexcode":"1F3BC","shortcodes":["musical_score"],"tags":["五线谱","音乐","音符"],"emoji":"🎼","text":"","type":1,"order":3351,"group":7,"subgroup":67,"version":0.6},{"annotation":"音符","name":"MUSICAL NOTE","hexcode":"1F3B5","shortcodes":["musical_note"],"tags":["乐谱","五线谱","八分音符","音乐"],"emoji":"🎵","text":"","type":1,"order":3352,"group":7,"subgroup":67,"version":0.6},{"annotation":"多个音符","name":"MULTIPLE MUSICAL NOTES","hexcode":"1F3B6","shortcodes":["musical_notes"],"tags":["乐谱","五线谱","八分音符","音乐","音符"],"emoji":"🎶","text":"","type":1,"order":3353,"group":7,"subgroup":67,"version":0.6},{"annotation":"录音室麦克风","name":"STUDIO MICROPHONE","hexcode":"1F399","shortcodes":["studio_microphone"],"tags":["录音室","音乐","麦","麦克","麦克风"],"emoji":"🎙️","text":"🎙︎","type":0,"order":3355,"group":7,"subgroup":67,"version":0.7},{"annotation":"电平滑块","name":"LEVEL SLIDER","hexcode":"1F39A","shortcodes":["level_slider"],"tags":["滑块","电平","调节","音乐"],"emoji":"🎚️","text":"🎚︎","type":0,"order":3357,"group":7,"subgroup":67,"version":0.7},{"annotation":"控制旋钮","name":"CONTROL KNOBS","hexcode":"1F39B","shortcodes":["control_knobs"],"tags":["控制","旋钮","调节","音乐"],"emoji":"🎛️","text":"🎛︎","type":0,"order":3359,"group":7,"subgroup":67,"version":0.7},{"annotation":"麦克风","name":"MICROPHONE","hexcode":"1F3A4","shortcodes":["microphone"],"tags":["卡拉ok","唱k","唱歌","麦","麦克"],"emoji":"🎤","text":"","type":1,"order":3360,"group":7,"subgroup":67,"version":0.6},{"annotation":"耳机","name":"HEADPHONE","hexcode":"1F3A7","shortcodes":["headphones"],"tags":["头戴式耳机"],"emoji":"🎧️","text":"🎧︎","type":1,"order":3361,"group":7,"subgroup":67,"version":0.6},{"annotation":"收音机","name":"RADIO","hexcode":"1F4FB","shortcodes":["radio"],"tags":["广播","广播电台","无线电","电台"],"emoji":"📻️","text":"📻︎","type":1,"order":3362,"group":7,"subgroup":67,"version":0.6},{"annotation":"萨克斯管","name":"SAXOPHONE","hexcode":"1F3B7","shortcodes":["saxophone"],"tags":["乐器","吹奏","演奏","音乐"],"emoji":"🎷","text":"","type":1,"order":3363,"group":7,"subgroup":68,"version":0.6},{"annotation":"手风琴","name":"ACCORDION","hexcode":"1FA97","shortcodes":["accordion"],"tags":["六角形风琴","风琴"],"emoji":"🪗","text":"","type":1,"order":3364,"group":7,"subgroup":68,"version":13},{"annotation":"吉他","name":"GUITAR","hexcode":"1F3B8","shortcodes":["guitar"],"tags":["乐器","弹奏","演奏","音乐"],"emoji":"🎸","text":"","type":1,"order":3365,"group":7,"subgroup":68,"version":0.6},{"annotation":"音乐键盘","name":"MUSICAL KEYBOARD","hexcode":"1F3B9","shortcodes":["musical_keyboard"],"tags":["乐器","弹奏","演奏","钢琴","音乐"],"emoji":"🎹","text":"","type":1,"order":3366,"group":7,"subgroup":68,"version":0.6},{"annotation":"小号","name":"TRUMPET","hexcode":"1F3BA","shortcodes":["trumpet"],"tags":["乐器","吹奏","喇叭","音乐"],"emoji":"🎺","text":"","type":1,"order":3367,"group":7,"subgroup":68,"version":0.6},{"annotation":"小提琴","name":"VIOLIN","hexcode":"1F3BB","shortcodes":["violin"],"tags":["乐器","提琴","演奏","音乐"],"emoji":"🎻","text":"","type":1,"order":3368,"group":7,"subgroup":68,"version":0.6},{"annotation":"班卓琴","name":"BANJO","hexcode":"1FA95","shortcodes":["banjo"],"tags":["弦乐器","弹奏","音乐"],"emoji":"🪕","text":"","type":1,"order":3369,"group":7,"subgroup":68,"version":12},{"annotation":"鼓","name":"DRUM WITH DRUMSTICKS","hexcode":"1F941","shortcodes":["drum"],"tags":["音乐","鼓声","鼓槌"],"emoji":"🥁","text":"","type":1,"order":3370,"group":7,"subgroup":68,"version":3},{"annotation":"长鼓","name":"LONG DRUM","hexcode":"1FA98","shortcodes":["long_drum"],"tags":["康加鼓","敲","节奏","鼓"],"emoji":"🪘","text":"","type":1,"order":3371,"group":7,"subgroup":68,"version":13},{"annotation":"手机","name":"MOBILE PHONE","hexcode":"1F4F1","shortcodes":["mobile","iphone","android"],"tags":["手提电话","智能手机","电话","移动"],"emoji":"📱","text":"","type":1,"order":3372,"group":7,"subgroup":69,"version":0.6},{"annotation":"带有箭头的手机","name":"MOBILE PHONE WITH RIGHTWARDS ARROW AT LEFT","hexcode":"1F4F2","shortcodes":["mobile_calling"],"tags":["手机","接收","智能手机","来电"],"emoji":"📲","text":"","type":1,"order":3373,"group":7,"subgroup":69,"version":0.6},{"annotation":"电话","name":"BLACK TELEPHONE","hexcode":"260E","shortcodes":["telephone"],"tags":["固定电话","固话","座机"],"emoji":"☎️","text":"☎︎","type":0,"order":3375,"group":7,"subgroup":69,"version":0.6},{"annotation":"电话听筒","name":"TELEPHONE RECEIVER","hexcode":"1F4DE","shortcodes":["telephone_receiver"],"tags":["固定电话","固话","座机","电话"],"emoji":"📞","text":"","type":1,"order":3376,"group":7,"subgroup":69,"version":0.6},{"annotation":"寻呼机","name":"PAGER","hexcode":"1F4DF","shortcodes":["pager"],"tags":["bb 机","传呼机","呼机"],"emoji":"📟️","text":"📟︎","type":1,"order":3377,"group":7,"subgroup":69,"version":0.6},{"annotation":"传真机","name":"FAX MACHINE","hexcode":"1F4E0","shortcodes":["fax"],"tags":["传真","传真号","发传真"],"emoji":"📠","text":"","type":1,"order":3378,"group":7,"subgroup":69,"version":0.6},{"annotation":"电池","name":"BATTERY","hexcode":"1F50B","shortcodes":["battery"],"tags":["正极","电极","电源","蓄电池","负极"],"emoji":"🔋","text":"","type":1,"order":3379,"group":7,"subgroup":70,"version":0.6},{"annotation":"电源插头","name":"ELECTRIC PLUG","hexcode":"1F50C","shortcodes":["electric_plug"],"tags":["插头","电插头","电源","电线"],"emoji":"🔌","text":"","type":1,"order":3380,"group":7,"subgroup":70,"version":0.6},{"annotation":"笔记本电脑","name":"PERSONAL COMPUTER","hexcode":"1F4BB","shortcodes":["laptop"],"tags":["pc","个人电脑","手提电脑","电脑"],"emoji":"💻️","text":"💻︎","type":1,"order":3381,"group":7,"subgroup":70,"version":0.6},{"annotation":"台式电脑","name":"DESKTOP COMPUTER","hexcode":"1F5A5","shortcodes":["desktop","computer"],"tags":["pc","个人电脑","显示器","显示屏","计算机"],"emoji":"🖥️","text":"🖥︎","type":0,"order":3383,"group":7,"subgroup":70,"version":0.7},{"annotation":"打印机","name":"PRINTER","hexcode":"1F5A8","shortcodes":["printer"],"tags":["印刷机","喷墨打印","复印","扫描","激光打印"],"emoji":"🖨️","text":"🖨︎","type":0,"order":3385,"group":7,"subgroup":70,"version":0.7},{"annotation":"键盘","name":"KEYBOARD","hexcode":"2328","shortcodes":["keyboard"],"tags":["打字","按键","电脑","输入"],"emoji":"⌨️","text":"⌨︎","type":0,"order":3387,"group":7,"subgroup":70,"version":1},{"annotation":"电脑鼠标","name":"THREE BUTTON MOUSE","hexcode":"1F5B1","shortcodes":["computer_mouse"],"tags":["有线鼠标","激光鼠标","点击","点按","电脑"],"emoji":"🖱️","text":"🖱︎","type":0,"order":3389,"group":7,"subgroup":70,"version":0.7},{"annotation":"轨迹球","name":"TRACKBALL","hexcode":"1F5B2","shortcodes":["trackball"],"tags":["有线鼠标","电脑","追踪球","鼠标"],"emoji":"🖲️","text":"🖲︎","type":0,"order":3391,"group":7,"subgroup":70,"version":0.7},{"annotation":"电脑光盘","name":"MINIDISC","hexcode":"1F4BD","shortcodes":["minidisc"],"tags":["minidisk","mini光盘","光盘","迷你光碟","迷你唱片"],"emoji":"💽","text":"","type":1,"order":3392,"group":7,"subgroup":70,"version":0.6},{"annotation":"软盘","name":"FLOPPY DISK","hexcode":"1F4BE","shortcodes":["floppy_disk"],"tags":["3.5英寸","便携","存储","磁盘"],"emoji":"💾","text":"","type":1,"order":3393,"group":7,"subgroup":70,"version":0.6},{"annotation":"光盘","name":"OPTICAL DISC","hexcode":"1F4BF","shortcodes":["cd","disk"],"tags":["cd","专辑","存储","影片","音乐"],"emoji":"💿️","text":"💿︎","type":1,"order":3394,"group":7,"subgroup":70,"version":0.6},{"annotation":"DVD","name":"DVD","hexcode":"1F4C0","shortcodes":["dvd"],"tags":["dvd","光盘","光碟","影片","音乐"],"emoji":"📀","text":"","type":1,"order":3395,"group":7,"subgroup":70,"version":0.6},{"annotation":"算盘","name":"ABACUS","hexcode":"1F9EE","shortcodes":["abacus"],"tags":["计算"],"emoji":"🧮","text":"","type":1,"order":3396,"group":7,"subgroup":70,"version":11},{"annotation":"电影摄影机","name":"MOVIE CAMERA","hexcode":"1F3A5","shortcodes":["movie_camera"],"tags":["摄像机","摄录机","摄影","摄影机","电影"],"emoji":"🎥","text":"","type":1,"order":3397,"group":7,"subgroup":71,"version":0.6},{"annotation":"影片帧","name":"FILM FRAMES","hexcode":"1F39E","shortcodes":["film_frames"],"tags":["帧","电影","电影胶片","胶卷","胶片"],"emoji":"🎞️","text":"🎞︎","type":0,"order":3399,"group":7,"subgroup":71,"version":0.7},{"annotation":"电影放映机","name":"FILM PROJECTOR","hexcode":"1F4FD","shortcodes":["projector"],"tags":["影片","投影仪","放映机","电影","视频"],"emoji":"📽️","text":"📽︎","type":0,"order":3401,"group":7,"subgroup":71,"version":0.7},{"annotation":"场记板","name":"CLAPPER BOARD","hexcode":"1F3AC","shortcodes":["clapper"],"tags":["场记","打板","拍电影"],"emoji":"🎬️","text":"🎬︎","type":1,"order":3402,"group":7,"subgroup":71,"version":0.6},{"annotation":"电视机","name":"TELEVISION","hexcode":"1F4FA","shortcodes":["tv"],"tags":["电视","看电视","节目","视频"],"emoji":"📺️","text":"📺︎","type":1,"order":3403,"group":7,"subgroup":71,"version":0.6},{"annotation":"相机","name":"CAMERA","hexcode":"1F4F7","shortcodes":["camera"],"tags":["卡片相机","拍照","摄影","照片","照相机"],"emoji":"📷️","text":"📷︎","type":1,"order":3404,"group":7,"subgroup":71,"version":0.6},{"annotation":"开闪光灯的相机","name":"CAMERA WITH FLASH","hexcode":"1F4F8","shortcodes":["camera_flash"],"tags":["拍照","相机","闪光灯","闪光灯打开"],"emoji":"📸","text":"","type":1,"order":3405,"group":7,"subgroup":71,"version":1},{"annotation":"摄像机","name":"VIDEO CAMERA","hexcode":"1F4F9","shortcodes":["video_camera"],"tags":["录像","录影","拍摄","摄影机","视频"],"emoji":"📹️","text":"📹︎","type":1,"order":3406,"group":7,"subgroup":71,"version":0.6},{"annotation":"录像带","name":"VIDEOCASSETTE","hexcode":"1F4FC","shortcodes":["vhs"],"tags":["vhs","录影带","磁带"],"emoji":"📼","text":"","type":1,"order":3407,"group":7,"subgroup":71,"version":0.6},{"annotation":"左斜的放大镜","name":"LEFT-POINTING MAGNIFYING GLASS","hexcode":"1F50D","shortcodes":["mag"],"tags":["工具","搜索","放大","放大镜","查找"],"emoji":"🔍️","text":"🔍︎","type":1,"order":3408,"group":7,"subgroup":71,"version":0.6},{"annotation":"右斜的放大镜","name":"RIGHT-POINTING MAGNIFYING GLASS","hexcode":"1F50E","shortcodes":["mag_right"],"tags":["工具","搜索","放大","放大镜","查找"],"emoji":"🔎","text":"","type":1,"order":3409,"group":7,"subgroup":71,"version":0.6},{"annotation":"蜡烛","name":"CANDLE","hexcode":"1F56F","shortcodes":["candle"],"tags":["光","烛光","烛火","照明","燃烧"],"emoji":"🕯️","text":"🕯︎","type":0,"order":3411,"group":7,"subgroup":71,"version":0.7},{"annotation":"灯泡","name":"ELECTRIC LIGHT BULB","hexcode":"1F4A1","shortcodes":["bulb","light_bulb"],"tags":["主意","想法","电灯泡","白炽灯"],"emoji":"💡","text":"","type":1,"order":3412,"group":7,"subgroup":71,"version":0.6},{"annotation":"手电筒","name":"ELECTRIC TORCH","hexcode":"1F526","shortcodes":["flashlight"],"tags":["光","工具","手电","照明","电筒"],"emoji":"🔦","text":"","type":1,"order":3413,"group":7,"subgroup":71,"version":0.6},{"annotation":"红灯笼","name":"IZAKAYA LANTERN","hexcode":"1F3EE","shortcodes":["red_lantern"],"tags":["光","喜庆","灯笼","节日"],"emoji":"🏮","text":"","type":1,"order":3414,"group":7,"subgroup":71,"version":0.6},{"annotation":"印度油灯","name":"DIYA LAMP","hexcode":"1FA94","shortcodes":["diya_lamp"],"tags":["排灯节","油","灯","迪亚"],"emoji":"🪔","text":"","type":1,"order":3415,"group":7,"subgroup":71,"version":12},{"annotation":"精装笔记本","name":"NOTEBOOK WITH DECORATIVE COVER","hexcode":"1F4D4","shortcodes":["decorative_notebook"],"tags":["封面","本子","笔记","笔记本","记录"],"emoji":"📔","text":"","type":1,"order":3416,"group":7,"subgroup":72,"version":0.6},{"annotation":"合上的书本","name":"CLOSED BOOK","hexcode":"1F4D5","shortcodes":["closed_book"],"tags":["书","书本","合上"],"emoji":"📕","text":"","type":1,"order":3417,"group":7,"subgroup":72,"version":0.6},{"annotation":"打开的书本","name":"OPEN BOOK","hexcode":"1F4D6","shortcodes":["book"],"tags":["书","书本","打开","读书","阅读"],"emoji":"📖","text":"","type":1,"order":3418,"group":7,"subgroup":72,"version":0.6},{"annotation":"绿色书本","name":"GREEN BOOK","hexcode":"1F4D7","shortcodes":["green_book"],"tags":["书","书本","绿","绿色"],"emoji":"📗","text":"","type":1,"order":3419,"group":7,"subgroup":72,"version":0.6},{"annotation":"蓝色书本","name":"BLUE BOOK","hexcode":"1F4D8","shortcodes":["blue_book"],"tags":["书","书本","篮","蓝色"],"emoji":"📘","text":"","type":1,"order":3420,"group":7,"subgroup":72,"version":0.6},{"annotation":"橙色书本","name":"ORANGE BOOK","hexcode":"1F4D9","shortcodes":["orange_book"],"tags":["书","书本","橙色"],"emoji":"📙","text":"","type":1,"order":3421,"group":7,"subgroup":72,"version":0.6},{"annotation":"书","name":"BOOKS","hexcode":"1F4DA","shortcodes":["books"],"tags":["书本","书籍","图书","学习"],"emoji":"📚️","text":"📚︎","type":1,"order":3422,"group":7,"subgroup":72,"version":0.6},{"annotation":"笔记本","name":"NOTEBOOK","hexcode":"1F4D3","shortcodes":["notebook"],"tags":["日记本","本子","笔记","记事本","记录"],"emoji":"📓","text":"","type":1,"order":3423,"group":7,"subgroup":72,"version":0.6},{"annotation":"账本","name":"LEDGER","hexcode":"1F4D2","shortcodes":["ledger"],"tags":["笔记本","记事本","记账","账簿"],"emoji":"📒","text":"","type":1,"order":3424,"group":7,"subgroup":72,"version":0.6},{"annotation":"带卷边的页面","name":"PAGE WITH CURL","hexcode":"1F4C3","shortcodes":["page_curl"],"tags":["卷边","文书","文件","文档"],"emoji":"📃","text":"","type":1,"order":3425,"group":7,"subgroup":72,"version":0.6},{"annotation":"卷轴","name":"SCROLL","hexcode":"1F4DC","shortcodes":["scroll"],"tags":["画卷","纸","纸卷","羊皮纸"],"emoji":"📜","text":"","type":1,"order":3426,"group":7,"subgroup":72,"version":0.6},{"annotation":"文件","name":"PAGE FACING UP","hexcode":"1F4C4","shortcodes":["page_facing_up"],"tags":["文书","文档"],"emoji":"📄","text":"","type":1,"order":3427,"group":7,"subgroup":72,"version":0.6},{"annotation":"报纸","name":"NEWSPAPER","hexcode":"1F4F0","shortcodes":["newspaper"],"tags":["报道","新闻","看报","读报"],"emoji":"📰","text":"","type":1,"order":3428,"group":7,"subgroup":72,"version":0.6},{"annotation":"报纸卷","name":"ROLLED-UP NEWSPAPER","hexcode":"1F5DE","shortcodes":["rolled_newspaper"],"tags":["卷起","卷起的报纸","报纸","新闻","纸"],"emoji":"🗞️","text":"🗞︎","type":0,"order":3430,"group":7,"subgroup":72,"version":0.7},{"annotation":"标签页","name":"BOOKMARK TABS","hexcode":"1F4D1","shortcodes":["bookmark_tabs"],"tags":["书签","有书签的页面"],"emoji":"📑","text":"","type":1,"order":3431,"group":7,"subgroup":72,"version":0.6},{"annotation":"书签","name":"BOOKMARK","hexcode":"1F516","shortcodes":["bookmark"],"tags":["标签","读书","阅读"],"emoji":"🔖","text":"","type":1,"order":3432,"group":7,"subgroup":72,"version":0.6},{"annotation":"标签","name":"LABEL","hexcode":"1F3F7","shortcodes":["label"],"tags":["吊牌","标记","行李牌"],"emoji":"🏷️","text":"🏷︎","type":0,"order":3434,"group":7,"subgroup":72,"version":0.7},{"annotation":"钱袋","name":"MONEY BAG","hexcode":"1F4B0","shortcodes":["moneybag"],"tags":["美元","钱","钱包"],"emoji":"💰️","text":"💰︎","type":1,"order":3435,"group":7,"subgroup":73,"version":0.6},{"annotation":"硬币","name":"COIN","hexcode":"1FA99","shortcodes":["coin"],"tags":["财富","金","金属","钱","银"],"emoji":"🪙","text":"","type":1,"order":3436,"group":7,"subgroup":73,"version":13},{"annotation":"日元","name":"BANKNOTE WITH YEN SIGN","hexcode":"1F4B4","shortcodes":["yen"],"tags":["现金","货币","钞票","钱"],"emoji":"💴","text":"","type":1,"order":3437,"group":7,"subgroup":73,"version":0.6},{"annotation":"美元","name":"BANKNOTE WITH DOLLAR SIGN","hexcode":"1F4B5","shortcodes":["dollar"],"tags":["现金","纸币","货币","钱"],"emoji":"💵","text":"","type":1,"order":3438,"group":7,"subgroup":73,"version":0.6},{"annotation":"欧元","name":"BANKNOTE WITH EURO SIGN","hexcode":"1F4B6","shortcodes":["euro"],"tags":["现金","货币","钞票","钱"],"emoji":"💶","text":"","type":1,"order":3439,"group":7,"subgroup":73,"version":1},{"annotation":"英镑","name":"BANKNOTE WITH POUND SIGN","hexcode":"1F4B7","shortcodes":["pound"],"tags":["现金","货币","钞票","钱"],"emoji":"💷","text":"","type":1,"order":3440,"group":7,"subgroup":73,"version":1},{"annotation":"长翅膀的钱","name":"MONEY WITH WINGS","hexcode":"1F4B8","shortcodes":["money_wings"],"tags":["纸币","翅膀","花钱","钱"],"emoji":"💸","text":"","type":1,"order":3441,"group":7,"subgroup":73,"version":0.6},{"annotation":"信用卡","name":"CREDIT CARD","hexcode":"1F4B3","shortcodes":["credit_card"],"tags":["借记卡","刷卡","卡","贷记卡","银行卡"],"emoji":"💳️","text":"💳︎","type":1,"order":3442,"group":7,"subgroup":73,"version":0.6},{"annotation":"收据","name":"RECEIPT","hexcode":"1F9FE","shortcodes":["receipt"],"tags":["凭据","发票","记账","证明","账单"],"emoji":"🧾","text":"","type":1,"order":3443,"group":7,"subgroup":73,"version":11},{"annotation":"趋势向上且带有日元符号的图表","name":"CHART WITH UPWARDS TREND AND YEN SIGN","hexcode":"1F4B9","shortcodes":["ja_chart"],"tags":["上扬","上涨","日元汇率","货币升值图表","走势"],"emoji":"💹","text":"","type":1,"order":3444,"group":7,"subgroup":73,"version":0.6},{"annotation":"信封","name":"ENVELOPE","hexcode":"2709","shortcodes":["envelope"],"tags":["信件","信息","来信","邮件"],"emoji":"✉️","text":"✉︎","type":0,"order":3446,"group":7,"subgroup":74,"version":0.6},{"annotation":"电子邮件","name":"E-MAIL SYMBOL","hexcode":"1F4E7","shortcodes":["email"],"tags":["信封","邮件"],"emoji":"📧","text":"","type":1,"order":3447,"group":7,"subgroup":74,"version":0.6},{"annotation":"来信","name":"INCOMING ENVELOPE","hexcode":"1F4E8","shortcodes":["incoming_envelope"],"tags":["接收","收信","收到来信","收到邮件","电子邮件"],"emoji":"📨","text":"","type":1,"order":3448,"group":7,"subgroup":74,"version":0.6},{"annotation":"收邮件","name":"ENVELOPE WITH DOWNWARDS ARROW ABOVE","hexcode":"1F4E9","shortcodes":["envelope_arrow"],"tags":["信件","信封","发信","发出","发送","发邮件","邮件"],"emoji":"📩","text":"","type":1,"order":3449,"group":7,"subgroup":74,"version":0.6},{"annotation":"发件箱","name":"OUTBOX TRAY","hexcode":"1F4E4","shortcodes":["outbox_tray"],"tags":["信件","发信","发送","发邮件","邮件"],"emoji":"📤️","text":"📤︎","type":1,"order":3450,"group":7,"subgroup":74,"version":0.6},{"annotation":"收件箱","name":"INBOX TRAY","hexcode":"1F4E5","shortcodes":["inbox_tray"],"tags":["信件","接收","收信","收到邮件","邮件"],"emoji":"📥️","text":"📥︎","type":1,"order":3451,"group":7,"subgroup":74,"version":0.6},{"annotation":"包裹","name":"PACKAGE","hexcode":"1F4E6","shortcodes":["package"],"tags":["快递","盒子","箱子","装货","运送"],"emoji":"📦️","text":"📦︎","type":1,"order":3452,"group":7,"subgroup":74,"version":0.6},{"annotation":"有待收信件","name":"CLOSED MAILBOX WITH RAISED FLAG","hexcode":"1F4EB","shortcodes":["mailbox"],"tags":["信箱","旗标","有新信件"],"emoji":"📫️","text":"📫︎","type":1,"order":3453,"group":7,"subgroup":74,"version":0.6},{"annotation":"无待收信件","name":"CLOSED MAILBOX WITH LOWERED FLAG","hexcode":"1F4EA","shortcodes":["mailbox_closed"],"tags":["信箱","旗标","无新信件"],"emoji":"📪️","text":"📪︎","type":1,"order":3454,"group":7,"subgroup":74,"version":0.6},{"annotation":"有新信件","name":"OPEN MAILBOX WITH RAISED FLAG","hexcode":"1F4EC","shortcodes":["mailbox_mail"],"tags":["信箱","打开","旗标","有待收信件"],"emoji":"📬️","text":"📬︎","type":1,"order":3455,"group":7,"subgroup":74,"version":0.7},{"annotation":"无新信件","name":"OPEN MAILBOX WITH LOWERED FLAG","hexcode":"1F4ED","shortcodes":["mailbox_no_mail"],"tags":["信箱","旗标","无待收信件"],"emoji":"📭️","text":"📭︎","type":1,"order":3456,"group":7,"subgroup":74,"version":0.7},{"annotation":"邮筒","name":"POSTBOX","hexcode":"1F4EE","shortcodes":["postbox"],"tags":["信","寄信","邮箱"],"emoji":"📮","text":"","type":1,"order":3457,"group":7,"subgroup":74,"version":0.6},{"annotation":"投票箱","name":"BALLOT BOX WITH BALLOT","hexcode":"1F5F3","shortcodes":["ballot_box"],"tags":["投票","选举","选票"],"emoji":"🗳️","text":"🗳︎","type":0,"order":3459,"group":7,"subgroup":74,"version":0.7},{"annotation":"铅笔","name":"PENCIL","hexcode":"270F","shortcodes":["pencil"],"tags":["橡皮","橡皮擦","画画","画笔","笔","绘画"],"emoji":"✏️","text":"✏︎","type":0,"order":3461,"group":7,"subgroup":75,"version":0.6},{"annotation":"钢笔尖","name":"BLACK NIB","hexcode":"2712","shortcodes":["black_nib"],"tags":["写字","硬笔","笔尖","钢笔"],"emoji":"✒️","text":"✒︎","type":0,"order":3463,"group":7,"subgroup":75,"version":0.6},{"annotation":"钢笔","name":"LOWER LEFT FOUNTAIN PEN","hexcode":"1F58B","shortcodes":["fountain_pen"],"tags":["写字","硬笔","笔"],"emoji":"🖋️","text":"🖋︎","type":0,"order":3465,"group":7,"subgroup":75,"version":0.7},{"annotation":"笔","name":"LOWER LEFT BALLPOINT PEN","hexcode":"1F58A","shortcodes":["pen"],"tags":["原子笔","圆珠笔","油笔"],"emoji":"🖊️","text":"🖊︎","type":0,"order":3467,"group":7,"subgroup":75,"version":0.7},{"annotation":"画笔","name":"LOWER LEFT PAINTBRUSH","hexcode":"1F58C","shortcodes":["paintbrush"],"tags":["刷","毛笔","画刷","笔刷"],"emoji":"🖌️","text":"🖌︎","type":0,"order":3469,"group":7,"subgroup":75,"version":0.7},{"annotation":"蜡笔","name":"LOWER LEFT CRAYON","hexcode":"1F58D","shortcodes":["crayon"],"tags":["油画棒","画棒"],"emoji":"🖍️","text":"🖍︎","type":0,"order":3471,"group":7,"subgroup":75,"version":0.7},{"annotation":"备忘录","name":"MEMO","hexcode":"1F4DD","shortcodes":["memo"],"tags":["便条","便条簿","便笺"],"emoji":"📝","text":"","type":1,"order":3472,"group":7,"subgroup":75,"version":0.6},{"annotation":"公文包","name":"BRIEFCASE","hexcode":"1F4BC","shortcodes":["briefcase"],"tags":["公事包","包","手提包"],"emoji":"💼","text":"","type":1,"order":3473,"group":7,"subgroup":76,"version":0.6},{"annotation":"文件夹","name":"FILE FOLDER","hexcode":"1F4C1","shortcodes":["file_folder"],"tags":["办公","文件","文具","硬纸夹"],"emoji":"📁","text":"","type":1,"order":3474,"group":7,"subgroup":76,"version":0.6},{"annotation":"打开的文件夹","name":"OPEN FILE FOLDER","hexcode":"1F4C2","shortcodes":["open_file_folder"],"tags":["办公","打开","文件","文具"],"emoji":"📂","text":"","type":1,"order":3475,"group":7,"subgroup":76,"version":0.6},{"annotation":"索引分隔文件夹","name":"CARD INDEX DIVIDERS","hexcode":"1F5C2","shortcodes":["dividers"],"tags":["分隔","文件夹","索引"],"emoji":"🗂️","text":"🗂︎","type":0,"order":3477,"group":7,"subgroup":76,"version":0.7},{"annotation":"日历","name":"CALENDAR","hexcode":"1F4C5","shortcodes":["date","calendar"],"tags":["日期"],"emoji":"📅","text":"","type":1,"order":3478,"group":7,"subgroup":76,"version":0.6},{"annotation":"手撕日历","name":"TEAR-OFF CALENDAR","hexcode":"1F4C6","shortcodes":["torn_calendar"],"tags":["日历","日期"],"emoji":"📆","text":"","type":1,"order":3479,"group":7,"subgroup":76,"version":0.6},{"annotation":"线圈本","name":"SPIRAL NOTE PAD","hexcode":"1F5D2","shortcodes":["notepad_spiral"],"tags":["文具","笔记本","记事本"],"emoji":"🗒️","text":"🗒︎","type":0,"order":3481,"group":7,"subgroup":76,"version":0.7},{"annotation":"线圈日历","name":"SPIRAL CALENDAR PAD","hexcode":"1F5D3","shortcodes":["calendar_spiral"],"tags":["日历","日期","线圈"],"emoji":"🗓️","text":"🗓︎","type":0,"order":3483,"group":7,"subgroup":76,"version":0.7},{"annotation":"卡片索引","name":"CARD INDEX","hexcode":"1F4C7","shortcodes":["card_index"],"tags":["卡片","卡牌索引","目录","索引"],"emoji":"📇","text":"","type":1,"order":3484,"group":7,"subgroup":76,"version":0.6},{"annotation":"趋势向上的图表","name":"CHART WITH UPWARDS TREND","hexcode":"1F4C8","shortcodes":["chart_up"],"tags":["上升","上涨","上涨图表","向上","图表"],"emoji":"📈","text":"","type":1,"order":3485,"group":7,"subgroup":76,"version":0.6},{"annotation":"趋势向下的图表","name":"CHART WITH DOWNWARDS TREND","hexcode":"1F4C9","shortcodes":["chart_down"],"tags":["下跌","下跌图表","下降","向下","图表"],"emoji":"📉","text":"","type":1,"order":3486,"group":7,"subgroup":76,"version":0.6},{"annotation":"条形图","name":"BAR CHART","hexcode":"1F4CA","shortcodes":["bar_chart"],"tags":["图表","柱形图","直方图"],"emoji":"📊","text":"","type":1,"order":3487,"group":7,"subgroup":76,"version":0.6},{"annotation":"剪贴板","name":"CLIPBOARD","hexcode":"1F4CB","shortcodes":["clipboard"],"tags":["写字板","剪贴簿","夹子","纸张"],"emoji":"📋️","text":"📋︎","type":1,"order":3488,"group":7,"subgroup":76,"version":0.6},{"annotation":"图钉","name":"PUSHPIN","hexcode":"1F4CC","shortcodes":["pushpin"],"tags":["固定","按钉"],"emoji":"📌","text":"","type":1,"order":3489,"group":7,"subgroup":76,"version":0.6},{"annotation":"圆图钉","name":"ROUND PUSHPIN","hexcode":"1F4CD","shortcodes":["round_pushpin"],"tags":["固定","图钉"],"emoji":"📍","text":"","type":1,"order":3490,"group":7,"subgroup":76,"version":0.6},{"annotation":"回形针","name":"PAPERCLIP","hexcode":"1F4CE","shortcodes":["paperclip"],"tags":["万字夹","回纹针","曲别针","纸夹"],"emoji":"📎","text":"","type":1,"order":3491,"group":7,"subgroup":76,"version":0.6},{"annotation":"连起来的两个回形针","name":"LINKED PAPERCLIPS","hexcode":"1F587","shortcodes":["paperclips"],"tags":["万字夹","回形针","回纹针","曲别针","纸夹"],"emoji":"🖇️","text":"🖇︎","type":0,"order":3493,"group":7,"subgroup":76,"version":0.7},{"annotation":"直尺","name":"STRAIGHT RULER","hexcode":"1F4CF","shortcodes":["straight_ruler"],"tags":["尺","尺子","文具","测量","长度"],"emoji":"📏","text":"","type":1,"order":3494,"group":7,"subgroup":76,"version":0.6},{"annotation":"三角尺","name":"TRIANGULAR RULER","hexcode":"1F4D0","shortcodes":["triangular_ruler"],"tags":["三角","尺","文具","测量","角度"],"emoji":"📐","text":"","type":1,"order":3495,"group":7,"subgroup":76,"version":0.6},{"annotation":"剪刀","name":"BLACK SCISSORS","hexcode":"2702","shortcodes":["scissors"],"tags":["修剪","剪","剪子","剪裁","工具"],"emoji":"✂️","text":"✂︎","type":0,"order":3497,"group":7,"subgroup":76,"version":0.6},{"annotation":"卡片盒","name":"CARD FILE BOX","hexcode":"1F5C3","shortcodes":["card_box"],"tags":["存档","标签","档案","箱","索引"],"emoji":"🗃️","text":"🗃︎","type":0,"order":3499,"group":7,"subgroup":76,"version":0.7},{"annotation":"文件柜","name":"FILE CABINET","hexcode":"1F5C4","shortcodes":["file_cabinet"],"tags":["存档","归档","收纳","柜","档案"],"emoji":"🗄️","text":"🗄︎","type":0,"order":3501,"group":7,"subgroup":76,"version":0.7},{"annotation":"垃圾桶","name":"WASTEBASKET","hexcode":"1F5D1","shortcodes":["trashcan","wastebasket"],"tags":["垃圾","垃圾篓","废纸篓"],"emoji":"🗑️","text":"🗑︎","type":0,"order":3503,"group":7,"subgroup":76,"version":0.7},{"annotation":"合上的锁","name":"LOCK","hexcode":"1F512","shortcodes":["lock"],"tags":["上锁","锁","锁住","锁定"],"emoji":"🔒️","text":"🔒︎","type":1,"order":3504,"group":7,"subgroup":77,"version":0.6},{"annotation":"打开的锁","name":"OPEN LOCK","hexcode":"1F513","shortcodes":["unlock"],"tags":["取消锁定","开锁","解锁","锁"],"emoji":"🔓️","text":"🔓︎","type":1,"order":3505,"group":7,"subgroup":77,"version":0.6},{"annotation":"墨水笔和锁","name":"LOCK WITH INK PEN","hexcode":"1F50F","shortcodes":["locked_pen"],"tags":["笔","笔尖","钢笔","锁","隐私"],"emoji":"🔏","text":"","type":1,"order":3506,"group":7,"subgroup":77,"version":0.6},{"annotation":"钥匙和锁","name":"CLOSED LOCK WITH KEY","hexcode":"1F510","shortcodes":["locked_key"],"tags":["安全","钥匙","锁","锁上"],"emoji":"🔐","text":"","type":1,"order":3507,"group":7,"subgroup":77,"version":0.6},{"annotation":"钥匙","name":"KEY","hexcode":"1F511","shortcodes":["key"],"tags":["密码","密钥","开锁","解锁"],"emoji":"🔑","text":"","type":1,"order":3508,"group":7,"subgroup":77,"version":0.6},{"annotation":"老式钥匙","name":"OLD KEY","hexcode":"1F5DD","shortcodes":["old_key"],"tags":["古老的钥匙","旧钥匙","钥匙"],"emoji":"🗝️","text":"🗝︎","type":0,"order":3510,"group":7,"subgroup":77,"version":0.7},{"annotation":"锤子","name":"HAMMER","hexcode":"1F528","shortcodes":["hammer"],"tags":["工具","敲","施工","砸","铁锤"],"emoji":"🔨","text":"","type":1,"order":3511,"group":7,"subgroup":78,"version":0.6},{"annotation":"斧头","name":"AXE","hexcode":"1FA93","shortcodes":["axe"],"tags":["切","劈","木头","砍"],"emoji":"🪓","text":"","type":1,"order":3512,"group":7,"subgroup":78,"version":12},{"annotation":"铁镐","name":"PICK","hexcode":"26CF","shortcodes":["pick"],"tags":["工具","挖掘","采矿","锄头","鹤嘴锄"],"emoji":"⛏️","text":"⛏︎","type":0,"order":3514,"group":7,"subgroup":78,"version":0.7},{"annotation":"锤子与镐","name":"HAMMER AND PICK","hexcode":"2692","shortcodes":["hammer_pick"],"tags":["工具","铁锤","铁镐","锤子","镐子"],"emoji":"⚒️","text":"⚒︎","type":0,"order":3516,"group":7,"subgroup":78,"version":1},{"annotation":"锤子与扳手","name":"HAMMER AND WRENCH","hexcode":"1F6E0","shortcodes":["tools","hammer_wrench"],"tags":["工具","扳手","铁锤","锤子"],"emoji":"🛠️","text":"🛠︎","type":0,"order":3518,"group":7,"subgroup":78,"version":0.7},{"annotation":"匕首","name":"DAGGER KNIFE","hexcode":"1F5E1","shortcodes":["dagger"],"tags":["武器","短刀"],"emoji":"🗡️","text":"🗡︎","type":0,"order":3520,"group":7,"subgroup":78,"version":0.7},{"annotation":"交叉放置的剑","name":"CROSSED SWORDS","hexcode":"2694","shortcodes":["crossed_swords"],"tags":["交叉","剑","双剑"],"emoji":"⚔️","text":"⚔︎","type":0,"order":3522,"group":7,"subgroup":78,"version":1},{"annotation":"手枪","name":"PISTOL","hexcode":"1F52B","shortcodes":["gun","pistol"],"tags":["工具","左轮","枪","武器"],"emoji":"🔫","text":"","type":1,"order":3523,"group":7,"subgroup":78,"version":0.6},{"annotation":"回旋镖","name":"BOOMERANG","hexcode":"1FA83","shortcodes":["boomerang"],"tags":["反弹","回弹","澳大利亚"],"emoji":"🪃","text":"","type":1,"order":3524,"group":7,"subgroup":78,"version":13},{"annotation":"弓和箭","name":"BOW AND ARROW","hexcode":"1F3F9","shortcodes":["bow"],"tags":["射手","射箭","弓","箭"],"emoji":"🏹","text":"","type":1,"order":3525,"group":7,"subgroup":78,"version":1},{"annotation":"盾牌","name":"SHIELD","hexcode":"1F6E1","shortcodes":["shield"],"tags":["武器","盾","防御"],"emoji":"🛡️","text":"🛡︎","type":0,"order":3527,"group":7,"subgroup":78,"version":0.7},{"annotation":"木工锯","name":"CARPENTRY SAW","hexcode":"1FA9A","shortcodes":["saw"],"tags":["工具","木匠","木材","锯"],"emoji":"🪚","text":"","type":1,"order":3528,"group":7,"subgroup":78,"version":13},{"annotation":"扳手","name":"WRENCH","hexcode":"1F527","shortcodes":["wrench"],"tags":["工具","螺丝扳手"],"emoji":"🔧","text":"","type":1,"order":3529,"group":7,"subgroup":78,"version":0.6},{"annotation":"螺丝刀","name":"SCREWDRIVER","hexcode":"1FA9B","shortcodes":["screwdriver"],"tags":["工具","螺丝"],"emoji":"🪛","text":"","type":1,"order":3530,"group":7,"subgroup":78,"version":13},{"annotation":"螺母与螺栓","name":"NUT AND BOLT","hexcode":"1F529","shortcodes":["nut_and_bolt"],"tags":["工具","螺丝","螺帽","螺栓","螺母"],"emoji":"🔩","text":"","type":1,"order":3531,"group":7,"subgroup":78,"version":0.6},{"annotation":"齿轮","name":"GEAR","hexcode":"2699","shortcodes":["gear"],"tags":["传动","工具","机械","零件"],"emoji":"⚙️","text":"⚙︎","type":0,"order":3533,"group":7,"subgroup":78,"version":1},{"annotation":"夹钳","name":"COMPRESSION","hexcode":"1F5DC","shortcodes":["clamp","compression"],"tags":["夹具","工具","机械","紧固"],"emoji":"🗜️","text":"🗜︎","type":0,"order":3535,"group":7,"subgroup":78,"version":0.7},{"annotation":"天平","name":"SCALES","hexcode":"2696","shortcodes":["scales"],"tags":["公平","公正","正义","法律"],"emoji":"⚖️","text":"⚖︎","type":0,"order":3537,"group":7,"subgroup":78,"version":1},{"annotation":"盲杖","name":"PROBING CANE","hexcode":"1F9AF","shortcodes":["probing_cane"],"tags":["拐杖","无障碍","盲"],"emoji":"🦯","text":"","type":1,"order":3538,"group":7,"subgroup":78,"version":12},{"annotation":"链接","name":"LINK SYMBOL","hexcode":"1F517","shortcodes":["link"],"tags":["网址","链条","锁链"],"emoji":"🔗","text":"","type":1,"order":3539,"group":7,"subgroup":78,"version":0.6},{"annotation":"链条","name":"CHAINS","hexcode":"26D3","shortcodes":["chains"],"tags":["铁链","链","锁链"],"emoji":"⛓️","text":"⛓︎","type":0,"order":3541,"group":7,"subgroup":78,"version":0.7},{"annotation":"挂钩","name":"HOOK","hexcode":"1FA9D","shortcodes":["hook"],"tags":["卖点","抓","曲线","钩状物"],"emoji":"🪝","text":"","type":1,"order":3542,"group":7,"subgroup":78,"version":13},{"annotation":"工具箱","name":"TOOLBOX","hexcode":"1F9F0","shortcodes":["toolbox"],"tags":["工具","机修","箱子"],"emoji":"🧰","text":"","type":1,"order":3543,"group":7,"subgroup":78,"version":11},{"annotation":"磁铁","name":"MAGNET","hexcode":"1F9F2","shortcodes":["magnet"],"tags":["吸引力","磁性","马蹄铁"],"emoji":"🧲","text":"","type":1,"order":3544,"group":7,"subgroup":78,"version":11},{"annotation":"梯子","name":"LADDER","hexcode":"1FA9C","shortcodes":["ladder"],"tags":["台阶","梯级","横档","爬"],"emoji":"🪜","text":"","type":1,"order":3545,"group":7,"subgroup":78,"version":13},{"annotation":"蒸馏器","name":"ALEMBIC","hexcode":"2697","shortcodes":["alembic"],"tags":["净化","化学","实验","工具"],"emoji":"⚗️","text":"⚗︎","type":0,"order":3547,"group":7,"subgroup":79,"version":1},{"annotation":"试管","name":"TEST TUBE","hexcode":"1F9EA","shortcodes":["test_tube"],"tags":["化学","化学家","实验","实验室","科学"],"emoji":"🧪","text":"","type":1,"order":3548,"group":7,"subgroup":79,"version":11},{"annotation":"培养皿","name":"PETRI DISH","hexcode":"1F9EB","shortcodes":["petri_dish"],"tags":["培养","实验室","生物学","生物学家","细菌"],"emoji":"🧫","text":"","type":1,"order":3549,"group":7,"subgroup":79,"version":11},{"annotation":"DNA","name":"DNA DOUBLE HELIX","hexcode":"1F9EC","shortcodes":["dna","double_helix"],"tags":["dna","基因","生命","生物学家","进化","遗传学"],"emoji":"🧬","text":"","type":1,"order":3550,"group":7,"subgroup":79,"version":11},{"annotation":"显微镜","name":"MICROSCOPE","hexcode":"1F52C","shortcodes":["microscope"],"tags":["实验","工具","生物","科学","细胞"],"emoji":"🔬","text":"","type":1,"order":3551,"group":7,"subgroup":79,"version":1},{"annotation":"望远镜","name":"TELESCOPE","hexcode":"1F52D","shortcodes":["telescope"],"tags":["天体","天文","天文学","工具","观星"],"emoji":"🔭","text":"","type":1,"order":3552,"group":7,"subgroup":79,"version":1},{"annotation":"卫星天线","name":"SATELLITE ANTENNA","hexcode":"1F4E1","shortcodes":["satellite_antenna"],"tags":["信号接收","卫星","卫星接收天线","卫星碟形天线","天线"],"emoji":"📡","text":"","type":1,"order":3553,"group":7,"subgroup":79,"version":0.6},{"annotation":"注射器","name":"SYRINGE","hexcode":"1F489","shortcodes":["syringe"],"tags":["医学","打针","治疗","针头","针筒"],"emoji":"💉","text":"","type":1,"order":3554,"group":7,"subgroup":80,"version":0.6},{"annotation":"血滴","name":"DROP OF BLOOD","hexcode":"1FA78","shortcodes":["blood_drop"],"tags":["医疗","月经","献血","经血","输血"],"emoji":"🩸","text":"","type":1,"order":3555,"group":7,"subgroup":80,"version":12},{"annotation":"药丸","name":"PILL","hexcode":"1F48A","shortcodes":["pill"],"tags":["吃药","治疗","药","药物"],"emoji":"💊","text":"","type":1,"order":3556,"group":7,"subgroup":80,"version":0.6},{"annotation":"创可贴","name":"ADHESIVE BANDAGE","hexcode":"1FA79","shortcodes":["bandaid","adhesive_bandage"],"tags":["ok绷","伤口","绷带","胶布"],"emoji":"🩹","text":"","type":1,"order":3557,"group":7,"subgroup":80,"version":12},{"annotation":"听诊器","name":"STETHOSCOPE","hexcode":"1FA7A","shortcodes":["stethoscope"],"tags":["医生","医疗","心脏","心跳","诊断"],"emoji":"🩺","text":"","type":1,"order":3558,"group":7,"subgroup":80,"version":12},{"annotation":"门","name":"DOOR","hexcode":"1F6AA","shortcodes":["door"],"tags":["出入口","大门","屋门","房门","房间"],"emoji":"🚪","text":"","type":1,"order":3559,"group":7,"subgroup":81,"version":0.6},{"annotation":"电梯","name":"ELEVATOR","hexcode":"1F6D7","shortcodes":["elevator"],"tags":["升降机","可达性"],"emoji":"🛗","text":"","type":1,"order":3560,"group":7,"subgroup":81,"version":13},{"annotation":"镜子","name":"MIRROR","hexcode":"1FA9E","shortcodes":["mirror"],"tags":["反射","反射镜","窥镜"],"emoji":"🪞","text":"","type":1,"order":3561,"group":7,"subgroup":81,"version":13},{"annotation":"窗户","name":"WINDOW","hexcode":"1FA9F","shortcodes":["window"],"tags":["开窗","新鲜空气","景色","窗框","透明"],"emoji":"🪟","text":"","type":1,"order":3562,"group":7,"subgroup":81,"version":13},{"annotation":"床","name":"BED","hexcode":"1F6CF","shortcodes":["bed"],"tags":["宾馆","床垫","床铺","睡眠","睡觉"],"emoji":"🛏️","text":"🛏︎","type":0,"order":3564,"group":7,"subgroup":81,"version":0.7},{"annotation":"沙发和灯","name":"COUCH AND LAMP","hexcode":"1F6CB","shortcodes":["couch"],"tags":["家","沙发","灯","阅读"],"emoji":"🛋️","text":"🛋︎","type":0,"order":3566,"group":7,"subgroup":81,"version":0.7},{"annotation":"椅子","name":"CHAIR","hexcode":"1FA91","shortcodes":["chair"],"tags":["坐","座位","椅背"],"emoji":"🪑","text":"","type":1,"order":3567,"group":7,"subgroup":81,"version":12},{"annotation":"马桶","name":"TOILET","hexcode":"1F6BD","shortcodes":["toilet"],"tags":["wc","卫生间","厕所","洗手间"],"emoji":"🚽","text":"","type":1,"order":3568,"group":7,"subgroup":81,"version":0.6},{"annotation":"活塞","name":"PLUNGER","hexcode":"1FAA0","shortcodes":["plunger"],"tags":["吸力","水管工","马桶"],"emoji":"🪠","text":"","type":1,"order":3569,"group":7,"subgroup":81,"version":13},{"annotation":"淋浴","name":"SHOWER","hexcode":"1F6BF","shortcodes":["shower"],"tags":["喷头","喷水","水","洗澡 花洒"],"emoji":"🚿","text":"","type":1,"order":3570,"group":7,"subgroup":81,"version":1},{"annotation":"浴缸","name":"BATHTUB","hexcode":"1F6C1","shortcodes":["bathtub"],"tags":["沐浴","泡沫浴","泡澡","洗澡","澡盆"],"emoji":"🛁","text":"","type":1,"order":3571,"group":7,"subgroup":81,"version":1},{"annotation":"捕鼠器","name":"MOUSE TRAP","hexcode":"1FAA4","shortcodes":["mouse_trap"],"tags":["诱饵","陷进"],"emoji":"🪤","text":"","type":1,"order":3572,"group":7,"subgroup":81,"version":13},{"annotation":"剃须刀","name":"RAZOR","hexcode":"1FA92","shortcodes":["razor"],"tags":["刀","刮","毛","胡子","锋利"],"emoji":"🪒","text":"","type":1,"order":3573,"group":7,"subgroup":81,"version":12},{"annotation":"乳液瓶","name":"LOTION BOTTLE","hexcode":"1F9F4","shortcodes":["lotion"],"tags":["乳液","护肤霜","洗发水","防晒霜"],"emoji":"🧴","text":"","type":1,"order":3574,"group":7,"subgroup":81,"version":11},{"annotation":"安全别针","name":"SAFETY PIN","hexcode":"1F9F7","shortcodes":["safety_pin"],"tags":["别针","扣针"],"emoji":"🧷","text":"","type":1,"order":3575,"group":7,"subgroup":81,"version":11},{"annotation":"扫帚","name":"BROOM","hexcode":"1F9F9","shortcodes":["broom"],"tags":["女巫","打扫","扫地"],"emoji":"🧹","text":"","type":1,"order":3576,"group":7,"subgroup":81,"version":11},{"annotation":"筐","name":"BASKET","hexcode":"1F9FA","shortcodes":["basket"],"tags":["农作","脏衣篮","野餐"],"emoji":"🧺","text":"","type":1,"order":3577,"group":7,"subgroup":81,"version":11},{"annotation":"卷纸","name":"ROLL OF PAPER","hexcode":"1F9FB","shortcodes":["toilet_paper"],"tags":["卫生纸","纸巾"],"emoji":"🧻","text":"","type":1,"order":3578,"group":7,"subgroup":81,"version":11},{"annotation":"桶","name":"BUCKET","hexcode":"1FAA3","shortcodes":["bucket"],"tags":["大桶","木桶","水桶","缸"],"emoji":"🪣","text":"","type":1,"order":3579,"group":7,"subgroup":81,"version":13},{"annotation":"皂","name":"BAR OF SOAP","hexcode":"1F9FC","shortcodes":["soap"],"tags":["杀菌","洗手","清洁","肥皂泡","肥皂盒"],"emoji":"🧼","text":"","type":1,"order":3580,"group":7,"subgroup":81,"version":11},{"annotation":"牙刷","name":"TOOTHBRUSH","hexcode":"1FAA5","shortcodes":["toothbrush"],"tags":["刷","卫生","情节","浴室","牙科","牙齿"],"emoji":"🪥","text":"","type":1,"order":3581,"group":7,"subgroup":81,"version":13},{"annotation":"海绵","name":"SPONGE","hexcode":"1F9FD","shortcodes":["sponge"],"tags":["吸水","清洁","渗透"],"emoji":"🧽","text":"","type":1,"order":3582,"group":7,"subgroup":81,"version":11},{"annotation":"灭火器","name":"FIRE EXTINGUISHER","hexcode":"1F9EF","shortcodes":["fire_extinguisher"],"tags":["火灾","灭火"],"emoji":"🧯","text":"","type":1,"order":3583,"group":7,"subgroup":81,"version":11},{"annotation":"购物车","name":"SHOPPING TROLLEY","hexcode":"1F6D2","shortcodes":["shopping_cart"],"tags":["手推车","采购"],"emoji":"🛒","text":"","type":1,"order":3584,"group":7,"subgroup":81,"version":3},{"annotation":"香烟","name":"SMOKING SYMBOL","hexcode":"1F6AC","shortcodes":["cigarette","smoking"],"tags":["卷烟","吸烟","抽烟","烟","烟草"],"emoji":"🚬","text":"","type":1,"order":3585,"group":7,"subgroup":82,"version":0.6},{"annotation":"棺材","name":"COFFIN","hexcode":"26B0","shortcodes":["coffin"],"tags":["埋葬","死亡","灵柩","葬礼","陵墓"],"emoji":"⚰️","text":"⚰︎","type":0,"order":3587,"group":7,"subgroup":82,"version":1},{"annotation":"墓碑","name":"HEADSTONE","hexcode":"1FAA6","shortcodes":["headstone"],"tags":["公墓","墓园","墓地"],"emoji":"🪦","text":"","type":1,"order":3588,"group":7,"subgroup":82,"version":13},{"annotation":"骨灰缸","name":"FUNERAL URN","hexcode":"26B1","shortcodes":["urn"],"tags":["瓮","缸","葬礼"],"emoji":"⚱️","text":"⚱︎","type":0,"order":3590,"group":7,"subgroup":82,"version":1},{"annotation":"摩埃","name":"MOYAI","hexcode":"1F5FF","shortcodes":["moai"],"tags":["复活岛","复活节岛","复活节岛石像","摩艾","摩艾石像","毛埃"],"emoji":"🗿","text":"","type":1,"order":3591,"group":7,"subgroup":82,"version":0.6},{"annotation":"标语牌","name":"PLACARD","hexcode":"1FAA7","shortcodes":["placard"],"tags":["布告","标志","海报","示威","纠察队标语牌","警戒哨"],"emoji":"🪧","text":"","type":1,"order":3592,"group":7,"subgroup":82,"version":13},{"annotation":"取款机","name":"AUTOMATED TELLER MACHINE","hexcode":"1F3E7","shortcodes":["atm"],"tags":["柜员机","标识","银行"],"emoji":"🏧","text":"","type":1,"order":3593,"group":8,"subgroup":83,"version":0.6},{"annotation":"倒垃圾","name":"PUT LITTER IN ITS PLACE SYMBOL","hexcode":"1F6AE","shortcodes":["litter_bin"],"tags":["垃圾丢弃处","垃圾入篓"],"emoji":"🚮","text":"","type":1,"order":3594,"group":8,"subgroup":83,"version":1},{"annotation":"饮用水","name":"POTABLE WATER SYMBOL","hexcode":"1F6B0","shortcodes":["potable_water"],"tags":["喝水","接水","水","水龙头"],"emoji":"🚰","text":"","type":1,"order":3595,"group":8,"subgroup":83,"version":1},{"annotation":"轮椅标识","name":"WHEELCHAIR SYMBOL","hexcode":"267F","shortcodes":["handicapped"],"tags":["无障碍","残疾","残障","轮椅","轮椅符号"],"emoji":"♿️","text":"♿︎","type":1,"order":3596,"group":8,"subgroup":83,"version":0.6},{"annotation":"男厕","name":"MENS SYMBOL","hexcode":"1F6B9","shortcodes":["mens"],"tags":["卫生间","厕所","洗手间","男士"],"emoji":"🚹️","text":"🚹︎","type":1,"order":3597,"group":8,"subgroup":83,"version":0.6},{"annotation":"女厕","name":"WOMENS SYMBOL","hexcode":"1F6BA","shortcodes":["womens"],"tags":["卫生间","厕所","女士","洗手间"],"emoji":"🚺️","text":"🚺︎","type":1,"order":3598,"group":8,"subgroup":83,"version":0.6},{"annotation":"卫生间","name":"RESTROOM","hexcode":"1F6BB","shortcodes":["restroom","bathroom"],"tags":["厕所","洗手间"],"emoji":"🚻","text":"","type":1,"order":3599,"group":8,"subgroup":83,"version":0.6},{"annotation":"宝宝","name":"BABY SYMBOL","hexcode":"1F6BC","shortcodes":["baby_symbol"],"tags":["婴儿","母婴室"],"emoji":"🚼️","text":"🚼︎","type":1,"order":3600,"group":8,"subgroup":83,"version":0.6},{"annotation":"厕所","name":"WATER CLOSET","hexcode":"1F6BE","shortcodes":["wc"],"tags":["卫生间","洗手间","盥洗室"],"emoji":"🚾","text":"","type":1,"order":3601,"group":8,"subgroup":83,"version":0.6},{"annotation":"护照检查","name":"PASSPORT CONTROL","hexcode":"1F6C2","shortcodes":["passport_control"],"tags":["安检","检查","通行证"],"emoji":"🛂","text":"","type":1,"order":3602,"group":8,"subgroup":83,"version":1},{"annotation":"海关","name":"CUSTOMS","hexcode":"1F6C3","shortcodes":["customs"],"tags":["海关"],"emoji":"🛃","text":"","type":1,"order":3603,"group":8,"subgroup":83,"version":1},{"annotation":"提取行李","name":"BAGGAGE CLAIM","hexcode":"1F6C4","shortcodes":["baggage_claim"],"tags":["提取","行李"],"emoji":"🛄","text":"","type":1,"order":3604,"group":8,"subgroup":83,"version":1},{"annotation":"寄存行李","name":"LEFT LUGGAGE","hexcode":"1F6C5","shortcodes":["left_luggage"],"tags":["寄存","行李"],"emoji":"🛅","text":"","type":1,"order":3605,"group":8,"subgroup":83,"version":1},{"annotation":"警告","name":"WARNING SIGN","hexcode":"26A0","shortcodes":["warning"],"tags":["警告"],"emoji":"⚠️","text":"⚠︎","type":0,"order":3607,"group":8,"subgroup":84,"version":0.6},{"annotation":"儿童过街","name":"CHILDREN CROSSING","hexcode":"1F6B8","shortcodes":["children_crossing"],"tags":["交通","安全","指示牌","行人"],"emoji":"🚸","text":"","type":1,"order":3608,"group":8,"subgroup":84,"version":1},{"annotation":"禁止通行","name":"NO ENTRY","hexcode":"26D4","shortcodes":["no_entry"],"tags":["交通","请勿入内","请勿驶入"],"emoji":"⛔️","text":"⛔︎","type":1,"order":3609,"group":8,"subgroup":84,"version":0.6},{"annotation":"禁止","name":"NO ENTRY SIGN","hexcode":"1F6AB","shortcodes":["no_entry_sign"],"tags":["不准","不许","严禁","阻止"],"emoji":"🚫","text":"","type":1,"order":3610,"group":8,"subgroup":84,"version":0.6},{"annotation":"禁止自行车","name":"NO BICYCLES","hexcode":"1F6B3","shortcodes":["no_bicycles"],"tags":["严禁","交通","非机动车"],"emoji":"🚳","text":"","type":1,"order":3611,"group":8,"subgroup":84,"version":1},{"annotation":"禁止吸烟","name":"NO SMOKING SYMBOL","hexcode":"1F6AD","shortcodes":["no_smoking"],"tags":["严禁","抽烟"],"emoji":"🚭️","text":"🚭︎","type":1,"order":3612,"group":8,"subgroup":84,"version":0.6},{"annotation":"禁止乱扔垃圾","name":"DO NOT LITTER SYMBOL","hexcode":"1F6AF","shortcodes":["do_not_litter"],"tags":["严禁","垃圾"],"emoji":"🚯","text":"","type":1,"order":3613,"group":8,"subgroup":84,"version":1},{"annotation":"非饮用水","name":"NON-POTABLE WATER SYMBOL","hexcode":"1F6B1","shortcodes":["non_potable_water"],"tags":["水","非直饮水"],"emoji":"🚱","text":"","type":1,"order":3614,"group":8,"subgroup":84,"version":1},{"annotation":"禁止行人通行","name":"NO PEDESTRIANS","hexcode":"1F6B7","shortcodes":["no_pedestrians"],"tags":["严禁","行人"],"emoji":"🚷","text":"","type":1,"order":3615,"group":8,"subgroup":84,"version":1},{"annotation":"禁止使用手机","name":"NO MOBILE PHONES","hexcode":"1F4F5","shortcodes":["no_mobile_phones"],"tags":["严禁","电话"],"emoji":"📵","text":"","type":1,"order":3616,"group":8,"subgroup":84,"version":1},{"annotation":"18禁","name":"NO ONE UNDER EIGHTEEN SYMBOL","hexcode":"1F51E","shortcodes":["underage"],"tags":["未成年人不宜","禁止"],"emoji":"🔞","text":"","type":1,"order":3617,"group":8,"subgroup":84,"version":0.6},{"annotation":"辐射","name":"RADIOACTIVE SIGN","hexcode":"2622","shortcodes":["radioactive"],"tags":["放射性","标识"],"emoji":"☢️","text":"☢︎","type":0,"order":3619,"group":8,"subgroup":84,"version":1},{"annotation":"生物危害","name":"BIOHAZARD SIGN","hexcode":"2623","shortcodes":["biohazard"],"tags":["动物","当心感染"],"emoji":"☣️","text":"☣︎","type":0,"order":3621,"group":8,"subgroup":84,"version":1},{"annotation":"向上箭头","name":"UPWARDS BLACK ARROW","hexcode":"2B06","shortcodes":["arrow_up"],"tags":["北","方向","标识"],"emoji":"⬆️","text":"⬆︎","type":0,"order":3623,"group":8,"subgroup":85,"version":0.6},{"annotation":"右上箭头","name":"NORTH EAST ARROW","hexcode":"2197","shortcodes":["arrow_upper_right"],"tags":["东北","方向","标识"],"emoji":"↗️","text":"↗︎","type":0,"order":3625,"group":8,"subgroup":85,"version":0.6},{"annotation":"向右箭头","name":"BLACK RIGHTWARDS ARROW","hexcode":"27A1","shortcodes":["arrow_right"],"tags":["东","方向","标识"],"emoji":"➡️","text":"➡︎","type":0,"order":3627,"group":8,"subgroup":85,"version":0.6},{"annotation":"右下箭头","name":"SOUTH EAST ARROW","hexcode":"2198","shortcodes":["arrow_lower_right"],"tags":["东南","方向","标识"],"emoji":"↘️","text":"↘︎","type":0,"order":3629,"group":8,"subgroup":85,"version":0.6},{"annotation":"向下箭头","name":"DOWNWARDS BLACK ARROW","hexcode":"2B07","shortcodes":["arrow_down"],"tags":["向下","基本","方位","正南","箭头"],"emoji":"⬇️","text":"⬇︎","type":0,"order":3631,"group":8,"subgroup":85,"version":0.6},{"annotation":"左下箭头","name":"SOUTH WEST ARROW","hexcode":"2199","shortcodes":["arrow_lower_left"],"tags":["方向","标识","西南"],"emoji":"↙️","text":"↙︎","type":0,"order":3633,"group":8,"subgroup":85,"version":0.6},{"annotation":"向左箭头","name":"LEFTWARDS BLACK ARROW","hexcode":"2B05","shortcodes":["arrow_left"],"tags":["方向","标识","西"],"emoji":"⬅️","text":"⬅︎","type":0,"order":3635,"group":8,"subgroup":85,"version":0.6},{"annotation":"左上箭头","name":"NORTH WEST ARROW","hexcode":"2196","shortcodes":["arrow_upper_left"],"tags":["方向","标识","西北"],"emoji":"↖️","text":"↖︎","type":0,"order":3637,"group":8,"subgroup":85,"version":0.6},{"annotation":"上下箭头","name":"UP DOWN ARROW","hexcode":"2195","shortcodes":["arrow_up_down"],"tags":["上下","箭头"],"emoji":"↕️","text":"↕︎","type":0,"order":3639,"group":8,"subgroup":85,"version":0.6},{"annotation":"左右箭头","name":"LEFT RIGHT ARROW","hexcode":"2194","shortcodes":["arrow_left_right"],"tags":["左右","箭头"],"emoji":"↔️","text":"↔︎","type":0,"order":3641,"group":8,"subgroup":85,"version":0.6},{"annotation":"右转弯箭头","name":"LEFTWARDS ARROW WITH HOOK","hexcode":"21A9","shortcodes":["arrow_left_hook"],"tags":["右转弯","向左弯曲的右箭头","箭头"],"emoji":"↩️","text":"↩︎","type":0,"order":3643,"group":8,"subgroup":85,"version":0.6},{"annotation":"左转弯箭头","name":"RIGHTWARDS ARROW WITH HOOK","hexcode":"21AA","shortcodes":["arrow_right_hook"],"tags":["向右弯曲的左箭头","左转弯","箭头"],"emoji":"↪️","text":"↪︎","type":0,"order":3645,"group":8,"subgroup":85,"version":0.6},{"annotation":"右上弯箭头","name":"ARROW POINTING RIGHTWARDS THEN CURVING UPWARDS","hexcode":"2934","shortcodes":["arrow_heading_up"],"tags":["右上弯","向上弯曲的右箭头","箭头"],"emoji":"⤴️","text":"⤴︎","type":0,"order":3647,"group":8,"subgroup":85,"version":0.6},{"annotation":"右下弯箭头","name":"ARROW POINTING RIGHTWARDS THEN CURVING DOWNWARDS","hexcode":"2935","shortcodes":["arrow_heading_down"],"tags":["右下弯","向下弯曲的右箭头","箭头"],"emoji":"⤵️","text":"⤵︎","type":0,"order":3649,"group":8,"subgroup":85,"version":0.6},{"annotation":"顺时针垂直箭头","name":"CLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS","hexcode":"1F503","shortcodes":["clockwise"],"tags":["方向","标识","重新载入"],"emoji":"🔃","text":"","type":1,"order":3650,"group":8,"subgroup":85,"version":0.6},{"annotation":"逆时针箭头按钮","name":"ANTICLOCKWISE DOWNWARDS AND UPWARDS OPEN CIRCLE ARROWS","hexcode":"1F504","shortcodes":["counter_clockwise"],"tags":["箭头","逆时针","逆时针箭头"],"emoji":"🔄","text":"","type":1,"order":3651,"group":8,"subgroup":85,"version":1},{"annotation":"返回箭头","name":"BACK WITH LEFTWARDS ARROW ABOVE","hexcode":"1F519","shortcodes":["back"],"tags":["回退","箭头","返回"],"emoji":"🔙","text":"","type":1,"order":3652,"group":8,"subgroup":85,"version":0.6},{"annotation":"结束箭头","name":"END WITH LEFTWARDS ARROW ABOVE","hexcode":"1F51A","shortcodes":["end"],"tags":["箭头","结束"],"emoji":"🔚","text":"","type":1,"order":3653,"group":8,"subgroup":85,"version":0.6},{"annotation":"ON! 箭头","name":"ON WITH EXCLAMATION MARK WITH LEFT RIGHT ARROW ABOVE","hexcode":"1F51B","shortcodes":["on"],"tags":["on","on! 箭头","开始","标识","箭头"],"emoji":"🔛","text":"","type":1,"order":3654,"group":8,"subgroup":85,"version":0.6},{"annotation":"SOON 箭头","name":"SOON WITH RIGHTWARDS ARROW ABOVE","hexcode":"1F51C","shortcodes":["soon"],"tags":["soon 箭头","箭头","马上"],"emoji":"🔜","text":"","type":1,"order":3655,"group":8,"subgroup":85,"version":0.6},{"annotation":"置顶","name":"TOP WITH UPWARDS ARROW ABOVE","hexcode":"1F51D","shortcodes":["top"],"tags":["向上","标识"],"emoji":"🔝","text":"","type":1,"order":3656,"group":8,"subgroup":85,"version":0.6},{"annotation":"宗教场所","name":"PLACE OF WORSHIP","hexcode":"1F6D0","shortcodes":["place_of_worship"],"tags":["地点","礼拜","祈祷"],"emoji":"🛐","text":"","type":1,"order":3657,"group":8,"subgroup":86,"version":1},{"annotation":"原子符号","name":"ATOM SYMBOL","hexcode":"269B","shortcodes":["atom"],"tags":["无神论","物质"],"emoji":"⚛️","text":"⚛︎","type":0,"order":3659,"group":8,"subgroup":86,"version":1},{"annotation":"奥姆","name":"OM SYMBOL","hexcode":"1F549","shortcodes":["om_symbol"],"tags":["印度","宗教"],"emoji":"🕉️","text":"🕉︎","type":0,"order":3661,"group":8,"subgroup":86,"version":0.7},{"annotation":"六芒星","name":"STAR OF DAVID","hexcode":"2721","shortcodes":["star_of_david"],"tags":["大卫之星","宗教","犹太"],"emoji":"✡️","text":"✡︎","type":0,"order":3663,"group":8,"subgroup":86,"version":0.7},{"annotation":"法轮","name":"WHEEL OF DHARMA","hexcode":"2638","shortcodes":["wheel_of_dharma"],"tags":["佛","宗教","达摩"],"emoji":"☸️","text":"☸︎","type":0,"order":3665,"group":8,"subgroup":86,"version":0.7},{"annotation":"阴阳","name":"YIN YANG","hexcode":"262F","shortcodes":["yin_yang"],"tags":["太极","宗教","道","道教","阳","阴"],"emoji":"☯️","text":"☯︎","type":0,"order":3667,"group":8,"subgroup":86,"version":0.7},{"annotation":"十字架","name":"LATIN CROSS","hexcode":"271D","shortcodes":["cross"],"tags":["基督","天主教","宗教"],"emoji":"✝️","text":"✝︎","type":0,"order":3669,"group":8,"subgroup":86,"version":0.7},{"annotation":"东正教十字架","name":"ORTHODOX CROSS","hexcode":"2626","shortcodes":["orthodox_cross"],"tags":["东正教","十字架","基督","宗教"],"emoji":"☦️","text":"☦︎","type":0,"order":3671,"group":8,"subgroup":86,"version":1},{"annotation":"星月","name":"STAR AND CRESCENT","hexcode":"262A","shortcodes":["star_and_crescent"],"tags":["伊斯兰","宗教","穆斯林"],"emoji":"☪️","text":"☪︎","type":0,"order":3673,"group":8,"subgroup":86,"version":0.7},{"annotation":"和平符号","name":"PEACE SYMBOL","hexcode":"262E","shortcodes":["peace"],"tags":["和平"],"emoji":"☮️","text":"☮︎","type":0,"order":3675,"group":8,"subgroup":86,"version":1},{"annotation":"烛台","name":"MENORAH WITH NINE BRANCHES","hexcode":"1F54E","shortcodes":["menorah"],"tags":["光明节","宗教","灯台"],"emoji":"🕎","text":"","type":1,"order":3676,"group":8,"subgroup":86,"version":1},{"annotation":"带中间点的六芒星","name":"SIX POINTED STAR WITH MIDDLE DOT","hexcode":"1F52F","shortcodes":["six_pointed_star"],"tags":["六角星","命运"],"emoji":"🔯","text":"","type":1,"order":3677,"group":8,"subgroup":86,"version":0.6},{"annotation":"白羊座","name":"ARIES","hexcode":"2648","shortcodes":["aries"],"tags":["公羊","星座"],"emoji":"♈️","text":"♈︎","type":1,"order":3678,"group":8,"subgroup":87,"version":0.6},{"annotation":"金牛座","name":"TAURUS","hexcode":"2649","shortcodes":["taurus"],"tags":["公牛","星座"],"emoji":"♉️","text":"♉︎","type":1,"order":3679,"group":8,"subgroup":87,"version":0.6},{"annotation":"双子座","name":"GEMINI","hexcode":"264A","shortcodes":["gemini"],"tags":["孪生子","星座"],"emoji":"♊️","text":"♊︎","type":1,"order":3680,"group":8,"subgroup":87,"version":0.6},{"annotation":"巨蟹座","name":"CANCER","hexcode":"264B","shortcodes":["cancer"],"tags":["星座","螃蟹"],"emoji":"♋️","text":"♋︎","type":1,"order":3681,"group":8,"subgroup":87,"version":0.6},{"annotation":"狮子座","name":"LEO","hexcode":"264C","shortcodes":["leo"],"tags":["星座","雄狮"],"emoji":"♌️","text":"♌︎","type":1,"order":3682,"group":8,"subgroup":87,"version":0.6},{"annotation":"处女座","name":"VIRGO","hexcode":"264D","shortcodes":["virgo"],"tags":["星座","黄道十二宫"],"emoji":"♍️","text":"♍︎","type":1,"order":3683,"group":8,"subgroup":87,"version":0.6},{"annotation":"天秤座","name":"LIBRA","hexcode":"264E","shortcodes":["libra"],"tags":["平衡","星座","正义"],"emoji":"♎️","text":"♎︎","type":1,"order":3684,"group":8,"subgroup":87,"version":0.6},{"annotation":"天蝎座","name":"SCORPIUS","hexcode":"264F","shortcodes":["scorpius"],"tags":["星座","蝎子"],"emoji":"♏️","text":"♏︎","type":1,"order":3685,"group":8,"subgroup":87,"version":0.6},{"annotation":"射手座","name":"SAGITTARIUS","hexcode":"2650","shortcodes":["sagittarius"],"tags":["弓箭手","星座"],"emoji":"♐️","text":"♐︎","type":1,"order":3686,"group":8,"subgroup":87,"version":0.6},{"annotation":"摩羯座","name":"CAPRICORN","hexcode":"2651","shortcodes":["capricorn"],"tags":["山羊","星座"],"emoji":"♑️","text":"♑︎","type":1,"order":3687,"group":8,"subgroup":87,"version":0.6},{"annotation":"水瓶座","name":"AQUARIUS","hexcode":"2652","shortcodes":["aquarius"],"tags":["星座","水"],"emoji":"♒️","text":"♒︎","type":1,"order":3688,"group":8,"subgroup":87,"version":0.6},{"annotation":"双鱼座","name":"PISCES","hexcode":"2653","shortcodes":["pisces"],"tags":["星座","鱼"],"emoji":"♓️","text":"♓︎","type":1,"order":3689,"group":8,"subgroup":87,"version":0.6},{"annotation":"蛇夫座","name":"OPHIUCHUS","hexcode":"26CE","shortcodes":["ophiuchus"],"tags":["星座","蛇"],"emoji":"⛎","text":"","type":1,"order":3690,"group":8,"subgroup":87,"version":0.6},{"annotation":"随机播放音轨按钮","name":"TWISTED RIGHTWARDS ARROWS","hexcode":"1F500","shortcodes":["shuffle"],"tags":["交叉","打乱","随机"],"emoji":"🔀","text":"","type":1,"order":3691,"group":8,"subgroup":88,"version":1},{"annotation":"重复按钮","name":"CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS","hexcode":"1F501","shortcodes":["repeat"],"tags":["循环播放","箭头","顺时针"],"emoji":"🔁","text":"","type":1,"order":3692,"group":8,"subgroup":88,"version":1},{"annotation":"重复一次按钮","name":"CLOCKWISE RIGHTWARDS AND LEFTWARDS OPEN CIRCLE ARROWS WITH CIRCLED ONE OVERLAY","hexcode":"1F502","shortcodes":["repeat_single"],"tags":["单曲循环","循环","箭头","顺时针"],"emoji":"🔂","text":"","type":1,"order":3693,"group":8,"subgroup":88,"version":1},{"annotation":"播放按钮","name":"BLACK RIGHT-POINTING TRIANGLE","hexcode":"25B6","shortcodes":["play"],"tags":["三角","向右","箭头"],"emoji":"▶️","text":"▶︎","type":0,"order":3695,"group":8,"subgroup":88,"version":0.6},{"annotation":"快进按钮","name":"BLACK RIGHT-POINTING DOUBLE TRIANGLE","hexcode":"23E9","shortcodes":["fast_forward"],"tags":["双箭头","向前","快速"],"emoji":"⏩️","text":"⏩︎","type":1,"order":3696,"group":8,"subgroup":88,"version":0.6},{"annotation":"下一个音轨按钮","name":"BLACK RIGHT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR","hexcode":"23ED","shortcodes":["next_track"],"tags":["三角","往后","箭头"],"emoji":"⏭️","text":"⏭︎","type":0,"order":3698,"group":8,"subgroup":88,"version":0.7},{"annotation":"播放或暂停按钮","name":"BLACK RIGHT-POINTING TRIANGLE WITH DOUBLE VERTICAL BAR","hexcode":"23EF","shortcodes":["play_pause"],"tags":["三角","向右"],"emoji":"⏯️","text":"⏯︎","type":0,"order":3700,"group":8,"subgroup":88,"version":1},{"annotation":"倒退按钮","name":"BLACK LEFT-POINTING TRIANGLE","hexcode":"25C0","shortcodes":["reverse"],"tags":["三角","后退","向左"],"emoji":"◀️","text":"◀︎","type":0,"order":3702,"group":8,"subgroup":88,"version":0.6},{"annotation":"快退按钮","name":"BLACK LEFT-POINTING DOUBLE TRIANGLE","hexcode":"23EA","shortcodes":["rewind"],"tags":["倒回","双箭头"],"emoji":"⏪️","text":"⏪︎","type":1,"order":3703,"group":8,"subgroup":88,"version":0.6},{"annotation":"上一个音轨按钮","name":"BLACK LEFT-POINTING DOUBLE TRIANGLE WITH VERTICAL BAR","hexcode":"23EE","shortcodes":["previous_track"],"tags":["三角","箭头"],"emoji":"⏮️","text":"⏮︎","type":0,"order":3705,"group":8,"subgroup":88,"version":0.7},{"annotation":"向上三角形按钮","name":"UP-POINTING SMALL RED TRIANGLE","hexcode":"1F53C","shortcodes":["up_button"],"tags":["往上","箭头"],"emoji":"🔼","text":"","type":1,"order":3706,"group":8,"subgroup":88,"version":0.6},{"annotation":"快速上升按钮","name":"BLACK UP-POINTING DOUBLE TRIANGLE","hexcode":"23EB","shortcodes":["fast_up_button"],"tags":["双箭头","向上"],"emoji":"⏫","text":"","type":1,"order":3707,"group":8,"subgroup":88,"version":0.6},{"annotation":"向下三角形按钮","name":"DOWN-POINTING SMALL RED TRIANGLE","hexcode":"1F53D","shortcodes":["down_button"],"tags":["往下","箭头"],"emoji":"🔽","text":"","type":1,"order":3708,"group":8,"subgroup":88,"version":0.6},{"annotation":"快速下降按钮","name":"BLACK DOWN-POINTING DOUBLE TRIANGLE","hexcode":"23EC","shortcodes":["fast_down_button"],"tags":["双箭头","向下"],"emoji":"⏬","text":"","type":1,"order":3709,"group":8,"subgroup":88,"version":0.6},{"annotation":"暂停按钮","name":"DOUBLE VERTICAL BAR","hexcode":"23F8","shortcodes":["pause"],"tags":["停止","双条形"],"emoji":"⏸️","text":"⏸︎","type":0,"order":3711,"group":8,"subgroup":88,"version":0.7},{"annotation":"停止按钮","name":"BLACK SQUARE FOR STOP","hexcode":"23F9","shortcodes":["stop"],"tags":["方形","终止"],"emoji":"⏹️","text":"⏹︎","type":0,"order":3713,"group":8,"subgroup":88,"version":0.7},{"annotation":"录制按钮","name":"BLACK CIRCLE FOR RECORD","hexcode":"23FA","shortcodes":["record"],"tags":["制作","圆"],"emoji":"⏺️","text":"⏺︎","type":0,"order":3715,"group":8,"subgroup":88,"version":0.7},{"annotation":"推出按钮","name":"EJECT SYMBOL","hexcode":"23CF","shortcodes":["eject"],"tags":["向上三角","弹出"],"emoji":"⏏️","text":"⏏︎","type":0,"order":3717,"group":8,"subgroup":88,"version":1},{"annotation":"电影院","name":"CINEMA","hexcode":"1F3A6","shortcodes":["cinema"],"tags":["场所","影片"],"emoji":"🎦","text":"","type":1,"order":3718,"group":8,"subgroup":88,"version":0.6},{"annotation":"低亮度按钮","name":"LOW BRIGHTNESS SYMBOL","hexcode":"1F505","shortcodes":["dim","low_brightness"],"tags":["亮度","低","昏暗"],"emoji":"🔅","text":"","type":1,"order":3719,"group":8,"subgroup":88,"version":1},{"annotation":"高亮度按钮","name":"HIGH BRIGHTNESS SYMBOL","hexcode":"1F506","shortcodes":["bright","high_brightness"],"tags":["亮度","太阳","明亮"],"emoji":"🔆","text":"","type":1,"order":3720,"group":8,"subgroup":88,"version":1},{"annotation":"信号强度条","name":"ANTENNA WITH BARS","hexcode":"1F4F6","shortcodes":["signal_strength","antenna_bars"],"tags":["天线","手机","条"],"emoji":"📶","text":"","type":1,"order":3721,"group":8,"subgroup":88,"version":0.6},{"annotation":"振动模式","name":"VIBRATION MODE","hexcode":"1F4F3","shortcodes":["vibration_mode"],"tags":["手机","震动"],"emoji":"📳","text":"","type":1,"order":3722,"group":8,"subgroup":88,"version":0.6},{"annotation":"手机关机","name":"MOBILE PHONE OFF","hexcode":"1F4F4","shortcodes":["mobile_phone_off"],"tags":["关闭","手机"],"emoji":"📴","text":"","type":1,"order":3723,"group":8,"subgroup":88,"version":0.6},{"annotation":"女性符号","name":"FEMALE SIGN","hexcode":"2640","shortcodes":["female","female_sign"],"tags":["符号","雌性"],"emoji":"♀️","text":"♀︎","type":0,"order":3725,"group":8,"subgroup":89,"version":4},{"annotation":"男性符号","name":"MALE SIGN","hexcode":"2642","shortcodes":["male","male_sign"],"tags":["符号","雄性"],"emoji":"♂️","text":"♂︎","type":0,"order":3727,"group":8,"subgroup":89,"version":4},{"annotation":"跨性别符号","name":"MALE WITH STROKE AND MALE AND FEMALE SIGN","hexcode":"26A7","shortcodes":["trans"],"tags":["跨性别"],"emoji":"⚧️","text":"⚧︎","type":0,"order":3729,"group":8,"subgroup":89,"version":13},{"annotation":"乘","name":"HEAVY MULTIPLICATION X","hexcode":"2716","shortcodes":["multiplication"],"tags":["乘号","取消","相乘","符号"],"emoji":"✖️","text":"✖︎","type":0,"order":3731,"group":8,"subgroup":90,"version":0.6},{"annotation":"加号","name":"HEAVY PLUS SIGN","hexcode":"2795","shortcodes":["plus"],"tags":["十字","数学","相加","符号"],"emoji":"➕","text":"","type":1,"order":3732,"group":8,"subgroup":90,"version":0.6},{"annotation":"减号","name":"HEAVY MINUS SIGN","hexcode":"2796","shortcodes":["minus"],"tags":["数学","横线","符号"],"emoji":"➖","text":"","type":1,"order":3733,"group":8,"subgroup":90,"version":0.6},{"annotation":"除","name":"HEAVY DIVISION SIGN","hexcode":"2797","shortcodes":["division"],"tags":["数学","相除","符号","除号"],"emoji":"➗","text":"","type":1,"order":3734,"group":8,"subgroup":90,"version":0.6},{"annotation":"无限","name":"PERMANENT PAPER SIGN","hexcode":"267E","shortcodes":["infinity"],"tags":["宇宙","永恒"],"emoji":"♾️","text":"♾︎","type":0,"order":3736,"group":8,"subgroup":90,"version":11},{"annotation":"双感叹号","name":"DOUBLE EXCLAMATION MARK","hexcode":"203C","shortcodes":["bangbang","double_exclamation"],"tags":["两个","吃惊","标点符号","!","!!"],"emoji":"‼️","text":"‼︎","type":0,"order":3738,"group":8,"subgroup":91,"version":0.6},{"annotation":"感叹疑问号","name":"EXCLAMATION QUESTION MARK","hexcode":"2049","shortcodes":["interrobang","exclamation_question"],"tags":["吃惊","标点符号","问号","!","!?","?"],"emoji":"⁉️","text":"⁉︎","type":0,"order":3740,"group":8,"subgroup":91,"version":0.6},{"annotation":"问号","name":"BLACK QUESTION MARK ORNAMENT","hexcode":"2753","shortcodes":["question"],"tags":["为什么","标点符号"],"emoji":"❓️","text":"❓︎","type":1,"order":3741,"group":8,"subgroup":91,"version":0.6},{"annotation":"白色问号","name":"WHITE QUESTION MARK ORNAMENT","hexcode":"2754","shortcodes":["white_question"],"tags":["为什么","标点符号","空心","?"],"emoji":"❔","text":"","type":1,"order":3742,"group":8,"subgroup":91,"version":0.6},{"annotation":"白色感叹号","name":"WHITE EXCLAMATION MARK ORNAMENT","hexcode":"2755","shortcodes":["white_exclamation"],"tags":["吃惊","标点符号","空心","!"],"emoji":"❕","text":"","type":1,"order":3743,"group":8,"subgroup":91,"version":0.6},{"annotation":"感叹号","name":"HEAVY EXCLAMATION MARK SYMBOL","hexcode":"2757","shortcodes":["exclamation"],"tags":["吃惊","标点符号","!"],"emoji":"❗️","text":"❗︎","type":1,"order":3744,"group":8,"subgroup":91,"version":0.6},{"annotation":"波浪型破折号","name":"WAVY DASH","hexcode":"3030","shortcodes":["wavy_dash"],"tags":["标点符号","浪花"],"emoji":"〰️","text":"〰︎","type":0,"order":3746,"group":8,"subgroup":91,"version":0.6},{"annotation":"货币兑换","name":"CURRENCY EXCHANGE","hexcode":"1F4B1","shortcodes":["currency_exchange"],"tags":["兑换","外汇","换汇","汇率","流通"],"emoji":"💱","text":"","type":1,"order":3747,"group":8,"subgroup":92,"version":0.6},{"annotation":"美元符号","name":"HEAVY DOLLAR SIGN","hexcode":"1F4B2","shortcodes":["dollar_sign"],"tags":["美元","货币"],"emoji":"💲","text":"","type":1,"order":3748,"group":8,"subgroup":92,"version":0.6},{"annotation":"医疗标志","name":"STAFF OF AESCULAPIUS","hexcode":"2695","shortcodes":["medical"],"tags":["蛇杖","阿斯克勒庇俄斯"],"emoji":"⚕️","text":"⚕︎","type":0,"order":3750,"group":8,"subgroup":93,"version":4},{"annotation":"回收标志","name":"BLACK UNIVERSAL RECYCLING SYMBOL","hexcode":"267B","shortcodes":["recycle"],"tags":["再利用","循环"],"emoji":"♻️","text":"♻︎","type":0,"order":3752,"group":8,"subgroup":93,"version":0.6},{"annotation":"百合花饰","name":"FLEUR-DE-LIS","hexcode":"269C","shortcodes":["fleur-de-lis"],"tags":["鸢尾花"],"emoji":"⚜️","text":"⚜︎","type":0,"order":3754,"group":8,"subgroup":93,"version":1},{"annotation":"三叉戟徽章","name":"TRIDENT EMBLEM","hexcode":"1F531","shortcodes":["trident"],"tags":["工具","船","锚"],"emoji":"🔱","text":"","type":1,"order":3755,"group":8,"subgroup":93,"version":0.6},{"annotation":"姓名牌","name":"NAME BADGE","hexcode":"1F4DB","shortcodes":["name_badge"],"tags":["胸牌","证章"],"emoji":"📛","text":"","type":1,"order":3756,"group":8,"subgroup":93,"version":0.6},{"annotation":"日本新手驾驶标志","name":"JAPANESE SYMBOL FOR BEGINNER","hexcode":"1F530","shortcodes":["ja_beginner"],"tags":["v形图案","叶状","实习","箭尾"],"emoji":"🔰","text":"","type":1,"order":3757,"group":8,"subgroup":93,"version":0.6},{"annotation":"红色空心圆圈","name":"HEAVY LARGE CIRCLE","hexcode":"2B55","shortcodes":["o"],"tags":["o形","圆圈","大","红"],"emoji":"⭕️","text":"⭕︎","type":1,"order":3758,"group":8,"subgroup":93,"version":0.6},{"annotation":"勾号按钮","name":"WHITE HEAVY CHECK MARK","hexcode":"2705","shortcodes":["white_check_mark"],"tags":["勾","勾号","打勾","按钮"],"emoji":"✅","text":"","type":1,"order":3759,"group":8,"subgroup":93,"version":0.6},{"annotation":"勾选框","name":"BALLOT BOX WITH CHECK","hexcode":"2611","shortcodes":["checked_ballot"],"tags":["勾号","复选框","带勾方格","打勾"],"emoji":"☑️","text":"☑︎","type":0,"order":3761,"group":8,"subgroup":93,"version":0.6},{"annotation":"勾号","name":"HEAVY CHECK MARK","hexcode":"2714","shortcodes":["check_mark"],"tags":["对勾","打勾","正确","符号"],"emoji":"✔️","text":"✔︎","type":0,"order":3763,"group":8,"subgroup":93,"version":0.6},{"annotation":"叉号","name":"CROSS MARK","hexcode":"274C","shortcodes":["x","cross_mark"],"tags":["交叉","取消","相乘","符号"],"emoji":"❌","text":"","type":1,"order":3764,"group":8,"subgroup":93,"version":0.6},{"annotation":"叉号按钮","name":"NEGATIVE SQUARED CROSS MARK","hexcode":"274E","shortcodes":["cross_mark_button"],"tags":["取消","方形"],"emoji":"❎","text":"","type":1,"order":3765,"group":8,"subgroup":93,"version":0.6},{"annotation":"卷曲环","name":"CURLY LOOP","hexcode":"27B0","shortcodes":["curly_loop"],"tags":["单环","标志"],"emoji":"➰","text":"","type":1,"order":3766,"group":8,"subgroup":93,"version":0.6},{"annotation":"双卷曲环","name":"DOUBLE CURLY LOOP","hexcode":"27BF","shortcodes":["double_curly_loop"],"tags":["双环","标志"],"emoji":"➿","text":"","type":1,"order":3767,"group":8,"subgroup":93,"version":1},{"annotation":"庵点","name":"PART ALTERNATION MARK","hexcode":"303D","shortcodes":["part_alternation_mark"],"tags":["开始歌唱","符号"],"emoji":"〽️","text":"〽︎","type":0,"order":3769,"group":8,"subgroup":93,"version":0.6},{"annotation":"八轮辐星号","name":"EIGHT SPOKED ASTERISK","hexcode":"2733","shortcodes":["eight_spoked_asterisk"],"tags":["星号"],"emoji":"✳️","text":"✳︎","type":0,"order":3771,"group":8,"subgroup":93,"version":0.6},{"annotation":"八角星","name":"EIGHT POINTED BLACK STAR","hexcode":"2734","shortcodes":["eight_pointed_star"],"tags":["星","符号"],"emoji":"✴️","text":"✴︎","type":0,"order":3773,"group":8,"subgroup":93,"version":0.6},{"annotation":"火花","name":"SPARKLE","hexcode":"2747","shortcodes":["sparkle"],"tags":["烟火","闪耀"],"emoji":"❇️","text":"❇︎","type":0,"order":3775,"group":8,"subgroup":93,"version":0.6},{"annotation":"版权","name":"COPYRIGHT SIGN","hexcode":"00A9","shortcodes":["copyright"],"tags":["版权"],"emoji":"©️","text":"©︎","type":0,"order":3777,"group":8,"subgroup":93,"version":0.6},{"annotation":"注册","name":"REGISTERED SIGN","hexcode":"00AE","shortcodes":["registered"],"tags":["注册标记"],"emoji":"®️","text":"®︎","type":0,"order":3779,"group":8,"subgroup":93,"version":0.6},{"annotation":"商标","name":"TRADE MARK SIGN","hexcode":"2122","shortcodes":["tm"],"tags":["产品","标志"],"emoji":"™️","text":"™︎","type":0,"order":3781,"group":8,"subgroup":93,"version":0.6},{"annotation":"按键: #","name":"NUMBER SIGN, COMBINING ENCLOSING KEYCAP","hexcode":"0023-FE0F-20E3","shortcodes":["hash"],"tags":["按键"],"emoji":"#️⃣","text":"","type":1,"order":3782,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: *","name":"ASTERISK, COMBINING ENCLOSING KEYCAP","hexcode":"002A-FE0F-20E3","shortcodes":["asterisk"],"tags":["按键"],"emoji":"*️⃣","text":"","type":1,"order":3784,"group":8,"subgroup":94,"version":2},{"annotation":"按键: 0","name":"DIGIT ZERO, COMBINING ENCLOSING KEYCAP","hexcode":"0030-FE0F-20E3","shortcodes":["zero"],"tags":["按键"],"emoji":"0️⃣","text":"","type":1,"order":3786,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: 1","name":"DIGIT ONE, COMBINING ENCLOSING KEYCAP","hexcode":"0031-FE0F-20E3","shortcodes":["one"],"tags":["按键"],"emoji":"1️⃣","text":"","type":1,"order":3788,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: 2","name":"DIGIT TWO, COMBINING ENCLOSING KEYCAP","hexcode":"0032-FE0F-20E3","shortcodes":["two"],"tags":["按键"],"emoji":"2️⃣","text":"","type":1,"order":3790,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: 3","name":"DIGIT THREE, COMBINING ENCLOSING KEYCAP","hexcode":"0033-FE0F-20E3","shortcodes":["three"],"tags":["按键"],"emoji":"3️⃣","text":"","type":1,"order":3792,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: 4","name":"DIGIT FOUR, COMBINING ENCLOSING KEYCAP","hexcode":"0034-FE0F-20E3","shortcodes":["four"],"tags":["按键"],"emoji":"4️⃣","text":"","type":1,"order":3794,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: 5","name":"DIGIT FIVE, COMBINING ENCLOSING KEYCAP","hexcode":"0035-FE0F-20E3","shortcodes":["five"],"tags":["按键"],"emoji":"5️⃣","text":"","type":1,"order":3796,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: 6","name":"DIGIT SIX, COMBINING ENCLOSING KEYCAP","hexcode":"0036-FE0F-20E3","shortcodes":["six"],"tags":["按键"],"emoji":"6️⃣","text":"","type":1,"order":3798,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: 7","name":"DIGIT SEVEN, COMBINING ENCLOSING KEYCAP","hexcode":"0037-FE0F-20E3","shortcodes":["seven"],"tags":["按键"],"emoji":"7️⃣","text":"","type":1,"order":3800,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: 8","name":"DIGIT EIGHT, COMBINING ENCLOSING KEYCAP","hexcode":"0038-FE0F-20E3","shortcodes":["eight"],"tags":["按键"],"emoji":"8️⃣","text":"","type":1,"order":3802,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: 9","name":"DIGIT NINE, COMBINING ENCLOSING KEYCAP","hexcode":"0039-FE0F-20E3","shortcodes":["nine"],"tags":["按键"],"emoji":"9️⃣","text":"","type":1,"order":3804,"group":8,"subgroup":94,"version":0.6},{"annotation":"按键: 10","name":"KEYCAP TEN","hexcode":"1F51F","shortcodes":["ten"],"tags":["按键"],"emoji":"🔟","text":"","type":1,"order":3806,"group":8,"subgroup":94,"version":0.6},{"annotation":"输入大写拉丁字母","name":"INPUT SYMBOL FOR LATIN CAPITAL LETTERS","hexcode":"1F520","shortcodes":["upper_abcd"],"tags":["abcd","打字","拉丁文","输入法"],"emoji":"🔠","text":"","type":1,"order":3807,"group":8,"subgroup":95,"version":0.6},{"annotation":"输入小写拉丁字母","name":"INPUT SYMBOL FOR LATIN SMALL LETTERS","hexcode":"1F521","shortcodes":["abcd"],"tags":["abcd","打字","拉丁文","输入法"],"emoji":"🔡","text":"","type":1,"order":3808,"group":8,"subgroup":95,"version":0.6},{"annotation":"输入数字","name":"INPUT SYMBOL FOR NUMBERS","hexcode":"1F522","shortcodes":["1234"],"tags":["1234","打字"],"emoji":"🔢","text":"","type":1,"order":3809,"group":8,"subgroup":95,"version":0.6},{"annotation":"输入符号","name":"INPUT SYMBOL FOR SYMBOLS","hexcode":"1F523","shortcodes":["symbols"],"tags":["字符","打字"],"emoji":"🔣","text":"","type":1,"order":3810,"group":8,"subgroup":95,"version":0.6},{"annotation":"输入拉丁字母","name":"INPUT SYMBOL FOR LATIN LETTERS","hexcode":"1F524","shortcodes":["abc"],"tags":["abc","字母","打字","拉丁文"],"emoji":"🔤","text":"","type":1,"order":3811,"group":8,"subgroup":95,"version":0.6},{"annotation":"A 型血","name":"NEGATIVE SQUARED LATIN CAPITAL LETTER A","hexcode":"1F170","shortcodes":["a_blood"],"tags":["a","a 型血","按钮","血液"],"emoji":"🅰️","text":"🅰︎","type":0,"order":3813,"group":8,"subgroup":95,"version":0.6},{"annotation":"AB 型血","name":"NEGATIVE SQUARED AB","hexcode":"1F18E","shortcodes":["ab_blood"],"tags":["ab","ab 型血","按钮","血液"],"emoji":"🆎","text":"","type":1,"order":3814,"group":8,"subgroup":95,"version":0.6},{"annotation":"B 型血","name":"NEGATIVE SQUARED LATIN CAPITAL LETTER B","hexcode":"1F171","shortcodes":["b_blood"],"tags":["b","b 型血","按钮","血液"],"emoji":"🅱️","text":"🅱︎","type":0,"order":3816,"group":8,"subgroup":95,"version":0.6},{"annotation":"CL按钮","name":"SQUARED CL","hexcode":"1F191","shortcodes":["cl"],"tags":["cl","cl按钮","手机","清理"],"emoji":"🆑","text":"","type":1,"order":3817,"group":8,"subgroup":95,"version":0.6},{"annotation":"cool按钮","name":"SQUARED COOL","hexcode":"1F192","shortcodes":["cool"],"tags":["按键","酷"],"emoji":"🆒","text":"","type":1,"order":3818,"group":8,"subgroup":95,"version":0.6},{"annotation":"免费按钮","name":"SQUARED FREE","hexcode":"1F193","shortcodes":["free"],"tags":["不收费","按钮"],"emoji":"🆓","text":"","type":1,"order":3819,"group":8,"subgroup":95,"version":0.6},{"annotation":"信息","name":"INFORMATION SOURCE","hexcode":"2139","shortcodes":["info"],"tags":["查询","资料"],"emoji":"ℹ️","text":"ℹ︎","type":0,"order":3821,"group":8,"subgroup":95,"version":0.6},{"annotation":"ID按钮","name":"SQUARED ID","hexcode":"1F194","shortcodes":["id"],"tags":["id按钮","按键","识别","身份"],"emoji":"🆔","text":"","type":1,"order":3822,"group":8,"subgroup":95,"version":0.6},{"annotation":"圆圈包围的M","name":"CIRCLED LATIN CAPITAL LETTER M","hexcode":"24C2","shortcodes":["m"],"tags":["圆圈包围的m","圈","字母","米"],"emoji":"Ⓜ️","text":"Ⓜ︎","type":0,"order":3824,"group":8,"subgroup":95,"version":0.6},{"annotation":"new按钮","name":"SQUARED NEW","hexcode":"1F195","shortcodes":["new"],"tags":["按键","新的"],"emoji":"🆕","text":"","type":1,"order":3825,"group":8,"subgroup":95,"version":0.6},{"annotation":"NG按钮","name":"SQUARED NG","hexcode":"1F196","shortcodes":["ng"],"tags":["ng按钮","按键","花絮"],"emoji":"🆖","text":"","type":1,"order":3826,"group":8,"subgroup":95,"version":0.6},{"annotation":"O 型血","name":"NEGATIVE SQUARED LATIN CAPITAL LETTER O","hexcode":"1F17E","shortcodes":["o_blood"],"tags":["o","o 型血","按钮","血液"],"emoji":"🅾️","text":"🅾︎","type":0,"order":3828,"group":8,"subgroup":95,"version":0.6},{"annotation":"OK按钮","name":"SQUARED OK","hexcode":"1F197","shortcodes":["ok"],"tags":["ok按钮","同意","按键"],"emoji":"🆗","text":"","type":1,"order":3829,"group":8,"subgroup":95,"version":0.6},{"annotation":"停车按钮","name":"NEGATIVE SQUARED LATIN CAPITAL LETTER P","hexcode":"1F17F","shortcodes":["p"],"tags":["按键","泊车"],"emoji":"🅿️","text":"🅿︎","type":0,"order":3831,"group":8,"subgroup":95,"version":0.6},{"annotation":"SOS按钮","name":"SQUARED SOS","hexcode":"1F198","shortcodes":["sos"],"tags":["sos按钮","按键","求救"],"emoji":"🆘","text":"","type":1,"order":3832,"group":8,"subgroup":95,"version":0.6},{"annotation":"up按钮","name":"SQUARED UP WITH EXCLAMATION MARK","hexcode":"1F199","shortcodes":["up"],"tags":["向上","按键"],"emoji":"🆙","text":"","type":1,"order":3833,"group":8,"subgroup":95,"version":0.6},{"annotation":"VS按钮","name":"SQUARED VS","hexcode":"1F19A","shortcodes":["vs"],"tags":["vs按钮","对决","按键"],"emoji":"🆚","text":"","type":1,"order":3834,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“这里”按钮","name":"SQUARED KATAKANA KOKO","hexcode":"1F201","shortcodes":["ja_here","koko"],"tags":["按键","日文","此处"],"emoji":"🈁","text":"","type":1,"order":3835,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“服务费”按钮","name":"SQUARED KATAKANA SA","hexcode":"1F202","shortcodes":["ja_service_charge"],"tags":["按键","收费","日文","服务"],"emoji":"🈂️","text":"🈂︎","type":0,"order":3837,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“月总量”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-6708","hexcode":"1F237","shortcodes":["ja_monthly_amount"],"tags":["按键","日文","月度","统计"],"emoji":"🈷️","text":"🈷︎","type":0,"order":3839,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“收费”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-6709","hexcode":"1F236","shortcodes":["ja_not_free_of_carge"],"tags":["按键","日文","费用"],"emoji":"🈶","text":"","type":1,"order":3840,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“预留”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-6307","hexcode":"1F22F","shortcodes":["ja_reserved"],"tags":["按键","日文","预订"],"emoji":"🈯️","text":"🈯︎","type":1,"order":3841,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“议价”按钮","name":"CIRCLED IDEOGRAPH ADVANTAGE","hexcode":"1F250","shortcodes":["ja_bargain"],"tags":["按键","日文","讨价还价"],"emoji":"🉐","text":"","type":1,"order":3842,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“打折”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-5272","hexcode":"1F239","shortcodes":["ja_discount"],"tags":["折扣","按键","日文"],"emoji":"🈹","text":"","type":1,"order":3843,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“免费”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-7121","hexcode":"1F21A","shortcodes":["ja_free_of_charge"],"tags":["免费","按键","日文"],"emoji":"🈚️","text":"🈚︎","type":1,"order":3844,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“禁止”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-7981","hexcode":"1F232","shortcodes":["ja_prohibited"],"tags":["严禁","按键","日文"],"emoji":"🈲","text":"","type":1,"order":3845,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“可接受”按钮","name":"CIRCLED IDEOGRAPH ACCEPT","hexcode":"1F251","shortcodes":["ja_acceptable"],"tags":["按键","日文","许可"],"emoji":"🉑","text":"","type":1,"order":3846,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“申请”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-7533","hexcode":"1F238","shortcodes":["ja_application"],"tags":["日文","日语","申","申请","申请书","申请表"],"emoji":"🈸","text":"","type":1,"order":3847,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“合格”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-5408","hexcode":"1F234","shortcodes":["ja_passing_grade"],"tags":["按键","日文","通过"],"emoji":"🈴","text":"","type":1,"order":3848,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“有空位”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-7A7A","hexcode":"1F233","shortcodes":["ja_vacancy"],"tags":["日文","日语","有空位","空","空位","空闲"],"emoji":"🈳","text":"","type":1,"order":3849,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“祝贺”按钮","name":"CIRCLED IDEOGRAPH CONGRATULATION","hexcode":"3297","shortcodes":["ja_congratulations"],"tags":["庆贺","按键","日文"],"emoji":"㊗️","text":"㊗︎","type":0,"order":3851,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“秘密”按钮","name":"CIRCLED IDEOGRAPH SECRET","hexcode":"3299","shortcodes":["ja_secret"],"tags":["保密","按键","日文"],"emoji":"㊙️","text":"㊙︎","type":0,"order":3853,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“开始营业”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-55B6","hexcode":"1F23A","shortcodes":["ja_open_for_business"],"tags":["开门","按键","日文"],"emoji":"🈺","text":"","type":1,"order":3854,"group":8,"subgroup":95,"version":0.6},{"annotation":"日文的“没有空位”按钮","name":"SQUARED CJK UNIFIED IDEOGRAPH-6E80","hexcode":"1F235","shortcodes":["ja_no_vacancy"],"tags":["座位","按键","日文","满"],"emoji":"🈵","text":"","type":1,"order":3855,"group":8,"subgroup":95,"version":0.6},{"annotation":"红色圆","name":"LARGE RED CIRCLE","hexcode":"1F534","shortcodes":["red_circle"],"tags":["圆","圈","红","红色"],"emoji":"🔴","text":"","type":1,"order":3856,"group":8,"subgroup":96,"version":0.6},{"annotation":"橙色圆","name":"LARGE ORANGE CIRCLE","hexcode":"1F7E0","shortcodes":["orange_circle"],"tags":["圆","圈","橙"],"emoji":"🟠","text":"","type":1,"order":3857,"group":8,"subgroup":96,"version":12},{"annotation":"黄色圆","name":"LARGE YELLOW CIRCLE","hexcode":"1F7E1","shortcodes":["yellow_circle"],"tags":["圆","圈","黄"],"emoji":"🟡","text":"","type":1,"order":3858,"group":8,"subgroup":96,"version":12},{"annotation":"绿色圆","name":"LARGE GREEN CIRCLE","hexcode":"1F7E2","shortcodes":["green_circle"],"tags":["圆","圈","绿"],"emoji":"🟢","text":"","type":1,"order":3859,"group":8,"subgroup":96,"version":12},{"annotation":"蓝色圆","name":"LARGE BLUE CIRCLE","hexcode":"1F535","shortcodes":["blue_circle"],"tags":["圈","蓝"],"emoji":"🔵","text":"","type":1,"order":3860,"group":8,"subgroup":96,"version":0.6},{"annotation":"紫色圆","name":"LARGE PURPLE CIRCLE","hexcode":"1F7E3","shortcodes":["purple_circle"],"tags":["圆","圈","紫"],"emoji":"🟣","text":"","type":1,"order":3861,"group":8,"subgroup":96,"version":12},{"annotation":"棕色圆","name":"LARGE BROWN CIRCLE","hexcode":"1F7E4","shortcodes":["brown_circle"],"tags":["圆","圈","棕"],"emoji":"🟤","text":"","type":1,"order":3862,"group":8,"subgroup":96,"version":12},{"annotation":"黑色圆","name":"MEDIUM BLACK CIRCLE","hexcode":"26AB","shortcodes":["black_circle"],"tags":["圈","黑"],"emoji":"⚫️","text":"⚫︎","type":1,"order":3863,"group":8,"subgroup":96,"version":0.6},{"annotation":"白色圆","name":"MEDIUM WHITE CIRCLE","hexcode":"26AA","shortcodes":["white_circle"],"tags":["圈","白"],"emoji":"⚪️","text":"⚪︎","type":1,"order":3864,"group":8,"subgroup":96,"version":0.6},{"annotation":"红色方块","name":"LARGE RED SQUARE","hexcode":"1F7E5","shortcodes":["red_square"],"tags":["方块","方框","正方形","红"],"emoji":"🟥","text":"","type":1,"order":3865,"group":8,"subgroup":96,"version":12},{"annotation":"橙色方块","name":"LARGE ORANGE SQUARE","hexcode":"1F7E7","shortcodes":["orange_square"],"tags":["方块","方框","橙","正方形"],"emoji":"🟧","text":"","type":1,"order":3866,"group":8,"subgroup":96,"version":12},{"annotation":"黄色方块","name":"LARGE YELLOW SQUARE","hexcode":"1F7E8","shortcodes":["yellow_square"],"tags":["方块","方框","正方形","黄"],"emoji":"🟨","text":"","type":1,"order":3867,"group":8,"subgroup":96,"version":12},{"annotation":"绿色方块","name":"LARGE GREEN SQUARE","hexcode":"1F7E9","shortcodes":["green_square"],"tags":["方块","方框","正方形","绿"],"emoji":"🟩","text":"","type":1,"order":3868,"group":8,"subgroup":96,"version":12},{"annotation":"蓝色方块","name":"LARGE BLUE SQUARE","hexcode":"1F7E6","shortcodes":["blue_square"],"tags":["方块","方框","正方形","蓝"],"emoji":"🟦","text":"","type":1,"order":3869,"group":8,"subgroup":96,"version":12},{"annotation":"紫色方块","name":"LARGE PURPLE SQUARE","hexcode":"1F7EA","shortcodes":["purple_square"],"tags":["方块","方框","正方形","紫"],"emoji":"🟪","text":"","type":1,"order":3870,"group":8,"subgroup":96,"version":12},{"annotation":"棕色方块","name":"LARGE BROWN SQUARE","hexcode":"1F7EB","shortcodes":["brown_square"],"tags":["方块","方框","棕","正方形"],"emoji":"🟫","text":"","type":1,"order":3871,"group":8,"subgroup":96,"version":12},{"annotation":"黑线大方框","name":"BLACK LARGE SQUARE","hexcode":"2B1B","shortcodes":["large_black_square"],"tags":["大","正方形","黑色"],"emoji":"⬛️","text":"⬛︎","type":1,"order":3872,"group":8,"subgroup":96,"version":0.6},{"annotation":"白线大方框","name":"WHITE LARGE SQUARE","hexcode":"2B1C","shortcodes":["large_white_square"],"tags":["大","正方形","白色"],"emoji":"⬜️","text":"⬜︎","type":1,"order":3873,"group":8,"subgroup":96,"version":0.6},{"annotation":"黑色中方块","name":"BLACK MEDIUM SQUARE","hexcode":"25FC","shortcodes":["medium_black_square"],"tags":["中等","正方形","黑色"],"emoji":"◼️","text":"◼︎","type":0,"order":3875,"group":8,"subgroup":96,"version":0.6},{"annotation":"白色中方块","name":"WHITE MEDIUM SQUARE","hexcode":"25FB","shortcodes":["medium_white_square"],"tags":["中等","正方形","白色"],"emoji":"◻️","text":"◻︎","type":0,"order":3877,"group":8,"subgroup":96,"version":0.6},{"annotation":"黑色中小方块","name":"BLACK MEDIUM SMALL SQUARE","hexcode":"25FE","shortcodes":["medium_small_black_square"],"tags":["中小","正方形","黑色"],"emoji":"◾️","text":"◾︎","type":1,"order":3878,"group":8,"subgroup":96,"version":0.6},{"annotation":"白色中小方块","name":"WHITE MEDIUM SMALL SQUARE","hexcode":"25FD","shortcodes":["medium_small_white_square"],"tags":["中小 正方形","白色"],"emoji":"◽️","text":"◽︎","type":1,"order":3879,"group":8,"subgroup":96,"version":0.6},{"annotation":"黑色小方块","name":"BLACK SMALL SQUARE","hexcode":"25AA","shortcodes":["small_black_square"],"tags":["小","正方形","黑色"],"emoji":"▪️","text":"▪︎","type":0,"order":3881,"group":8,"subgroup":96,"version":0.6},{"annotation":"白色小方块","name":"WHITE SMALL SQUARE","hexcode":"25AB","shortcodes":["small_white_square"],"tags":["小","正方形","白色"],"emoji":"▫️","text":"▫︎","type":0,"order":3883,"group":8,"subgroup":96,"version":0.6},{"annotation":"橙色大菱形","name":"LARGE ORANGE DIAMOND","hexcode":"1F536","shortcodes":["large_orange_diamond"],"tags":["大","方片","橘黄色"],"emoji":"🔶","text":"","type":1,"order":3884,"group":8,"subgroup":96,"version":0.6},{"annotation":"蓝色大菱形","name":"LARGE BLUE DIAMOND","hexcode":"1F537","shortcodes":["large_blue_diamond"],"tags":["大","方片","蓝色"],"emoji":"🔷","text":"","type":1,"order":3885,"group":8,"subgroup":96,"version":0.6},{"annotation":"橙色小菱形","name":"SMALL ORANGE DIAMOND","hexcode":"1F538","shortcodes":["small_orange_diamond"],"tags":["小","方片","橘黄色"],"emoji":"🔸","text":"","type":1,"order":3886,"group":8,"subgroup":96,"version":0.6},{"annotation":"蓝色小菱形","name":"SMALL BLUE DIAMOND","hexcode":"1F539","shortcodes":["small_blue_diamond"],"tags":["小","方片","蓝色"],"emoji":"🔹","text":"","type":1,"order":3887,"group":8,"subgroup":96,"version":0.6},{"annotation":"红色正三角","name":"UP-POINTING RED TRIANGLE","hexcode":"1F53A","shortcodes":["up_red_triangle"],"tags":["三角形","向上","正三角","红色"],"emoji":"🔺","text":"","type":1,"order":3888,"group":8,"subgroup":96,"version":0.6},{"annotation":"红色倒三角","name":"DOWN-POINTING RED TRIANGLE","hexcode":"1F53B","shortcodes":["down_red_triangle"],"tags":["三角形","倒三角","向下","红色"],"emoji":"🔻","text":"","type":1,"order":3889,"group":8,"subgroup":96,"version":0.6},{"annotation":"带圆点的菱形","name":"DIAMOND SHAPE WITH A DOT INSIDE","hexcode":"1F4A0","shortcodes":["diamond_dot"],"tags":["中心","内部","圆","梅花形"],"emoji":"💠","text":"","type":1,"order":3890,"group":8,"subgroup":96,"version":0.6},{"annotation":"单选按钮","name":"RADIO BUTTON","hexcode":"1F518","shortcodes":["radio_button"],"tags":["单独","圆心","按键","选中"],"emoji":"🔘","text":"","type":1,"order":3891,"group":8,"subgroup":96,"version":0.6},{"annotation":"白色方形按钮","name":"WHITE SQUARE BUTTON","hexcode":"1F533","shortcodes":["white_square_button"],"tags":["按钮","白线方形按钮","白线正方形按钮","白色正方形按钮","白边线方形按钮","白边线正方形按钮"],"emoji":"🔳","text":"","type":1,"order":3892,"group":8,"subgroup":96,"version":0.6},{"annotation":"黑色方形按钮","name":"BLACK SQUARE BUTTON","hexcode":"1F532","shortcodes":["black_square_button"],"tags":["按钮","黑线方形按钮","黑线正方形按钮","黑色正方形按钮","黑边线方形按钮","黑边线正方形按钮"],"emoji":"🔲","text":"","type":1,"order":3893,"group":8,"subgroup":96,"version":0.6},{"annotation":"终点旗","name":"CHEQUERED FLAG","hexcode":"1F3C1","shortcodes":["checkered_flag"],"tags":["格子旗"],"emoji":"🏁","text":"","type":1,"order":3894,"group":9,"subgroup":97,"version":0.6},{"annotation":"三角旗","name":"TRIANGULAR FLAG ON POST","hexcode":"1F6A9","shortcodes":["triangle_flag"],"tags":["升旗","旗","旗杆上的三角旗","旗杆上的旗帜","红色旗帜"],"emoji":"🚩","text":"","type":1,"order":3895,"group":9,"subgroup":97,"version":0.6},{"annotation":"交叉旗","name":"CROSSED FLAGS","hexcode":"1F38C","shortcodes":["crossed_flags"],"tags":["对叉","旗帜","日本"],"emoji":"🎌","text":"","type":1,"order":3896,"group":9,"subgroup":97,"version":0.6},{"annotation":"举黑旗","name":"WAVING BLACK FLAG","hexcode":"1F3F4","shortcodes":["black_flag"],"tags":["黑旗","黑色旗","黑色旗子","黑色旗帜"],"emoji":"🏴","text":"","type":1,"order":3897,"group":9,"subgroup":97,"version":1},{"annotation":"举白旗","name":"WAVING WHITE FLAG","hexcode":"1F3F3","shortcodes":["white_flag"],"tags":["白旗","白色旗子","白色旗帜"],"emoji":"🏳️","text":"🏳︎","type":0,"order":3899,"group":9,"subgroup":97,"version":0.7},{"annotation":"彩虹旗","name":"WAVING WHITE FLAG, RAINBOW","hexcode":"1F3F3-FE0F-200D-1F308","shortcodes":["rainbow_flag"],"tags":["同性","多色","旗帜"],"emoji":"🏳️‍🌈","text":"","type":1,"order":3900,"group":9,"subgroup":97,"version":4},{"annotation":"跨性别旗","name":"WAVING WHITE FLAG, MALE WITH STROKE AND MALE AND FEMALE SIGN","hexcode":"1F3F3-FE0F-200D-26A7-FE0F","shortcodes":["trans_flag"],"tags":["旗帜","跨性别"],"emoji":"🏳️‍⚧️","text":"","type":1,"order":3902,"group":9,"subgroup":97,"version":13},{"annotation":"海盗旗","name":"WAVING BLACK FLAG, SKULL AND CROSSBONES","hexcode":"1F3F4-200D-2620-FE0F","shortcodes":["pirate_flag","jolly_roger"],"tags":["掠夺","海上","财宝","骷髅"],"emoji":"🏴‍☠️","text":"","type":1,"order":3906,"group":9,"subgroup":97,"version":11},{"annotation":"旗: 阿森松岛","name":"FLAG: ASCENSION ISLAND","hexcode":"1F1E6-1F1E8","shortcodes":["flag_ac"],"tags":["AC","旗"],"emoji":"🇦🇨","text":"","type":1,"order":3908,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 安道尔","name":"FLAG: ANDORRA","hexcode":"1F1E6-1F1E9","shortcodes":["flag_ad"],"tags":["AD","旗"],"emoji":"🇦🇩","text":"","type":1,"order":3909,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 阿拉伯联合酋长国","name":"FLAG: UNITED ARAB EMIRATES","hexcode":"1F1E6-1F1EA","shortcodes":["flag_ae"],"tags":["AE","旗"],"emoji":"🇦🇪","text":"","type":1,"order":3910,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 阿富汗","name":"FLAG: AFGHANISTAN","hexcode":"1F1E6-1F1EB","shortcodes":["flag_af"],"tags":["AF","旗"],"emoji":"🇦🇫","text":"","type":1,"order":3911,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 安提瓜和巴布达","name":"FLAG: ANTIGUA & BARBUDA","hexcode":"1F1E6-1F1EC","shortcodes":["flag_ag"],"tags":["AG","旗"],"emoji":"🇦🇬","text":"","type":1,"order":3912,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 安圭拉","name":"FLAG: ANGUILLA","hexcode":"1F1E6-1F1EE","shortcodes":["flag_ai"],"tags":["AI","旗"],"emoji":"🇦🇮","text":"","type":1,"order":3913,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 阿尔巴尼亚","name":"FLAG: ALBANIA","hexcode":"1F1E6-1F1F1","shortcodes":["flag_al"],"tags":["AL","旗"],"emoji":"🇦🇱","text":"","type":1,"order":3914,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 亚美尼亚","name":"FLAG: ARMENIA","hexcode":"1F1E6-1F1F2","shortcodes":["flag_am"],"tags":["AM","旗"],"emoji":"🇦🇲","text":"","type":1,"order":3915,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 安哥拉","name":"FLAG: ANGOLA","hexcode":"1F1E6-1F1F4","shortcodes":["flag_ao"],"tags":["AO","旗"],"emoji":"🇦🇴","text":"","type":1,"order":3916,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 南极洲","name":"FLAG: ANTARCTICA","hexcode":"1F1E6-1F1F6","shortcodes":["flag_aq"],"tags":["AQ","旗"],"emoji":"🇦🇶","text":"","type":1,"order":3917,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 阿根廷","name":"FLAG: ARGENTINA","hexcode":"1F1E6-1F1F7","shortcodes":["flag_ar"],"tags":["AR","旗"],"emoji":"🇦🇷","text":"","type":1,"order":3918,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 美属萨摩亚","name":"FLAG: AMERICAN SAMOA","hexcode":"1F1E6-1F1F8","shortcodes":["flag_as"],"tags":["AS","旗"],"emoji":"🇦🇸","text":"","type":1,"order":3919,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 奥地利","name":"FLAG: AUSTRIA","hexcode":"1F1E6-1F1F9","shortcodes":["flag_at"],"tags":["AT","旗"],"emoji":"🇦🇹","text":"","type":1,"order":3920,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 澳大利亚","name":"FLAG: AUSTRALIA","hexcode":"1F1E6-1F1FA","shortcodes":["flag_au"],"tags":["AU","旗"],"emoji":"🇦🇺","text":"","type":1,"order":3921,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 阿鲁巴","name":"FLAG: ARUBA","hexcode":"1F1E6-1F1FC","shortcodes":["flag_aw"],"tags":["AW","旗"],"emoji":"🇦🇼","text":"","type":1,"order":3922,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 奥兰群岛","name":"FLAG: ÅLAND ISLANDS","hexcode":"1F1E6-1F1FD","shortcodes":["flag_ax"],"tags":["AX","旗"],"emoji":"🇦🇽","text":"","type":1,"order":3923,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 阿塞拜疆","name":"FLAG: AZERBAIJAN","hexcode":"1F1E6-1F1FF","shortcodes":["flag_az"],"tags":["AZ","旗"],"emoji":"🇦🇿","text":"","type":1,"order":3924,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 波斯尼亚和黑塞哥维那","name":"FLAG: BOSNIA & HERZEGOVINA","hexcode":"1F1E7-1F1E6","shortcodes":["flag_ba"],"tags":["BA","旗"],"emoji":"🇧🇦","text":"","type":1,"order":3925,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 巴巴多斯","name":"FLAG: BARBADOS","hexcode":"1F1E7-1F1E7","shortcodes":["flag_bb"],"tags":["BB","旗"],"emoji":"🇧🇧","text":"","type":1,"order":3926,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 孟加拉国","name":"FLAG: BANGLADESH","hexcode":"1F1E7-1F1E9","shortcodes":["flag_bd"],"tags":["BD","旗"],"emoji":"🇧🇩","text":"","type":1,"order":3927,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 比利时","name":"FLAG: BELGIUM","hexcode":"1F1E7-1F1EA","shortcodes":["flag_be"],"tags":["BE","旗"],"emoji":"🇧🇪","text":"","type":1,"order":3928,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 布基纳法索","name":"FLAG: BURKINA FASO","hexcode":"1F1E7-1F1EB","shortcodes":["flag_bf"],"tags":["BF","旗"],"emoji":"🇧🇫","text":"","type":1,"order":3929,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 保加利亚","name":"FLAG: BULGARIA","hexcode":"1F1E7-1F1EC","shortcodes":["flag_bg"],"tags":["BG","旗"],"emoji":"🇧🇬","text":"","type":1,"order":3930,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 巴林","name":"FLAG: BAHRAIN","hexcode":"1F1E7-1F1ED","shortcodes":["flag_bh"],"tags":["BH","旗"],"emoji":"🇧🇭","text":"","type":1,"order":3931,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 布隆迪","name":"FLAG: BURUNDI","hexcode":"1F1E7-1F1EE","shortcodes":["flag_bi"],"tags":["BI","旗"],"emoji":"🇧🇮","text":"","type":1,"order":3932,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 贝宁","name":"FLAG: BENIN","hexcode":"1F1E7-1F1EF","shortcodes":["flag_bj"],"tags":["BJ","旗"],"emoji":"🇧🇯","text":"","type":1,"order":3933,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 圣巴泰勒米","name":"FLAG: ST. BARTHÉLEMY","hexcode":"1F1E7-1F1F1","shortcodes":["flag_bl"],"tags":["BL","旗"],"emoji":"🇧🇱","text":"","type":1,"order":3934,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 百慕大","name":"FLAG: BERMUDA","hexcode":"1F1E7-1F1F2","shortcodes":["flag_bm"],"tags":["BM","旗"],"emoji":"🇧🇲","text":"","type":1,"order":3935,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 文莱","name":"FLAG: BRUNEI","hexcode":"1F1E7-1F1F3","shortcodes":["flag_bn"],"tags":["BN","旗"],"emoji":"🇧🇳","text":"","type":1,"order":3936,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 玻利维亚","name":"FLAG: BOLIVIA","hexcode":"1F1E7-1F1F4","shortcodes":["flag_bo"],"tags":["BO","旗"],"emoji":"🇧🇴","text":"","type":1,"order":3937,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 荷属加勒比区","name":"FLAG: CARIBBEAN NETHERLANDS","hexcode":"1F1E7-1F1F6","shortcodes":["flag_bq"],"tags":["BQ","旗"],"emoji":"🇧🇶","text":"","type":1,"order":3938,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 巴西","name":"FLAG: BRAZIL","hexcode":"1F1E7-1F1F7","shortcodes":["flag_br"],"tags":["BR","旗"],"emoji":"🇧🇷","text":"","type":1,"order":3939,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 巴哈马","name":"FLAG: BAHAMAS","hexcode":"1F1E7-1F1F8","shortcodes":["flag_bs"],"tags":["BS","旗"],"emoji":"🇧🇸","text":"","type":1,"order":3940,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 不丹","name":"FLAG: BHUTAN","hexcode":"1F1E7-1F1F9","shortcodes":["flag_bt"],"tags":["BT","旗"],"emoji":"🇧🇹","text":"","type":1,"order":3941,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 布韦岛","name":"FLAG: BOUVET ISLAND","hexcode":"1F1E7-1F1FB","shortcodes":["flag_bv"],"tags":["BV","旗"],"emoji":"🇧🇻","text":"","type":1,"order":3942,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 博茨瓦纳","name":"FLAG: BOTSWANA","hexcode":"1F1E7-1F1FC","shortcodes":["flag_bw"],"tags":["BW","旗"],"emoji":"🇧🇼","text":"","type":1,"order":3943,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 白俄罗斯","name":"FLAG: BELARUS","hexcode":"1F1E7-1F1FE","shortcodes":["flag_by"],"tags":["BY","旗"],"emoji":"🇧🇾","text":"","type":1,"order":3944,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 伯利兹","name":"FLAG: BELIZE","hexcode":"1F1E7-1F1FF","shortcodes":["flag_bz"],"tags":["BZ","旗"],"emoji":"🇧🇿","text":"","type":1,"order":3945,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 加拿大","name":"FLAG: CANADA","hexcode":"1F1E8-1F1E6","shortcodes":["flag_ca"],"tags":["CA","旗"],"emoji":"🇨🇦","text":"","type":1,"order":3946,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 科科斯(基林)群岛","name":"FLAG: COCOS (KEELING) ISLANDS","hexcode":"1F1E8-1F1E8","shortcodes":["flag_cc"],"tags":["CC","旗"],"emoji":"🇨🇨","text":"","type":1,"order":3947,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 刚果(金)","name":"FLAG: CONGO - KINSHASA","hexcode":"1F1E8-1F1E9","shortcodes":["flag_cd"],"tags":["CD","旗"],"emoji":"🇨🇩","text":"","type":1,"order":3948,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 中非共和国","name":"FLAG: CENTRAL AFRICAN REPUBLIC","hexcode":"1F1E8-1F1EB","shortcodes":["flag_cf"],"tags":["CF","旗"],"emoji":"🇨🇫","text":"","type":1,"order":3949,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 刚果(布)","name":"FLAG: CONGO - BRAZZAVILLE","hexcode":"1F1E8-1F1EC","shortcodes":["flag_cg"],"tags":["CG","旗"],"emoji":"🇨🇬","text":"","type":1,"order":3950,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 瑞士","name":"FLAG: SWITZERLAND","hexcode":"1F1E8-1F1ED","shortcodes":["flag_ch"],"tags":["CH","旗"],"emoji":"🇨🇭","text":"","type":1,"order":3951,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 科特迪瓦","name":"FLAG: CÔTE D’IVOIRE","hexcode":"1F1E8-1F1EE","shortcodes":["flag_ci"],"tags":["CI","旗"],"emoji":"🇨🇮","text":"","type":1,"order":3952,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 库克群岛","name":"FLAG: COOK ISLANDS","hexcode":"1F1E8-1F1F0","shortcodes":["flag_ck"],"tags":["CK","旗"],"emoji":"🇨🇰","text":"","type":1,"order":3953,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 智利","name":"FLAG: CHILE","hexcode":"1F1E8-1F1F1","shortcodes":["flag_cl"],"tags":["CL","旗"],"emoji":"🇨🇱","text":"","type":1,"order":3954,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 喀麦隆","name":"FLAG: CAMEROON","hexcode":"1F1E8-1F1F2","shortcodes":["flag_cm"],"tags":["CM","旗"],"emoji":"🇨🇲","text":"","type":1,"order":3955,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 中国","name":"FLAG: CHINA","hexcode":"1F1E8-1F1F3","shortcodes":["flag_cn"],"tags":["CN","旗"],"emoji":"🇨🇳","text":"","type":1,"order":3956,"group":9,"subgroup":98,"version":0.6},{"annotation":"旗: 哥伦比亚","name":"FLAG: COLOMBIA","hexcode":"1F1E8-1F1F4","shortcodes":["flag_co"],"tags":["CO","旗"],"emoji":"🇨🇴","text":"","type":1,"order":3957,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 克利珀顿岛","name":"FLAG: CLIPPERTON ISLAND","hexcode":"1F1E8-1F1F5","shortcodes":["flag_cp"],"tags":["CP","旗"],"emoji":"🇨🇵","text":"","type":1,"order":3958,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 哥斯达黎加","name":"FLAG: COSTA RICA","hexcode":"1F1E8-1F1F7","shortcodes":["flag_cr"],"tags":["CR","旗"],"emoji":"🇨🇷","text":"","type":1,"order":3959,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 古巴","name":"FLAG: CUBA","hexcode":"1F1E8-1F1FA","shortcodes":["flag_cu"],"tags":["CU","旗"],"emoji":"🇨🇺","text":"","type":1,"order":3960,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 佛得角","name":"FLAG: CAPE VERDE","hexcode":"1F1E8-1F1FB","shortcodes":["flag_cv"],"tags":["CV","旗"],"emoji":"🇨🇻","text":"","type":1,"order":3961,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 库拉索","name":"FLAG: CURAÇAO","hexcode":"1F1E8-1F1FC","shortcodes":["flag_cw"],"tags":["CW","旗"],"emoji":"🇨🇼","text":"","type":1,"order":3962,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 圣诞岛","name":"FLAG: CHRISTMAS ISLAND","hexcode":"1F1E8-1F1FD","shortcodes":["flag_cx"],"tags":["CX","旗"],"emoji":"🇨🇽","text":"","type":1,"order":3963,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 塞浦路斯","name":"FLAG: CYPRUS","hexcode":"1F1E8-1F1FE","shortcodes":["flag_cy"],"tags":["CY","旗"],"emoji":"🇨🇾","text":"","type":1,"order":3964,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 捷克","name":"FLAG: CZECHIA","hexcode":"1F1E8-1F1FF","shortcodes":["flag_cz"],"tags":["CZ","旗"],"emoji":"🇨🇿","text":"","type":1,"order":3965,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 德国","name":"FLAG: GERMANY","hexcode":"1F1E9-1F1EA","shortcodes":["flag_de"],"tags":["DE","旗"],"emoji":"🇩🇪","text":"","type":1,"order":3966,"group":9,"subgroup":98,"version":0.6},{"annotation":"旗: 迪戈加西亚岛","name":"FLAG: DIEGO GARCIA","hexcode":"1F1E9-1F1EC","shortcodes":["flag_dg"],"tags":["DG","旗"],"emoji":"🇩🇬","text":"","type":1,"order":3967,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 吉布提","name":"FLAG: DJIBOUTI","hexcode":"1F1E9-1F1EF","shortcodes":["flag_dj"],"tags":["DJ","旗"],"emoji":"🇩🇯","text":"","type":1,"order":3968,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 丹麦","name":"FLAG: DENMARK","hexcode":"1F1E9-1F1F0","shortcodes":["flag_dk"],"tags":["DK","旗"],"emoji":"🇩🇰","text":"","type":1,"order":3969,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 多米尼克","name":"FLAG: DOMINICA","hexcode":"1F1E9-1F1F2","shortcodes":["flag_dm"],"tags":["DM","旗"],"emoji":"🇩🇲","text":"","type":1,"order":3970,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 多米尼加共和国","name":"FLAG: DOMINICAN REPUBLIC","hexcode":"1F1E9-1F1F4","shortcodes":["flag_do"],"tags":["DO","旗"],"emoji":"🇩🇴","text":"","type":1,"order":3971,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 阿尔及利亚","name":"FLAG: ALGERIA","hexcode":"1F1E9-1F1FF","shortcodes":["flag_dz"],"tags":["DZ","旗"],"emoji":"🇩🇿","text":"","type":1,"order":3972,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 休达及梅利利亚","name":"FLAG: CEUTA & MELILLA","hexcode":"1F1EA-1F1E6","shortcodes":["flag_ea"],"tags":["EA","旗"],"emoji":"🇪🇦","text":"","type":1,"order":3973,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 厄瓜多尔","name":"FLAG: ECUADOR","hexcode":"1F1EA-1F1E8","shortcodes":["flag_ec"],"tags":["EC","旗"],"emoji":"🇪🇨","text":"","type":1,"order":3974,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 爱沙尼亚","name":"FLAG: ESTONIA","hexcode":"1F1EA-1F1EA","shortcodes":["flag_ee"],"tags":["EE","旗"],"emoji":"🇪🇪","text":"","type":1,"order":3975,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 埃及","name":"FLAG: EGYPT","hexcode":"1F1EA-1F1EC","shortcodes":["flag_eg"],"tags":["EG","旗"],"emoji":"🇪🇬","text":"","type":1,"order":3976,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 西撒哈拉","name":"FLAG: WESTERN SAHARA","hexcode":"1F1EA-1F1ED","shortcodes":["flag_eh"],"tags":["EH","旗"],"emoji":"🇪🇭","text":"","type":1,"order":3977,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 厄立特里亚","name":"FLAG: ERITREA","hexcode":"1F1EA-1F1F7","shortcodes":["flag_er"],"tags":["ER","旗"],"emoji":"🇪🇷","text":"","type":1,"order":3978,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 西班牙","name":"FLAG: SPAIN","hexcode":"1F1EA-1F1F8","shortcodes":["flag_es"],"tags":["ES","旗"],"emoji":"🇪🇸","text":"","type":1,"order":3979,"group":9,"subgroup":98,"version":0.6},{"annotation":"旗: 埃塞俄比亚","name":"FLAG: ETHIOPIA","hexcode":"1F1EA-1F1F9","shortcodes":["flag_et"],"tags":["ET","旗"],"emoji":"🇪🇹","text":"","type":1,"order":3980,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 欧盟","name":"FLAG: EUROPEAN UNION","hexcode":"1F1EA-1F1FA","shortcodes":["flag_eu"],"tags":["EU","旗"],"emoji":"🇪🇺","text":"","type":1,"order":3981,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 芬兰","name":"FLAG: FINLAND","hexcode":"1F1EB-1F1EE","shortcodes":["flag_fi"],"tags":["FI","旗"],"emoji":"🇫🇮","text":"","type":1,"order":3982,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 斐济","name":"FLAG: FIJI","hexcode":"1F1EB-1F1EF","shortcodes":["flag_fj"],"tags":["FJ","旗"],"emoji":"🇫🇯","text":"","type":1,"order":3983,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 福克兰群岛","name":"FLAG: FALKLAND ISLANDS","hexcode":"1F1EB-1F1F0","shortcodes":["flag_fk"],"tags":["FK","旗"],"emoji":"🇫🇰","text":"","type":1,"order":3984,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 密克罗尼西亚","name":"FLAG: MICRONESIA","hexcode":"1F1EB-1F1F2","shortcodes":["flag_fm"],"tags":["FM","旗"],"emoji":"🇫🇲","text":"","type":1,"order":3985,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 法罗群岛","name":"FLAG: FAROE ISLANDS","hexcode":"1F1EB-1F1F4","shortcodes":["flag_fo"],"tags":["FO","旗"],"emoji":"🇫🇴","text":"","type":1,"order":3986,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 法国","name":"FLAG: FRANCE","hexcode":"1F1EB-1F1F7","shortcodes":["flag_fr"],"tags":["FR","旗"],"emoji":"🇫🇷","text":"","type":1,"order":3987,"group":9,"subgroup":98,"version":0.6},{"annotation":"旗: 加蓬","name":"FLAG: GABON","hexcode":"1F1EC-1F1E6","shortcodes":["flag_ga"],"tags":["GA","旗"],"emoji":"🇬🇦","text":"","type":1,"order":3988,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 英国","name":"FLAG: UNITED KINGDOM","hexcode":"1F1EC-1F1E7","shortcodes":["flag_gb"],"tags":["GB","旗"],"emoji":"🇬🇧","text":"","type":1,"order":3989,"group":9,"subgroup":98,"version":0.6},{"annotation":"旗: 格林纳达","name":"FLAG: GRENADA","hexcode":"1F1EC-1F1E9","shortcodes":["flag_gd"],"tags":["GD","旗"],"emoji":"🇬🇩","text":"","type":1,"order":3990,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 格鲁吉亚","name":"FLAG: GEORGIA","hexcode":"1F1EC-1F1EA","shortcodes":["flag_ge"],"tags":["GE","旗"],"emoji":"🇬🇪","text":"","type":1,"order":3991,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 法属圭亚那","name":"FLAG: FRENCH GUIANA","hexcode":"1F1EC-1F1EB","shortcodes":["flag_gf"],"tags":["GF","旗"],"emoji":"🇬🇫","text":"","type":1,"order":3992,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 根西岛","name":"FLAG: GUERNSEY","hexcode":"1F1EC-1F1EC","shortcodes":["flag_gg"],"tags":["GG","旗"],"emoji":"🇬🇬","text":"","type":1,"order":3993,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 加纳","name":"FLAG: GHANA","hexcode":"1F1EC-1F1ED","shortcodes":["flag_gh"],"tags":["GH","旗"],"emoji":"🇬🇭","text":"","type":1,"order":3994,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 直布罗陀","name":"FLAG: GIBRALTAR","hexcode":"1F1EC-1F1EE","shortcodes":["flag_gi"],"tags":["GI","旗"],"emoji":"🇬🇮","text":"","type":1,"order":3995,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 格陵兰","name":"FLAG: GREENLAND","hexcode":"1F1EC-1F1F1","shortcodes":["flag_gl"],"tags":["GL","旗"],"emoji":"🇬🇱","text":"","type":1,"order":3996,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 冈比亚","name":"FLAG: GAMBIA","hexcode":"1F1EC-1F1F2","shortcodes":["flag_gm"],"tags":["GM","旗"],"emoji":"🇬🇲","text":"","type":1,"order":3997,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 几内亚","name":"FLAG: GUINEA","hexcode":"1F1EC-1F1F3","shortcodes":["flag_gn"],"tags":["GN","旗"],"emoji":"🇬🇳","text":"","type":1,"order":3998,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 瓜德罗普","name":"FLAG: GUADELOUPE","hexcode":"1F1EC-1F1F5","shortcodes":["flag_gp"],"tags":["GP","旗"],"emoji":"🇬🇵","text":"","type":1,"order":3999,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 赤道几内亚","name":"FLAG: EQUATORIAL GUINEA","hexcode":"1F1EC-1F1F6","shortcodes":["flag_gq"],"tags":["GQ","旗"],"emoji":"🇬🇶","text":"","type":1,"order":4000,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 希腊","name":"FLAG: GREECE","hexcode":"1F1EC-1F1F7","shortcodes":["flag_gr"],"tags":["GR","旗"],"emoji":"🇬🇷","text":"","type":1,"order":4001,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 南乔治亚和南桑威奇群岛","name":"FLAG: SOUTH GEORGIA & SOUTH SANDWICH ISLANDS","hexcode":"1F1EC-1F1F8","shortcodes":["flag_gs"],"tags":["GS","旗"],"emoji":"🇬🇸","text":"","type":1,"order":4002,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 危地马拉","name":"FLAG: GUATEMALA","hexcode":"1F1EC-1F1F9","shortcodes":["flag_gt"],"tags":["GT","旗"],"emoji":"🇬🇹","text":"","type":1,"order":4003,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 关岛","name":"FLAG: GUAM","hexcode":"1F1EC-1F1FA","shortcodes":["flag_gu"],"tags":["GU","旗"],"emoji":"🇬🇺","text":"","type":1,"order":4004,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 几内亚比绍","name":"FLAG: GUINEA-BISSAU","hexcode":"1F1EC-1F1FC","shortcodes":["flag_gw"],"tags":["GW","旗"],"emoji":"🇬🇼","text":"","type":1,"order":4005,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 圭亚那","name":"FLAG: GUYANA","hexcode":"1F1EC-1F1FE","shortcodes":["flag_gy"],"tags":["GY","旗"],"emoji":"🇬🇾","text":"","type":1,"order":4006,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 中国香港特别行政区","name":"FLAG: HONG KONG SAR CHINA","hexcode":"1F1ED-1F1F0","shortcodes":["flag_hk"],"tags":["HK","旗"],"emoji":"🇭🇰","text":"","type":1,"order":4007,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 赫德岛和麦克唐纳群岛","name":"FLAG: HEARD & MCDONALD ISLANDS","hexcode":"1F1ED-1F1F2","shortcodes":["flag_hm"],"tags":["HM","旗"],"emoji":"🇭🇲","text":"","type":1,"order":4008,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 洪都拉斯","name":"FLAG: HONDURAS","hexcode":"1F1ED-1F1F3","shortcodes":["flag_hn"],"tags":["HN","旗"],"emoji":"🇭🇳","text":"","type":1,"order":4009,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 克罗地亚","name":"FLAG: CROATIA","hexcode":"1F1ED-1F1F7","shortcodes":["flag_hr"],"tags":["HR","旗"],"emoji":"🇭🇷","text":"","type":1,"order":4010,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 海地","name":"FLAG: HAITI","hexcode":"1F1ED-1F1F9","shortcodes":["flag_ht"],"tags":["HT","旗"],"emoji":"🇭🇹","text":"","type":1,"order":4011,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 匈牙利","name":"FLAG: HUNGARY","hexcode":"1F1ED-1F1FA","shortcodes":["flag_hu"],"tags":["HU","旗"],"emoji":"🇭🇺","text":"","type":1,"order":4012,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 加纳利群岛","name":"FLAG: CANARY ISLANDS","hexcode":"1F1EE-1F1E8","shortcodes":["flag_ic"],"tags":["IC","旗"],"emoji":"🇮🇨","text":"","type":1,"order":4013,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 印度尼西亚","name":"FLAG: INDONESIA","hexcode":"1F1EE-1F1E9","shortcodes":["flag_id"],"tags":["ID","旗"],"emoji":"🇮🇩","text":"","type":1,"order":4014,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 爱尔兰","name":"FLAG: IRELAND","hexcode":"1F1EE-1F1EA","shortcodes":["flag_ie"],"tags":["IE","旗"],"emoji":"🇮🇪","text":"","type":1,"order":4015,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 以色列","name":"FLAG: ISRAEL","hexcode":"1F1EE-1F1F1","shortcodes":["flag_il"],"tags":["IL","旗"],"emoji":"🇮🇱","text":"","type":1,"order":4016,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 马恩岛","name":"FLAG: ISLE OF MAN","hexcode":"1F1EE-1F1F2","shortcodes":["flag_im"],"tags":["IM","旗"],"emoji":"🇮🇲","text":"","type":1,"order":4017,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 印度","name":"FLAG: INDIA","hexcode":"1F1EE-1F1F3","shortcodes":["flag_in"],"tags":["IN","旗"],"emoji":"🇮🇳","text":"","type":1,"order":4018,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 英属印度洋领地","name":"FLAG: BRITISH INDIAN OCEAN TERRITORY","hexcode":"1F1EE-1F1F4","shortcodes":["flag_io"],"tags":["IO","旗"],"emoji":"🇮🇴","text":"","type":1,"order":4019,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 伊拉克","name":"FLAG: IRAQ","hexcode":"1F1EE-1F1F6","shortcodes":["flag_iq"],"tags":["IQ","旗"],"emoji":"🇮🇶","text":"","type":1,"order":4020,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 伊朗","name":"FLAG: IRAN","hexcode":"1F1EE-1F1F7","shortcodes":["flag_ir"],"tags":["IR","旗"],"emoji":"🇮🇷","text":"","type":1,"order":4021,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 冰岛","name":"FLAG: ICELAND","hexcode":"1F1EE-1F1F8","shortcodes":["flag_is"],"tags":["IS","旗"],"emoji":"🇮🇸","text":"","type":1,"order":4022,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 意大利","name":"FLAG: ITALY","hexcode":"1F1EE-1F1F9","shortcodes":["flag_it"],"tags":["IT","旗"],"emoji":"🇮🇹","text":"","type":1,"order":4023,"group":9,"subgroup":98,"version":0.6},{"annotation":"旗: 泽西岛","name":"FLAG: JERSEY","hexcode":"1F1EF-1F1EA","shortcodes":["flag_je"],"tags":["JE","旗"],"emoji":"🇯🇪","text":"","type":1,"order":4024,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 牙买加","name":"FLAG: JAMAICA","hexcode":"1F1EF-1F1F2","shortcodes":["flag_jm"],"tags":["JM","旗"],"emoji":"🇯🇲","text":"","type":1,"order":4025,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 约旦","name":"FLAG: JORDAN","hexcode":"1F1EF-1F1F4","shortcodes":["flag_jo"],"tags":["JO","旗"],"emoji":"🇯🇴","text":"","type":1,"order":4026,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 日本","name":"FLAG: JAPAN","hexcode":"1F1EF-1F1F5","shortcodes":["flag_jp"],"tags":["JP","旗"],"emoji":"🇯🇵","text":"","type":1,"order":4027,"group":9,"subgroup":98,"version":0.6},{"annotation":"旗: 肯尼亚","name":"FLAG: KENYA","hexcode":"1F1F0-1F1EA","shortcodes":["flag_ke"],"tags":["KE","旗"],"emoji":"🇰🇪","text":"","type":1,"order":4028,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 吉尔吉斯斯坦","name":"FLAG: KYRGYZSTAN","hexcode":"1F1F0-1F1EC","shortcodes":["flag_kg"],"tags":["KG","旗"],"emoji":"🇰🇬","text":"","type":1,"order":4029,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 柬埔寨","name":"FLAG: CAMBODIA","hexcode":"1F1F0-1F1ED","shortcodes":["flag_kh"],"tags":["KH","旗"],"emoji":"🇰🇭","text":"","type":1,"order":4030,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 基里巴斯","name":"FLAG: KIRIBATI","hexcode":"1F1F0-1F1EE","shortcodes":["flag_ki"],"tags":["KI","旗"],"emoji":"🇰🇮","text":"","type":1,"order":4031,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 科摩罗","name":"FLAG: COMOROS","hexcode":"1F1F0-1F1F2","shortcodes":["flag_km"],"tags":["KM","旗"],"emoji":"🇰🇲","text":"","type":1,"order":4032,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 圣基茨和尼维斯","name":"FLAG: ST. KITTS & NEVIS","hexcode":"1F1F0-1F1F3","shortcodes":["flag_kn"],"tags":["KN","旗"],"emoji":"🇰🇳","text":"","type":1,"order":4033,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 朝鲜","name":"FLAG: NORTH KOREA","hexcode":"1F1F0-1F1F5","shortcodes":["flag_kp"],"tags":["KP","旗"],"emoji":"🇰🇵","text":"","type":1,"order":4034,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 韩国","name":"FLAG: SOUTH KOREA","hexcode":"1F1F0-1F1F7","shortcodes":["flag_kr"],"tags":["KR","旗"],"emoji":"🇰🇷","text":"","type":1,"order":4035,"group":9,"subgroup":98,"version":0.6},{"annotation":"旗: 科威特","name":"FLAG: KUWAIT","hexcode":"1F1F0-1F1FC","shortcodes":["flag_kw"],"tags":["KW","旗"],"emoji":"🇰🇼","text":"","type":1,"order":4036,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 开曼群岛","name":"FLAG: CAYMAN ISLANDS","hexcode":"1F1F0-1F1FE","shortcodes":["flag_ky"],"tags":["KY","旗"],"emoji":"🇰🇾","text":"","type":1,"order":4037,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 哈萨克斯坦","name":"FLAG: KAZAKHSTAN","hexcode":"1F1F0-1F1FF","shortcodes":["flag_kz"],"tags":["KZ","旗"],"emoji":"🇰🇿","text":"","type":1,"order":4038,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 老挝","name":"FLAG: LAOS","hexcode":"1F1F1-1F1E6","shortcodes":["flag_la"],"tags":["LA","旗"],"emoji":"🇱🇦","text":"","type":1,"order":4039,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 黎巴嫩","name":"FLAG: LEBANON","hexcode":"1F1F1-1F1E7","shortcodes":["flag_lb"],"tags":["LB","旗"],"emoji":"🇱🇧","text":"","type":1,"order":4040,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 圣卢西亚","name":"FLAG: ST. LUCIA","hexcode":"1F1F1-1F1E8","shortcodes":["flag_lc"],"tags":["LC","旗"],"emoji":"🇱🇨","text":"","type":1,"order":4041,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 列支敦士登","name":"FLAG: LIECHTENSTEIN","hexcode":"1F1F1-1F1EE","shortcodes":["flag_li"],"tags":["LI","旗"],"emoji":"🇱🇮","text":"","type":1,"order":4042,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 斯里兰卡","name":"FLAG: SRI LANKA","hexcode":"1F1F1-1F1F0","shortcodes":["flag_lk"],"tags":["LK","旗"],"emoji":"🇱🇰","text":"","type":1,"order":4043,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 利比里亚","name":"FLAG: LIBERIA","hexcode":"1F1F1-1F1F7","shortcodes":["flag_lr"],"tags":["LR","旗"],"emoji":"🇱🇷","text":"","type":1,"order":4044,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 莱索托","name":"FLAG: LESOTHO","hexcode":"1F1F1-1F1F8","shortcodes":["flag_ls"],"tags":["LS","旗"],"emoji":"🇱🇸","text":"","type":1,"order":4045,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 立陶宛","name":"FLAG: LITHUANIA","hexcode":"1F1F1-1F1F9","shortcodes":["flag_lt"],"tags":["LT","旗"],"emoji":"🇱🇹","text":"","type":1,"order":4046,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 卢森堡","name":"FLAG: LUXEMBOURG","hexcode":"1F1F1-1F1FA","shortcodes":["flag_lu"],"tags":["LU","旗"],"emoji":"🇱🇺","text":"","type":1,"order":4047,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 拉脱维亚","name":"FLAG: LATVIA","hexcode":"1F1F1-1F1FB","shortcodes":["flag_lv"],"tags":["LV","旗"],"emoji":"🇱🇻","text":"","type":1,"order":4048,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 利比亚","name":"FLAG: LIBYA","hexcode":"1F1F1-1F1FE","shortcodes":["flag_ly"],"tags":["LY","旗"],"emoji":"🇱🇾","text":"","type":1,"order":4049,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 摩洛哥","name":"FLAG: MOROCCO","hexcode":"1F1F2-1F1E6","shortcodes":["flag_ma"],"tags":["MA","旗"],"emoji":"🇲🇦","text":"","type":1,"order":4050,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 摩纳哥","name":"FLAG: MONACO","hexcode":"1F1F2-1F1E8","shortcodes":["flag_mc"],"tags":["MC","旗"],"emoji":"🇲🇨","text":"","type":1,"order":4051,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 摩尔多瓦","name":"FLAG: MOLDOVA","hexcode":"1F1F2-1F1E9","shortcodes":["flag_md"],"tags":["MD","旗"],"emoji":"🇲🇩","text":"","type":1,"order":4052,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 黑山","name":"FLAG: MONTENEGRO","hexcode":"1F1F2-1F1EA","shortcodes":["flag_me"],"tags":["ME","旗"],"emoji":"🇲🇪","text":"","type":1,"order":4053,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 法属圣马丁","name":"FLAG: ST. MARTIN","hexcode":"1F1F2-1F1EB","shortcodes":["flag_mf"],"tags":["MF","旗"],"emoji":"🇲🇫","text":"","type":1,"order":4054,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 马达加斯加","name":"FLAG: MADAGASCAR","hexcode":"1F1F2-1F1EC","shortcodes":["flag_mg"],"tags":["MG","旗"],"emoji":"🇲🇬","text":"","type":1,"order":4055,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 马绍尔群岛","name":"FLAG: MARSHALL ISLANDS","hexcode":"1F1F2-1F1ED","shortcodes":["flag_mh"],"tags":["MH","旗"],"emoji":"🇲🇭","text":"","type":1,"order":4056,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 北马其顿","name":"FLAG: NORTH MACEDONIA","hexcode":"1F1F2-1F1F0","shortcodes":["flag_mk"],"tags":["MK","旗"],"emoji":"🇲🇰","text":"","type":1,"order":4057,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 马里","name":"FLAG: MALI","hexcode":"1F1F2-1F1F1","shortcodes":["flag_ml"],"tags":["ML","旗"],"emoji":"🇲🇱","text":"","type":1,"order":4058,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 缅甸","name":"FLAG: MYANMAR (BURMA)","hexcode":"1F1F2-1F1F2","shortcodes":["flag_mm"],"tags":["MM","旗"],"emoji":"🇲🇲","text":"","type":1,"order":4059,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 蒙古","name":"FLAG: MONGOLIA","hexcode":"1F1F2-1F1F3","shortcodes":["flag_mn"],"tags":["MN","旗"],"emoji":"🇲🇳","text":"","type":1,"order":4060,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 中国澳门特别行政区","name":"FLAG: MACAO SAR CHINA","hexcode":"1F1F2-1F1F4","shortcodes":["flag_mo"],"tags":["MO","旗"],"emoji":"🇲🇴","text":"","type":1,"order":4061,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 北马里亚纳群岛","name":"FLAG: NORTHERN MARIANA ISLANDS","hexcode":"1F1F2-1F1F5","shortcodes":["flag_mp"],"tags":["MP","旗"],"emoji":"🇲🇵","text":"","type":1,"order":4062,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 马提尼克","name":"FLAG: MARTINIQUE","hexcode":"1F1F2-1F1F6","shortcodes":["flag_mq"],"tags":["MQ","旗"],"emoji":"🇲🇶","text":"","type":1,"order":4063,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 毛里塔尼亚","name":"FLAG: MAURITANIA","hexcode":"1F1F2-1F1F7","shortcodes":["flag_mr"],"tags":["MR","旗"],"emoji":"🇲🇷","text":"","type":1,"order":4064,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 蒙特塞拉特","name":"FLAG: MONTSERRAT","hexcode":"1F1F2-1F1F8","shortcodes":["flag_ms"],"tags":["MS","旗"],"emoji":"🇲🇸","text":"","type":1,"order":4065,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 马耳他","name":"FLAG: MALTA","hexcode":"1F1F2-1F1F9","shortcodes":["flag_mt"],"tags":["MT","旗"],"emoji":"🇲🇹","text":"","type":1,"order":4066,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 毛里求斯","name":"FLAG: MAURITIUS","hexcode":"1F1F2-1F1FA","shortcodes":["flag_mu"],"tags":["MU","旗"],"emoji":"🇲🇺","text":"","type":1,"order":4067,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 马尔代夫","name":"FLAG: MALDIVES","hexcode":"1F1F2-1F1FB","shortcodes":["flag_mv"],"tags":["MV","旗"],"emoji":"🇲🇻","text":"","type":1,"order":4068,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 马拉维","name":"FLAG: MALAWI","hexcode":"1F1F2-1F1FC","shortcodes":["flag_mw"],"tags":["MW","旗"],"emoji":"🇲🇼","text":"","type":1,"order":4069,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 墨西哥","name":"FLAG: MEXICO","hexcode":"1F1F2-1F1FD","shortcodes":["flag_mx"],"tags":["MX","旗"],"emoji":"🇲🇽","text":"","type":1,"order":4070,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 马来西亚","name":"FLAG: MALAYSIA","hexcode":"1F1F2-1F1FE","shortcodes":["flag_my"],"tags":["MY","旗"],"emoji":"🇲🇾","text":"","type":1,"order":4071,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 莫桑比克","name":"FLAG: MOZAMBIQUE","hexcode":"1F1F2-1F1FF","shortcodes":["flag_mz"],"tags":["MZ","旗"],"emoji":"🇲🇿","text":"","type":1,"order":4072,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 纳米比亚","name":"FLAG: NAMIBIA","hexcode":"1F1F3-1F1E6","shortcodes":["flag_na"],"tags":["NA","旗"],"emoji":"🇳🇦","text":"","type":1,"order":4073,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 新喀里多尼亚","name":"FLAG: NEW CALEDONIA","hexcode":"1F1F3-1F1E8","shortcodes":["flag_nc"],"tags":["NC","旗"],"emoji":"🇳🇨","text":"","type":1,"order":4074,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 尼日尔","name":"FLAG: NIGER","hexcode":"1F1F3-1F1EA","shortcodes":["flag_ne"],"tags":["NE","旗"],"emoji":"🇳🇪","text":"","type":1,"order":4075,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 诺福克岛","name":"FLAG: NORFOLK ISLAND","hexcode":"1F1F3-1F1EB","shortcodes":["flag_nf"],"tags":["NF","旗"],"emoji":"🇳🇫","text":"","type":1,"order":4076,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 尼日利亚","name":"FLAG: NIGERIA","hexcode":"1F1F3-1F1EC","shortcodes":["flag_ng"],"tags":["NG","旗"],"emoji":"🇳🇬","text":"","type":1,"order":4077,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 尼加拉瓜","name":"FLAG: NICARAGUA","hexcode":"1F1F3-1F1EE","shortcodes":["flag_ni"],"tags":["NI","旗"],"emoji":"🇳🇮","text":"","type":1,"order":4078,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 荷兰","name":"FLAG: NETHERLANDS","hexcode":"1F1F3-1F1F1","shortcodes":["flag_nl"],"tags":["NL","旗"],"emoji":"🇳🇱","text":"","type":1,"order":4079,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 挪威","name":"FLAG: NORWAY","hexcode":"1F1F3-1F1F4","shortcodes":["flag_no"],"tags":["NO","旗"],"emoji":"🇳🇴","text":"","type":1,"order":4080,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 尼泊尔","name":"FLAG: NEPAL","hexcode":"1F1F3-1F1F5","shortcodes":["flag_np"],"tags":["NP","旗"],"emoji":"🇳🇵","text":"","type":1,"order":4081,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 瑙鲁","name":"FLAG: NAURU","hexcode":"1F1F3-1F1F7","shortcodes":["flag_nr"],"tags":["NR","旗"],"emoji":"🇳🇷","text":"","type":1,"order":4082,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 纽埃","name":"FLAG: NIUE","hexcode":"1F1F3-1F1FA","shortcodes":["flag_nu"],"tags":["NU","旗"],"emoji":"🇳🇺","text":"","type":1,"order":4083,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 新西兰","name":"FLAG: NEW ZEALAND","hexcode":"1F1F3-1F1FF","shortcodes":["flag_nz"],"tags":["NZ","旗"],"emoji":"🇳🇿","text":"","type":1,"order":4084,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 阿曼","name":"FLAG: OMAN","hexcode":"1F1F4-1F1F2","shortcodes":["flag_om"],"tags":["OM","旗"],"emoji":"🇴🇲","text":"","type":1,"order":4085,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 巴拿马","name":"FLAG: PANAMA","hexcode":"1F1F5-1F1E6","shortcodes":["flag_pa"],"tags":["PA","旗"],"emoji":"🇵🇦","text":"","type":1,"order":4086,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 秘鲁","name":"FLAG: PERU","hexcode":"1F1F5-1F1EA","shortcodes":["flag_pe"],"tags":["PE","旗"],"emoji":"🇵🇪","text":"","type":1,"order":4087,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 法属波利尼西亚","name":"FLAG: FRENCH POLYNESIA","hexcode":"1F1F5-1F1EB","shortcodes":["flag_pf"],"tags":["PF","旗"],"emoji":"🇵🇫","text":"","type":1,"order":4088,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 巴布亚新几内亚","name":"FLAG: PAPUA NEW GUINEA","hexcode":"1F1F5-1F1EC","shortcodes":["flag_pg"],"tags":["PG","旗"],"emoji":"🇵🇬","text":"","type":1,"order":4089,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 菲律宾","name":"FLAG: PHILIPPINES","hexcode":"1F1F5-1F1ED","shortcodes":["flag_ph"],"tags":["PH","旗"],"emoji":"🇵🇭","text":"","type":1,"order":4090,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 巴基斯坦","name":"FLAG: PAKISTAN","hexcode":"1F1F5-1F1F0","shortcodes":["flag_pk"],"tags":["PK","旗"],"emoji":"🇵🇰","text":"","type":1,"order":4091,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 波兰","name":"FLAG: POLAND","hexcode":"1F1F5-1F1F1","shortcodes":["flag_pl"],"tags":["PL","旗"],"emoji":"🇵🇱","text":"","type":1,"order":4092,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 圣皮埃尔和密克隆群岛","name":"FLAG: ST. PIERRE & MIQUELON","hexcode":"1F1F5-1F1F2","shortcodes":["flag_pm"],"tags":["PM","旗"],"emoji":"🇵🇲","text":"","type":1,"order":4093,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 皮特凯恩群岛","name":"FLAG: PITCAIRN ISLANDS","hexcode":"1F1F5-1F1F3","shortcodes":["flag_pn"],"tags":["PN","旗"],"emoji":"🇵🇳","text":"","type":1,"order":4094,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 波多黎各","name":"FLAG: PUERTO RICO","hexcode":"1F1F5-1F1F7","shortcodes":["flag_pr"],"tags":["PR","旗"],"emoji":"🇵🇷","text":"","type":1,"order":4095,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 巴勒斯坦领土","name":"FLAG: PALESTINIAN TERRITORIES","hexcode":"1F1F5-1F1F8","shortcodes":["flag_ps"],"tags":["PS","旗"],"emoji":"🇵🇸","text":"","type":1,"order":4096,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 葡萄牙","name":"FLAG: PORTUGAL","hexcode":"1F1F5-1F1F9","shortcodes":["flag_pt"],"tags":["PT","旗"],"emoji":"🇵🇹","text":"","type":1,"order":4097,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 帕劳","name":"FLAG: PALAU","hexcode":"1F1F5-1F1FC","shortcodes":["flag_pw"],"tags":["PW","旗"],"emoji":"🇵🇼","text":"","type":1,"order":4098,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 巴拉圭","name":"FLAG: PARAGUAY","hexcode":"1F1F5-1F1FE","shortcodes":["flag_py"],"tags":["PY","旗"],"emoji":"🇵🇾","text":"","type":1,"order":4099,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 卡塔尔","name":"FLAG: QATAR","hexcode":"1F1F6-1F1E6","shortcodes":["flag_qa"],"tags":["QA","旗"],"emoji":"🇶🇦","text":"","type":1,"order":4100,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 留尼汪","name":"FLAG: RÉUNION","hexcode":"1F1F7-1F1EA","shortcodes":["flag_re"],"tags":["RE","旗"],"emoji":"🇷🇪","text":"","type":1,"order":4101,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 罗马尼亚","name":"FLAG: ROMANIA","hexcode":"1F1F7-1F1F4","shortcodes":["flag_ro"],"tags":["RO","旗"],"emoji":"🇷🇴","text":"","type":1,"order":4102,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 塞尔维亚","name":"FLAG: SERBIA","hexcode":"1F1F7-1F1F8","shortcodes":["flag_rs"],"tags":["RS","旗"],"emoji":"🇷🇸","text":"","type":1,"order":4103,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 俄罗斯","name":"FLAG: RUSSIA","hexcode":"1F1F7-1F1FA","shortcodes":["flag_ru"],"tags":["RU","旗"],"emoji":"🇷🇺","text":"","type":1,"order":4104,"group":9,"subgroup":98,"version":0.6},{"annotation":"旗: 卢旺达","name":"FLAG: RWANDA","hexcode":"1F1F7-1F1FC","shortcodes":["flag_rw"],"tags":["RW","旗"],"emoji":"🇷🇼","text":"","type":1,"order":4105,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 沙特阿拉伯","name":"FLAG: SAUDI ARABIA","hexcode":"1F1F8-1F1E6","shortcodes":["flag_sa"],"tags":["SA","旗"],"emoji":"🇸🇦","text":"","type":1,"order":4106,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 所罗门群岛","name":"FLAG: SOLOMON ISLANDS","hexcode":"1F1F8-1F1E7","shortcodes":["flag_sb"],"tags":["SB","旗"],"emoji":"🇸🇧","text":"","type":1,"order":4107,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 塞舌尔","name":"FLAG: SEYCHELLES","hexcode":"1F1F8-1F1E8","shortcodes":["flag_sc"],"tags":["SC","旗"],"emoji":"🇸🇨","text":"","type":1,"order":4108,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 苏丹","name":"FLAG: SUDAN","hexcode":"1F1F8-1F1E9","shortcodes":["flag_sd"],"tags":["SD","旗"],"emoji":"🇸🇩","text":"","type":1,"order":4109,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 瑞典","name":"FLAG: SWEDEN","hexcode":"1F1F8-1F1EA","shortcodes":["flag_se"],"tags":["SE","旗"],"emoji":"🇸🇪","text":"","type":1,"order":4110,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 新加坡","name":"FLAG: SINGAPORE","hexcode":"1F1F8-1F1EC","shortcodes":["flag_sg"],"tags":["SG","旗"],"emoji":"🇸🇬","text":"","type":1,"order":4111,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 圣赫勒拿","name":"FLAG: ST. HELENA","hexcode":"1F1F8-1F1ED","shortcodes":["flag_sh"],"tags":["SH","旗"],"emoji":"🇸🇭","text":"","type":1,"order":4112,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 斯洛文尼亚","name":"FLAG: SLOVENIA","hexcode":"1F1F8-1F1EE","shortcodes":["flag_si"],"tags":["SI","旗"],"emoji":"🇸🇮","text":"","type":1,"order":4113,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 斯瓦尔巴和扬马延","name":"FLAG: SVALBARD & JAN MAYEN","hexcode":"1F1F8-1F1EF","shortcodes":["flag_sj"],"tags":["SJ","旗"],"emoji":"🇸🇯","text":"","type":1,"order":4114,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 斯洛伐克","name":"FLAG: SLOVAKIA","hexcode":"1F1F8-1F1F0","shortcodes":["flag_sk"],"tags":["SK","旗"],"emoji":"🇸🇰","text":"","type":1,"order":4115,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 塞拉利昂","name":"FLAG: SIERRA LEONE","hexcode":"1F1F8-1F1F1","shortcodes":["flag_sl"],"tags":["SL","旗"],"emoji":"🇸🇱","text":"","type":1,"order":4116,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 圣马力诺","name":"FLAG: SAN MARINO","hexcode":"1F1F8-1F1F2","shortcodes":["flag_sm"],"tags":["SM","旗"],"emoji":"🇸🇲","text":"","type":1,"order":4117,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 塞内加尔","name":"FLAG: SENEGAL","hexcode":"1F1F8-1F1F3","shortcodes":["flag_sn"],"tags":["SN","旗"],"emoji":"🇸🇳","text":"","type":1,"order":4118,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 索马里","name":"FLAG: SOMALIA","hexcode":"1F1F8-1F1F4","shortcodes":["flag_so"],"tags":["SO","旗"],"emoji":"🇸🇴","text":"","type":1,"order":4119,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 苏里南","name":"FLAG: SURINAME","hexcode":"1F1F8-1F1F7","shortcodes":["flag_sr"],"tags":["SR","旗"],"emoji":"🇸🇷","text":"","type":1,"order":4120,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 南苏丹","name":"FLAG: SOUTH SUDAN","hexcode":"1F1F8-1F1F8","shortcodes":["flag_ss"],"tags":["SS","旗"],"emoji":"🇸🇸","text":"","type":1,"order":4121,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 圣多美和普林西比","name":"FLAG: SÃO TOMÉ & PRÍNCIPE","hexcode":"1F1F8-1F1F9","shortcodes":["flag_st"],"tags":["ST","旗"],"emoji":"🇸🇹","text":"","type":1,"order":4122,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 萨尔瓦多","name":"FLAG: EL SALVADOR","hexcode":"1F1F8-1F1FB","shortcodes":["flag_sv"],"tags":["SV","旗"],"emoji":"🇸🇻","text":"","type":1,"order":4123,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 荷属圣马丁","name":"FLAG: SINT MAARTEN","hexcode":"1F1F8-1F1FD","shortcodes":["flag_sx"],"tags":["SX","旗"],"emoji":"🇸🇽","text":"","type":1,"order":4124,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 叙利亚","name":"FLAG: SYRIA","hexcode":"1F1F8-1F1FE","shortcodes":["flag_sy"],"tags":["SY","旗"],"emoji":"🇸🇾","text":"","type":1,"order":4125,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 斯威士兰","name":"FLAG: ESWATINI","hexcode":"1F1F8-1F1FF","shortcodes":["flag_sz"],"tags":["SZ","旗"],"emoji":"🇸🇿","text":"","type":1,"order":4126,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 特里斯坦-达库尼亚群岛","name":"FLAG: TRISTAN DA CUNHA","hexcode":"1F1F9-1F1E6","shortcodes":["flag_ta"],"tags":["TA","旗"],"emoji":"🇹🇦","text":"","type":1,"order":4127,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 特克斯和凯科斯群岛","name":"FLAG: TURKS & CAICOS ISLANDS","hexcode":"1F1F9-1F1E8","shortcodes":["flag_tc"],"tags":["TC","旗"],"emoji":"🇹🇨","text":"","type":1,"order":4128,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 乍得","name":"FLAG: CHAD","hexcode":"1F1F9-1F1E9","shortcodes":["flag_td"],"tags":["TD","旗"],"emoji":"🇹🇩","text":"","type":1,"order":4129,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 法属南部领地","name":"FLAG: FRENCH SOUTHERN TERRITORIES","hexcode":"1F1F9-1F1EB","shortcodes":["flag_tf"],"tags":["TF","旗"],"emoji":"🇹🇫","text":"","type":1,"order":4130,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 多哥","name":"FLAG: TOGO","hexcode":"1F1F9-1F1EC","shortcodes":["flag_tg"],"tags":["TG","旗"],"emoji":"🇹🇬","text":"","type":1,"order":4131,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 泰国","name":"FLAG: THAILAND","hexcode":"1F1F9-1F1ED","shortcodes":["flag_th"],"tags":["TH","旗"],"emoji":"🇹🇭","text":"","type":1,"order":4132,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 塔吉克斯坦","name":"FLAG: TAJIKISTAN","hexcode":"1F1F9-1F1EF","shortcodes":["flag_tj"],"tags":["TJ","旗"],"emoji":"🇹🇯","text":"","type":1,"order":4133,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 托克劳","name":"FLAG: TOKELAU","hexcode":"1F1F9-1F1F0","shortcodes":["flag_tk"],"tags":["TK","旗"],"emoji":"🇹🇰","text":"","type":1,"order":4134,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 东帝汶","name":"FLAG: TIMOR-LESTE","hexcode":"1F1F9-1F1F1","shortcodes":["flag_tl"],"tags":["TL","旗"],"emoji":"🇹🇱","text":"","type":1,"order":4135,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 土库曼斯坦","name":"FLAG: TURKMENISTAN","hexcode":"1F1F9-1F1F2","shortcodes":["flag_tm"],"tags":["TM","旗"],"emoji":"🇹🇲","text":"","type":1,"order":4136,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 突尼斯","name":"FLAG: TUNISIA","hexcode":"1F1F9-1F1F3","shortcodes":["flag_tn"],"tags":["TN","旗"],"emoji":"🇹🇳","text":"","type":1,"order":4137,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 汤加","name":"FLAG: TONGA","hexcode":"1F1F9-1F1F4","shortcodes":["flag_to"],"tags":["TO","旗"],"emoji":"🇹🇴","text":"","type":1,"order":4138,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 土耳其","name":"FLAG: TURKEY","hexcode":"1F1F9-1F1F7","shortcodes":["flag_tr"],"tags":["TR","旗"],"emoji":"🇹🇷","text":"","type":1,"order":4139,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 特立尼达和多巴哥","name":"FLAG: TRINIDAD & TOBAGO","hexcode":"1F1F9-1F1F9","shortcodes":["flag_tt"],"tags":["TT","旗"],"emoji":"🇹🇹","text":"","type":1,"order":4140,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 图瓦卢","name":"FLAG: TUVALU","hexcode":"1F1F9-1F1FB","shortcodes":["flag_tv"],"tags":["TV","旗"],"emoji":"🇹🇻","text":"","type":1,"order":4141,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 台湾","name":"FLAG: TAIWAN","hexcode":"1F1F9-1F1FC","shortcodes":["flag_tw"],"tags":["TW","旗"],"emoji":"🇹🇼","text":"","type":1,"order":4142,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 坦桑尼亚","name":"FLAG: TANZANIA","hexcode":"1F1F9-1F1FF","shortcodes":["flag_tz"],"tags":["TZ","旗"],"emoji":"🇹🇿","text":"","type":1,"order":4143,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 乌克兰","name":"FLAG: UKRAINE","hexcode":"1F1FA-1F1E6","shortcodes":["flag_ua"],"tags":["UA","旗"],"emoji":"🇺🇦","text":"","type":1,"order":4144,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 乌干达","name":"FLAG: UGANDA","hexcode":"1F1FA-1F1EC","shortcodes":["flag_ug"],"tags":["UG","旗"],"emoji":"🇺🇬","text":"","type":1,"order":4145,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 美国本土外小岛屿","name":"FLAG: U.S. OUTLYING ISLANDS","hexcode":"1F1FA-1F1F2","shortcodes":["flag_um"],"tags":["UM","旗"],"emoji":"🇺🇲","text":"","type":1,"order":4146,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 联合国","name":"FLAG: UNITED NATIONS","hexcode":"1F1FA-1F1F3","shortcodes":["flag_un"],"tags":["UN","旗"],"emoji":"🇺🇳","text":"","type":1,"order":4147,"group":9,"subgroup":98,"version":4},{"annotation":"旗: 美国","name":"FLAG: UNITED STATES","hexcode":"1F1FA-1F1F8","shortcodes":["flag_us","usa"],"tags":["US","旗"],"emoji":"🇺🇸","text":"","type":1,"order":4148,"group":9,"subgroup":98,"version":0.6},{"annotation":"旗: 乌拉圭","name":"FLAG: URUGUAY","hexcode":"1F1FA-1F1FE","shortcodes":["flag_uy"],"tags":["UY","旗"],"emoji":"🇺🇾","text":"","type":1,"order":4149,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 乌兹别克斯坦","name":"FLAG: UZBEKISTAN","hexcode":"1F1FA-1F1FF","shortcodes":["flag_uz"],"tags":["UZ","旗"],"emoji":"🇺🇿","text":"","type":1,"order":4150,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 梵蒂冈","name":"FLAG: VATICAN CITY","hexcode":"1F1FB-1F1E6","shortcodes":["flag_va"],"tags":["VA","旗"],"emoji":"🇻🇦","text":"","type":1,"order":4151,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 圣文森特和格林纳丁斯","name":"FLAG: ST. VINCENT & GRENADINES","hexcode":"1F1FB-1F1E8","shortcodes":["flag_vc"],"tags":["VC","旗"],"emoji":"🇻🇨","text":"","type":1,"order":4152,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 委内瑞拉","name":"FLAG: VENEZUELA","hexcode":"1F1FB-1F1EA","shortcodes":["flag_ve"],"tags":["VE","旗"],"emoji":"🇻🇪","text":"","type":1,"order":4153,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 英属维尔京群岛","name":"FLAG: BRITISH VIRGIN ISLANDS","hexcode":"1F1FB-1F1EC","shortcodes":["flag_vg"],"tags":["VG","旗"],"emoji":"🇻🇬","text":"","type":1,"order":4154,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 美属维尔京群岛","name":"FLAG: U.S. VIRGIN ISLANDS","hexcode":"1F1FB-1F1EE","shortcodes":["flag_vi"],"tags":["VI","旗"],"emoji":"🇻🇮","text":"","type":1,"order":4155,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 越南","name":"FLAG: VIETNAM","hexcode":"1F1FB-1F1F3","shortcodes":["flag_vn"],"tags":["VN","旗"],"emoji":"🇻🇳","text":"","type":1,"order":4156,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 瓦努阿图","name":"FLAG: VANUATU","hexcode":"1F1FB-1F1FA","shortcodes":["flag_vu"],"tags":["VU","旗"],"emoji":"🇻🇺","text":"","type":1,"order":4157,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 瓦利斯和富图纳","name":"FLAG: WALLIS & FUTUNA","hexcode":"1F1FC-1F1EB","shortcodes":["flag_wf"],"tags":["WF","旗"],"emoji":"🇼🇫","text":"","type":1,"order":4158,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 萨摩亚","name":"FLAG: SAMOA","hexcode":"1F1FC-1F1F8","shortcodes":["flag_ws"],"tags":["WS","旗"],"emoji":"🇼🇸","text":"","type":1,"order":4159,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 科索沃","name":"FLAG: KOSOVO","hexcode":"1F1FD-1F1F0","shortcodes":["flag_xk"],"tags":["XK","旗"],"emoji":"🇽🇰","text":"","type":1,"order":4160,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 也门","name":"FLAG: YEMEN","hexcode":"1F1FE-1F1EA","shortcodes":["flag_ye"],"tags":["YE","旗"],"emoji":"🇾🇪","text":"","type":1,"order":4161,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 马约特","name":"FLAG: MAYOTTE","hexcode":"1F1FE-1F1F9","shortcodes":["flag_yt"],"tags":["YT","旗"],"emoji":"🇾🇹","text":"","type":1,"order":4162,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 南非","name":"FLAG: SOUTH AFRICA","hexcode":"1F1FF-1F1E6","shortcodes":["flag_za"],"tags":["ZA","旗"],"emoji":"🇿🇦","text":"","type":1,"order":4163,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 赞比亚","name":"FLAG: ZAMBIA","hexcode":"1F1FF-1F1F2","shortcodes":["flag_zm"],"tags":["ZM","旗"],"emoji":"🇿🇲","text":"","type":1,"order":4164,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 津巴布韦","name":"FLAG: ZIMBABWE","hexcode":"1F1FF-1F1FC","shortcodes":["flag_zw"],"tags":["ZW","旗"],"emoji":"🇿🇼","text":"","type":1,"order":4165,"group":9,"subgroup":98,"version":2},{"annotation":"旗: 英格兰","name":"FLAG: ENGLAND","hexcode":"1F3F4-E0067-E0062-E0065-E006E-E0067-E007F","shortcodes":["flag_gbeng","england"],"tags":["gbeng","旗"],"emoji":"🏴󠁧󠁢󠁥󠁮󠁧󠁿","text":"","type":1,"order":4166,"group":9,"subgroup":99,"version":5},{"annotation":"旗: 苏格兰","name":"FLAG: SCOTLAND","hexcode":"1F3F4-E0067-E0062-E0073-E0063-E0074-E007F","shortcodes":["flag_gbsct","scotland"],"tags":["gbsct","旗"],"emoji":"🏴󠁧󠁢󠁳󠁣󠁴󠁿","text":"","type":1,"order":4167,"group":9,"subgroup":99,"version":5},{"annotation":"旗: 威尔士","name":"FLAG: WALES","hexcode":"1F3F4-E0067-E0062-E0077-E006C-E0073-E007F","shortcodes":["flag_gbwls","wales"],"tags":["gbwls","旗"],"emoji":"🏴󠁧󠁢󠁷󠁬󠁳󠁿","text":"","type":1,"order":4168,"group":9,"subgroup":99,"version":5}] \ No newline at end of file diff --git a/pc-client/public/favicon.ico b/pc-client/public/favicon.ico new file mode 100644 index 0000000..5f55bb4 Binary files /dev/null and b/pc-client/public/favicon.ico differ diff --git a/pc-client/public/font/twemoji.woff2 b/pc-client/public/font/twemoji.woff2 new file mode 100644 index 0000000..af22efa Binary files /dev/null and b/pc-client/public/font/twemoji.woff2 differ diff --git a/pc-client/public/icons/empty_tray.png b/pc-client/public/icons/empty_tray.png new file mode 100644 index 0000000..6da9238 Binary files /dev/null and b/pc-client/public/icons/empty_tray.png differ diff --git a/pc-client/public/icons/icon.ico b/pc-client/public/icons/icon.ico new file mode 100644 index 0000000..5f55bb4 Binary files /dev/null and b/pc-client/public/icons/icon.ico differ diff --git a/pc-client/public/icons/icon.png b/pc-client/public/icons/icon.png new file mode 100644 index 0000000..01db1d1 Binary files /dev/null and b/pc-client/public/icons/icon.png differ diff --git a/pc-client/public/icons/mac_icon.png b/pc-client/public/icons/mac_icon.png new file mode 100644 index 0000000..1be05b7 Binary files /dev/null and b/pc-client/public/icons/mac_icon.png differ diff --git a/pc-client/public/icons/tray.png b/pc-client/public/icons/tray.png new file mode 100644 index 0000000..812a6a1 Binary files /dev/null and b/pc-client/public/icons/tray.png differ diff --git a/pc-client/public/icons/tray@2x.png b/pc-client/public/icons/tray@2x.png new file mode 100644 index 0000000..d5c5b9e Binary files /dev/null and b/pc-client/public/icons/tray@2x.png differ diff --git a/pc-client/public/openIM.wasm b/pc-client/public/openIM.wasm new file mode 100644 index 0000000..d73bebc Binary files /dev/null and b/pc-client/public/openIM.wasm differ diff --git a/pc-client/public/splash.html b/pc-client/public/splash.html new file mode 100644 index 0000000..1369780 --- /dev/null +++ b/pc-client/public/splash.html @@ -0,0 +1,70 @@ + + + + + + + + + + + diff --git a/pc-client/public/sql-wasm.wasm b/pc-client/public/sql-wasm.wasm new file mode 100644 index 0000000..18b392e Binary files /dev/null and b/pc-client/public/sql-wasm.wasm differ diff --git a/pc-client/public/wasm_exec.js b/pc-client/public/wasm_exec.js new file mode 100644 index 0000000..d71af9e --- /dev/null +++ b/pc-client/public/wasm_exec.js @@ -0,0 +1,575 @@ +// Copyright 2018 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +"use strict"; + +(() => { + const enosys = () => { + const err = new Error("not implemented"); + err.code = "ENOSYS"; + return err; + }; + + if (!globalThis.fs) { + let outputBuf = ""; + globalThis.fs = { + constants: { O_WRONLY: -1, O_RDWR: -1, O_CREAT: -1, O_TRUNC: -1, O_APPEND: -1, O_EXCL: -1, O_DIRECTORY: -1 }, // unused + writeSync(fd, buf) { + outputBuf += decoder.decode(buf); + const nl = outputBuf.lastIndexOf("\n"); + if (nl != -1) { + console.log(outputBuf.substring(0, nl)); + outputBuf = outputBuf.substring(nl + 1); + } + return buf.length; + }, + write(fd, buf, offset, length, position, callback) { + if (offset !== 0 || length !== buf.length || position !== null) { + callback(enosys()); + return; + } + const n = this.writeSync(fd, buf); + callback(null, n); + }, + chmod(path, mode, callback) { callback(enosys()); }, + chown(path, uid, gid, callback) { callback(enosys()); }, + close(fd, callback) { callback(enosys()); }, + fchmod(fd, mode, callback) { callback(enosys()); }, + fchown(fd, uid, gid, callback) { callback(enosys()); }, + fstat(fd, callback) { callback(enosys()); }, + fsync(fd, callback) { callback(null); }, + ftruncate(fd, length, callback) { callback(enosys()); }, + lchown(path, uid, gid, callback) { callback(enosys()); }, + link(path, link, callback) { callback(enosys()); }, + lstat(path, callback) { callback(enosys()); }, + mkdir(path, perm, callback) { callback(enosys()); }, + open(path, flags, mode, callback) { callback(enosys()); }, + read(fd, buffer, offset, length, position, callback) { callback(enosys()); }, + readdir(path, callback) { callback(enosys()); }, + readlink(path, callback) { callback(enosys()); }, + rename(from, to, callback) { callback(enosys()); }, + rmdir(path, callback) { callback(enosys()); }, + stat(path, callback) { callback(enosys()); }, + symlink(path, link, callback) { callback(enosys()); }, + truncate(path, length, callback) { callback(enosys()); }, + unlink(path, callback) { callback(enosys()); }, + utimes(path, atime, mtime, callback) { callback(enosys()); }, + }; + } + + if (!globalThis.process) { + globalThis.process = { + getuid() { return -1; }, + getgid() { return -1; }, + geteuid() { return -1; }, + getegid() { return -1; }, + getgroups() { throw enosys(); }, + pid: -1, + ppid: -1, + umask() { throw enosys(); }, + cwd() { throw enosys(); }, + chdir() { throw enosys(); }, + } + } + + if (!globalThis.path) { + globalThis.path = { + resolve(...pathSegments) { + return pathSegments.join("/"); + } + } + } + + if (!globalThis.crypto) { + throw new Error("globalThis.crypto is not available, polyfill required (crypto.getRandomValues only)"); + } + + if (!globalThis.performance) { + throw new Error("globalThis.performance is not available, polyfill required (performance.now only)"); + } + + if (!globalThis.TextEncoder) { + throw new Error("globalThis.TextEncoder is not available, polyfill required"); + } + + if (!globalThis.TextDecoder) { + throw new Error("globalThis.TextDecoder is not available, polyfill required"); + } + + const encoder = new TextEncoder("utf-8"); + const decoder = new TextDecoder("utf-8"); + + globalThis.Go = class { + constructor() { + this.argv = ["js"]; + this.env = {}; + this.exit = (code) => { + if (code !== 0) { + console.warn("exit code:", code); + } + }; + this._exitPromise = new Promise((resolve) => { + this._resolveExitPromise = resolve; + }); + this._pendingEvent = null; + this._scheduledTimeouts = new Map(); + this._nextCallbackTimeoutID = 1; + + const setInt64 = (addr, v) => { + this.mem.setUint32(addr + 0, v, true); + this.mem.setUint32(addr + 4, Math.floor(v / 4294967296), true); + } + + const setInt32 = (addr, v) => { + this.mem.setUint32(addr + 0, v, true); + } + + const getInt64 = (addr) => { + const low = this.mem.getUint32(addr + 0, true); + const high = this.mem.getInt32(addr + 4, true); + return low + high * 4294967296; + } + + const loadValue = (addr) => { + const f = this.mem.getFloat64(addr, true); + if (f === 0) { + return undefined; + } + if (!isNaN(f)) { + return f; + } + + const id = this.mem.getUint32(addr, true); + return this._values[id]; + } + + const storeValue = (addr, v) => { + const nanHead = 0x7FF80000; + + if (typeof v === "number" && v !== 0) { + if (isNaN(v)) { + this.mem.setUint32(addr + 4, nanHead, true); + this.mem.setUint32(addr, 0, true); + return; + } + this.mem.setFloat64(addr, v, true); + return; + } + + if (v === undefined) { + this.mem.setFloat64(addr, 0, true); + return; + } + + let id = this._ids.get(v); + if (id === undefined) { + id = this._idPool.pop(); + if (id === undefined) { + id = this._values.length; + } + this._values[id] = v; + this._goRefCounts[id] = 0; + this._ids.set(v, id); + } + this._goRefCounts[id]++; + let typeFlag = 0; + switch (typeof v) { + case "object": + if (v !== null) { + typeFlag = 1; + } + break; + case "string": + typeFlag = 2; + break; + case "symbol": + typeFlag = 3; + break; + case "function": + typeFlag = 4; + break; + } + this.mem.setUint32(addr + 4, nanHead | typeFlag, true); + this.mem.setUint32(addr, id, true); + } + + const loadSlice = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + return new Uint8Array(this._inst.exports.mem.buffer, array, len); + } + + const loadSliceOfValues = (addr) => { + const array = getInt64(addr + 0); + const len = getInt64(addr + 8); + const a = new Array(len); + for (let i = 0; i < len; i++) { + a[i] = loadValue(array + i * 8); + } + return a; + } + + const loadString = (addr) => { + const saddr = getInt64(addr + 0); + const len = getInt64(addr + 8); + return decoder.decode(new DataView(this._inst.exports.mem.buffer, saddr, len)); + } + + const testCallExport = (a, b) => { + this._inst.exports.testExport0(); + return this._inst.exports.testExport(a, b); + } + + const timeOrigin = Date.now() - performance.now(); + this.importObject = { + _gotest: { + add: (a, b) => a + b, + callExport: testCallExport, + }, + gojs: { + // Go's SP does not change as long as no Go code is running. Some operations (e.g. calls, getters and setters) + // may synchronously trigger a Go event handler. This makes Go code get executed in the middle of the imported + // function. A goroutine can switch to a new stack if the current stack is too small (see morestack function). + // This changes the SP, thus we have to update the SP used by the imported function. + + // func wasmExit(code int32) + "runtime.wasmExit": (sp) => { + sp >>>= 0; + const code = this.mem.getInt32(sp + 8, true); + this.exited = true; + delete this._inst; + delete this._values; + delete this._goRefCounts; + delete this._ids; + delete this._idPool; + this.exit(code); + }, + + // func wasmWrite(fd uintptr, p unsafe.Pointer, n int32) + "runtime.wasmWrite": (sp) => { + sp >>>= 0; + const fd = getInt64(sp + 8); + const p = getInt64(sp + 16); + const n = this.mem.getInt32(sp + 24, true); + fs.writeSync(fd, new Uint8Array(this._inst.exports.mem.buffer, p, n)); + }, + + // func resetMemoryDataView() + "runtime.resetMemoryDataView": (sp) => { + sp >>>= 0; + this.mem = new DataView(this._inst.exports.mem.buffer); + }, + + // func nanotime1() int64 + "runtime.nanotime1": (sp) => { + sp >>>= 0; + setInt64(sp + 8, (timeOrigin + performance.now()) * 1000000); + }, + + // func walltime() (sec int64, nsec int32) + "runtime.walltime": (sp) => { + sp >>>= 0; + const msec = (new Date).getTime(); + setInt64(sp + 8, msec / 1000); + this.mem.setInt32(sp + 16, (msec % 1000) * 1000000, true); + }, + + // func scheduleTimeoutEvent(delay int64) int32 + "runtime.scheduleTimeoutEvent": (sp) => { + sp >>>= 0; + const id = this._nextCallbackTimeoutID; + this._nextCallbackTimeoutID++; + this._scheduledTimeouts.set(id, setTimeout( + () => { + this._resume(); + while (this._scheduledTimeouts.has(id)) { + // for some reason Go failed to register the timeout event, log and try again + // (temporary workaround for https://github.com/golang/go/issues/28975) + console.warn("scheduleTimeoutEvent: missed timeout event"); + this._resume(); + } + }, + getInt64(sp + 8), + )); + this.mem.setInt32(sp + 16, id, true); + }, + + // func clearTimeoutEvent(id int32) + "runtime.clearTimeoutEvent": (sp) => { + sp >>>= 0; + const id = this.mem.getInt32(sp + 8, true); + clearTimeout(this._scheduledTimeouts.get(id)); + this._scheduledTimeouts.delete(id); + }, + + // func getRandomData(r []byte) + "runtime.getRandomData": (sp) => { + sp >>>= 0; + crypto.getRandomValues(loadSlice(sp + 8)); + }, + + // func finalizeRef(v ref) + "syscall/js.finalizeRef": (sp) => { + sp >>>= 0; + const id = this.mem.getUint32(sp + 8, true); + this._goRefCounts[id]--; + if (this._goRefCounts[id] === 0) { + const v = this._values[id]; + this._values[id] = null; + this._ids.delete(v); + this._idPool.push(id); + } + }, + + // func stringVal(value string) ref + "syscall/js.stringVal": (sp) => { + sp >>>= 0; + storeValue(sp + 24, loadString(sp + 8)); + }, + + // func valueGet(v ref, p string) ref + "syscall/js.valueGet": (sp) => { + sp >>>= 0; + const result = Reflect.get(loadValue(sp + 8), loadString(sp + 16)); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 32, result); + }, + + // func valueSet(v ref, p string, x ref) + "syscall/js.valueSet": (sp) => { + sp >>>= 0; + Reflect.set(loadValue(sp + 8), loadString(sp + 16), loadValue(sp + 32)); + }, + + // func valueDelete(v ref, p string) + "syscall/js.valueDelete": (sp) => { + sp >>>= 0; + Reflect.deleteProperty(loadValue(sp + 8), loadString(sp + 16)); + }, + + // func valueIndex(v ref, i int) ref + "syscall/js.valueIndex": (sp) => { + sp >>>= 0; + storeValue(sp + 24, Reflect.get(loadValue(sp + 8), getInt64(sp + 16))); + }, + + // valueSetIndex(v ref, i int, x ref) + "syscall/js.valueSetIndex": (sp) => { + sp >>>= 0; + Reflect.set(loadValue(sp + 8), getInt64(sp + 16), loadValue(sp + 24)); + }, + + // func valueCall(v ref, m string, args []ref) (ref, bool) + "syscall/js.valueCall": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const m = Reflect.get(v, loadString(sp + 16)); + const args = loadSliceOfValues(sp + 32); + const result = Reflect.apply(m, v, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 56, result); + this.mem.setUint8(sp + 64, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 56, err); + this.mem.setUint8(sp + 64, 0); + } + }, + + // func valueInvoke(v ref, args []ref) (ref, bool) + "syscall/js.valueInvoke": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + const result = Reflect.apply(v, undefined, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, result); + this.mem.setUint8(sp + 48, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, err); + this.mem.setUint8(sp + 48, 0); + } + }, + + // func valueNew(v ref, args []ref) (ref, bool) + "syscall/js.valueNew": (sp) => { + sp >>>= 0; + try { + const v = loadValue(sp + 8); + const args = loadSliceOfValues(sp + 16); + const result = Reflect.construct(v, args); + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, result); + this.mem.setUint8(sp + 48, 1); + } catch (err) { + sp = this._inst.exports.getsp() >>> 0; // see comment above + storeValue(sp + 40, err); + this.mem.setUint8(sp + 48, 0); + } + }, + + // func valueLength(v ref) int + "syscall/js.valueLength": (sp) => { + sp >>>= 0; + setInt64(sp + 16, parseInt(loadValue(sp + 8).length)); + }, + + // valuePrepareString(v ref) (ref, int) + "syscall/js.valuePrepareString": (sp) => { + sp >>>= 0; + const str = encoder.encode(String(loadValue(sp + 8))); + storeValue(sp + 16, str); + setInt64(sp + 24, str.length); + }, + + // valueLoadString(v ref, b []byte) + "syscall/js.valueLoadString": (sp) => { + sp >>>= 0; + const str = loadValue(sp + 8); + loadSlice(sp + 16).set(str); + }, + + // func valueInstanceOf(v ref, t ref) bool + "syscall/js.valueInstanceOf": (sp) => { + sp >>>= 0; + this.mem.setUint8(sp + 24, (loadValue(sp + 8) instanceof loadValue(sp + 16)) ? 1 : 0); + }, + + // func copyBytesToGo(dst []byte, src ref) (int, bool) + "syscall/js.copyBytesToGo": (sp) => { + sp >>>= 0; + const dst = loadSlice(sp + 8); + const src = loadValue(sp + 32); + if (!(src instanceof Uint8Array || src instanceof Uint8ClampedArray)) { + this.mem.setUint8(sp + 48, 0); + return; + } + const toCopy = src.subarray(0, dst.length); + dst.set(toCopy); + setInt64(sp + 40, toCopy.length); + this.mem.setUint8(sp + 48, 1); + }, + + // func copyBytesToJS(dst ref, src []byte) (int, bool) + "syscall/js.copyBytesToJS": (sp) => { + sp >>>= 0; + const dst = loadValue(sp + 8); + const src = loadSlice(sp + 16); + if (!(dst instanceof Uint8Array || dst instanceof Uint8ClampedArray)) { + this.mem.setUint8(sp + 48, 0); + return; + } + const toCopy = src.subarray(0, dst.length); + dst.set(toCopy); + setInt64(sp + 40, toCopy.length); + this.mem.setUint8(sp + 48, 1); + }, + + "debug": (value) => { + console.log(value); + }, + } + }; + } + + async run(instance) { + if (!(instance instanceof WebAssembly.Instance)) { + throw new Error("Go.run: WebAssembly.Instance expected"); + } + this._inst = instance; + this.mem = new DataView(this._inst.exports.mem.buffer); + this._values = [ // JS values that Go currently has references to, indexed by reference id + NaN, + 0, + null, + true, + false, + globalThis, + this, + ]; + this._goRefCounts = new Array(this._values.length).fill(Infinity); // number of references that Go has to a JS value, indexed by reference id + this._ids = new Map([ // mapping from JS values to reference ids + [0, 1], + [null, 2], + [true, 3], + [false, 4], + [globalThis, 5], + [this, 6], + ]); + this._idPool = []; // unused ids that have been garbage collected + this.exited = false; // whether the Go program has exited + + // Pass command line arguments and environment variables to WebAssembly by writing them to the linear memory. + let offset = 4096; + + const strPtr = (str) => { + const ptr = offset; + const bytes = encoder.encode(str + "\0"); + new Uint8Array(this.mem.buffer, offset, bytes.length).set(bytes); + offset += bytes.length; + if (offset % 8 !== 0) { + offset += 8 - (offset % 8); + } + return ptr; + }; + + const argc = this.argv.length; + + const argvPtrs = []; + this.argv.forEach((arg) => { + argvPtrs.push(strPtr(arg)); + }); + argvPtrs.push(0); + + const keys = Object.keys(this.env).sort(); + keys.forEach((key) => { + argvPtrs.push(strPtr(`${key}=${this.env[key]}`)); + }); + argvPtrs.push(0); + + const argv = offset; + argvPtrs.forEach((ptr) => { + this.mem.setUint32(offset, ptr, true); + this.mem.setUint32(offset + 4, 0, true); + offset += 8; + }); + + // The linker guarantees global data starts from at least wasmMinDataAddr. + // Keep in sync with cmd/link/internal/ld/data.go:wasmMinDataAddr. + const wasmMinDataAddr = 4096 + 8192; + if (offset >= wasmMinDataAddr) { + throw new Error("total length of command line and environment variables exceeds limit"); + } + + this._inst.exports.run(argc, argv); + if (this.exited) { + this._resolveExitPromise(); + } + await this._exitPromise; + } + + _resume() { + if (this.exited) { + throw new Error("Go program has already exited"); + } + this._inst.exports.resume(); + if (this.exited) { + this._resolveExitPromise(); + } + } + + _makeFuncWrapper(id) { + const go = this; + return function () { + const event = { id: id, this: this, args: arguments }; + go._pendingEvent = event; + go._resume(); + return event.result; + }; + } + } +})(); diff --git a/pc-client/scripts/mock-account-server.js b/pc-client/scripts/mock-account-server.js new file mode 100644 index 0000000..ad17491 --- /dev/null +++ b/pc-client/scripts/mock-account-server.js @@ -0,0 +1,161 @@ +/** + * 本地开发用 mock 账号服务(畅联 PC 端联调用) + * + * ⚠️ 仅供本地开发联调! + * - 内置测试环境默认密钥(OpenIM secret / LiveKit key),都是内网测试环境的公开默认值 + * - 禁止打包进客户端、禁止用于正式环境 + * - 真实员工账号由管理员在服务器上的账号服务(:10010)开通 + * + * 用法: + * 1. node scripts/mock-account-server.js(或 npm run mock:account) + * 2. 把 .env 里的 VITE_ACCOUNT_URL 临时指向 http://127.0.0.1:11010 + * 3. 用 test001 / test123(或 test002 / test123)登录 + * + * 接口形状与真实账号服务完全一致:POST /api/login、POST /api/rtc_token。 + * 零依赖,Node >= 18(用到全局 fetch)。 + */ + +'use strict'; + +const http = require('http'); +const crypto = require('crypto'); + +const PORT = 11010; +const OPENIM_API_URL = 'http://192.168.200.11:10002'; +const OPENIM_SECRET = 'openIM123'; +const LIVEKIT_API_KEY = 'openimLKkey'; +const LIVEKIT_API_SECRET = 'lk-secret-9f2c7a41d5e8b063f1a4c795e2d8b3a6'; + +// 本地测试账号(密码均为 test123) +const USERS = { + test001: { password: 'test123', nickname: '测试一号' }, + test002: { password: 'test123', nickname: '测试二号' }, +}; + +// ---------------- OpenIM 管理接口 ---------------- + +async function imApi(route, body, token) { + const res = await fetch(OPENIM_API_URL + route, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + operationID: crypto.randomUUID(), + ...(token ? { token } : {}), + }, + body: JSON.stringify(body), + }); + return res.json(); +} + +async function getAdminToken() { + const r = await imApi('/auth/get_admin_token', { + secret: OPENIM_SECRET, + userID: 'imAdmin', + }); + if (r.errCode !== 0) throw new Error('OpenIM 管理员令牌获取失败: ' + (r.errMsg || r.errCode)); + return r.data.token; +} + +/** 确保 OpenIM 里存在该用户(不存在则注册,尽力而为) */ +async function ensureImUser(userID, nickname, admin) { + try { + await imApi('/user/user_register', { + users: [{ userID, nickname, faceURL: '' }], + }, admin); + } catch { /* 忽略,后面取令牌时再报错 */ } +} + +async function getImUserToken(userID, platformID) { + const admin = await getAdminToken(); + await ensureImUser(userID, USERS[userID].nickname, admin); + const r = await imApi('/auth/get_user_token', { secret: OPENIM_SECRET, platformID, userID }, admin); + if (r.errCode !== 0) throw new Error('OpenIM 用户令牌获取失败: ' + (r.errMsg || r.errCode)); + return r.data; +} + +// ---------------- LiveKit RTC 令牌签发 ---------------- + +const b64url = (s) => Buffer.from(s).toString('base64url'); + +function signLivekitToken(userID, room) { + const now = Math.floor(Date.now() / 1000); + const header = b64url(JSON.stringify({ alg: 'HS256', typ: 'JWT' })); + const payload = b64url(JSON.stringify({ + iss: LIVEKIT_API_KEY, + sub: userID, + exp: now + 3600, + nbf: now - 10, + video: { roomJoin: true, room }, + metadata: '', + })); + const sig = crypto.createHmac('sha256', LIVEKIT_API_SECRET).update(`${header}.${payload}`).digest('base64url'); + return `${header}.${payload}.${sig}`; +} + +// ---------------- HTTP 服务 ---------------- + +function send(res, status, obj) { + res.writeHead(status, { + 'Content-Type': 'application/json; charset=utf-8', + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Headers': 'Content-Type, authorization', + 'Access-Control-Allow-Methods': 'GET,POST,OPTIONS', + }); + res.end(JSON.stringify(obj)); +} + +const ok = (res, data) => send(res, 200, { code: 0, msg: '', data }); +const fail = (res, msg, httpStatus = 200) => send(res, httpStatus, { code: 1, msg }); + +function readBody(req) { + return new Promise((resolve, reject) => { + let buf = ''; + req.on('data', (c) => { buf += c; }); + req.on('end', () => { + if (!buf) return resolve({}); + try { resolve(JSON.parse(buf)); } catch { reject(new Error('请求体不是合法 JSON')); } + }); + req.on('error', reject); + }); +} + +const server = http.createServer(async (req, res) => { + try { + const url = new URL(req.url, 'http://localhost'); + if (req.method === 'OPTIONS') return send(res, 204, {}); + + if (req.method === 'POST' && url.pathname === '/api/login') { + const body = await readBody(req); + const { staffNo, password, platformID } = body; + if (!staffNo || !password) return fail(res, '工号和密码不能为空'); + const user = USERS[staffNo]; + if (!user || user.password !== String(password)) return fail(res, '工号或密码错误'); + const t = await getImUserToken(staffNo, Number.isInteger(platformID) ? platformID : 3); + return ok(res, { + userID: staffNo, + nickname: user.nickname, + imToken: t.token, + expireTimeSeconds: t.expireTimeSeconds, + }); + } + + if (req.method === 'POST' && url.pathname === '/api/rtc_token') { + // 与真实账号服务一致:Authorization: Bearer + {room, identity},返回 {token} + const m = /^Bearer\s+(.+)$/.exec(String(req.headers.authorization || '')); + if (!m) return fail(res, '未登录或登录已过期', 401); + const body = await readBody(req); + const { room, identity } = body; + if (!room || !identity) return fail(res, '房间号或用户标识不能为空'); + return ok(res, { token: signLivekitToken(String(identity), String(room)) }); + } + + return fail(res, '接口不存在', 404); + } catch (e) { + return fail(res, '服务内部错误: ' + e.message, 500); + } +}); + +server.listen(PORT, '127.0.0.1', () => { + console.log(`mock-account-server listening on http://127.0.0.1:${PORT}`); + console.log('测试账号:test001 / test123,test002 / test123'); +}); diff --git a/pc-client/src/AntdGlobalComp.tsx b/pc-client/src/AntdGlobalComp.tsx new file mode 100644 index 0000000..4964b32 --- /dev/null +++ b/pc-client/src/AntdGlobalComp.tsx @@ -0,0 +1,18 @@ +import { App } from "antd"; +import type { MessageInstance } from "antd/es/message/interface"; +import type { ModalStaticFunctions } from "antd/es/modal/confirm"; +import type { NotificationInstance } from "antd/es/notification/interface"; + +let message: MessageInstance; +let notification: NotificationInstance; +let modal: Omit; + +export default () => { + const staticFunction = App.useApp(); + message = staticFunction.message; + modal = staticFunction.modal; + notification = staticFunction.notification; + return null; +}; + +export { message, modal, notification }; diff --git a/pc-client/src/App.tsx b/pc-client/src/App.tsx new file mode 100644 index 0000000..1d04d52 --- /dev/null +++ b/pc-client/src/App.tsx @@ -0,0 +1,44 @@ +import { App as AntdApp, ConfigProvider, theme } from "antd"; +import enUS from "antd/locale/en_US"; +import zhCN from "antd/locale/zh_CN"; +import { Suspense, useEffect } from "react"; +import { QueryClient, QueryClientProvider } from "react-query"; +import { ReactQueryDevtools } from "react-query/devtools"; +import { RouterProvider } from "react-router-dom"; + +import AntdGlobalComp from "./AntdGlobalComp"; +import router from "./routes"; +import { useUserStore } from "./store"; + +function App() { + const locale = useUserStore((state) => state.appSettings.locale); + const queryClient = new QueryClient({ + defaultOptions: { + queries: { + refetchOnWindowFocus: false, + }, + }, + }); + + return ( + + + loading...}> + + + + + + + + + ); +} + +export default App; diff --git a/pc-client/src/api/errorHandle.ts b/pc-client/src/api/errorHandle.ts new file mode 100644 index 0000000..a5f54dd --- /dev/null +++ b/pc-client/src/api/errorHandle.ts @@ -0,0 +1,14 @@ +import { message } from "@/AntdGlobalComp"; +import { ErrCodeMap } from "@/constants"; + +interface ErrorData { + errCode: number; + errMsg?: string; +} + +export const errorHandle = (err: unknown) => { + const errData = err as ErrorData; + if (errData.errMsg) { + message.error(ErrCodeMap[errData.errCode] || errData.errMsg); + } +}; diff --git a/pc-client/src/api/imApi.ts b/pc-client/src/api/imApi.ts new file mode 100644 index 0000000..cfde7fb --- /dev/null +++ b/pc-client/src/api/imApi.ts @@ -0,0 +1,31 @@ +import axios from "axios"; + +import { getIMToken } from "@/utils/storage"; + +// RTC(音视频通话)令牌改由自研账号服务签发(原 OpenIM chat 服务 :10008 已下线)。 +// 账号服务 /api/rtc_token 用登录拿到的 IM token 鉴权(Authorization: Bearer), +// 返回形状保持 { data: { serverUrl, token } },RtcCallModal 调用处无需改动。 +export const getRtcConnectData = async (room: string, identity: string) => { + const imToken = await getIMToken(); + if (!imToken) { + return Promise.reject(new Error("登录已过期,请重新登录")); + } + const { data: res } = await axios.post<{ + code: number; + msg: string; + data: { token: string }; + }>( + `${import.meta.env.VITE_ACCOUNT_URL}/api/rtc_token`, + { room, identity }, + { headers: { Authorization: `Bearer ${imToken}` } }, + ); + if (res.code !== 0) { + return Promise.reject(new Error(res.msg || "获取通话令牌失败")); + } + return { + data: { + serverUrl: import.meta.env.VITE_LIVEKIT_URL as string, + token: res.data.token, + }, + }; +}; diff --git a/pc-client/src/api/login.ts b/pc-client/src/api/login.ts new file mode 100644 index 0000000..e69bd24 --- /dev/null +++ b/pc-client/src/api/login.ts @@ -0,0 +1,89 @@ +import type { MessageReceiveOptType } from "@openim/wasm-client-sdk"; + +import { IMSDK } from "@/layout/MainContentWrap"; + +// 原 OpenIM chat 业务服务(:10008)已下线,用户信息相关接口全部改走 OpenIM SDK。 +// 以下导出保持原有函数签名和返回形状({ data: { users } } 等),调用处无需大改。 + +export interface BusinessUserInfo { + userID: string; + password: string; + account: string; + phoneNumber: string; + areaCode: string; + email: string; + nickname: string; + faceURL: string; + gender: number; + level: number; + birth: number; + allowAddFriend: BusinessAllowType; + allowBeep: BusinessAllowType; + allowVibration: BusinessAllowType; + globalRecvMsgOpt: MessageReceiveOptType; +} + +export enum BusinessAllowType { + Allow = 1, + NotAllow = 2, +} + +// 批量获取用户信息(原 chat 服务 /user/find/full) +// SDK 只提供公开资料(userID/nickname/faceURL/ex),手机号、邮箱等原业务字段不再有值。 +export const getBusinessUserInfo = async (userIDs: string[]) => { + const { data } = await IMSDK.getUsersInfo(userIDs); + return { + data: { + users: data as unknown as BusinessUserInfo[], + }, + }; +}; + +// 按工号精确查找用户(原 chat 服务 /user/search/full) +export const searchBusinessUserInfo = async (keyword: string) => { + try { + const { data } = await IMSDK.getUsersInfo([keyword]); + return { + data: { + total: data.length, + users: data as unknown as BusinessUserInfo[], + }, + }; + } catch { + // 查不到(用户不存在等)统一按无结果处理,由调用处提示“未搜索到相关结果” + return { + data: { + total: 0, + users: [] as BusinessUserInfo[], + }, + }; + } +}; + +interface UpdateBusinessUserInfoParams { + email: string; + nickname: string; + faceURL: string; + gender: number; + birth: number; + allowAddFriend: number; + allowBeep: number; + allowVibration: number; + globalRecvMsgOpt: number; +} + +// 更新个人资料(原 chat 服务 /user/update) +// OpenIM 只支持同步昵称/头像等字段,邮箱、性别、生日等业务字段仅更新本地,不会落服务端。 +export const updateBusinessUserInfo = async ( + params: Partial, +) => { + const imFields: { nickname?: string; faceURL?: string; globalRecvMsgOpt?: MessageReceiveOptType } = + {}; + if (params.nickname !== undefined) imFields.nickname = params.nickname; + if (params.faceURL !== undefined) imFields.faceURL = params.faceURL; + if (params.globalRecvMsgOpt !== undefined) { + imFields.globalRecvMsgOpt = params.globalRecvMsgOpt as MessageReceiveOptType; + } + await IMSDK.setSelfInfo(imFields); + return { data: {} }; +}; diff --git a/pc-client/src/assets/audio/newMsg.mp3 b/pc-client/src/assets/audio/newMsg.mp3 new file mode 100644 index 0000000..342118f Binary files /dev/null and b/pc-client/src/assets/audio/newMsg.mp3 differ diff --git a/pc-client/src/assets/avatar/ic_avatar_01.png b/pc-client/src/assets/avatar/ic_avatar_01.png new file mode 100644 index 0000000..b7765b2 Binary files /dev/null and b/pc-client/src/assets/avatar/ic_avatar_01.png differ diff --git a/pc-client/src/assets/avatar/ic_avatar_02.png b/pc-client/src/assets/avatar/ic_avatar_02.png new file mode 100644 index 0000000..ca48453 Binary files /dev/null and b/pc-client/src/assets/avatar/ic_avatar_02.png differ diff --git a/pc-client/src/assets/avatar/ic_avatar_03.png b/pc-client/src/assets/avatar/ic_avatar_03.png new file mode 100644 index 0000000..b89566f Binary files /dev/null and b/pc-client/src/assets/avatar/ic_avatar_03.png differ diff --git a/pc-client/src/assets/avatar/ic_avatar_04.png b/pc-client/src/assets/avatar/ic_avatar_04.png new file mode 100644 index 0000000..69e4c1c Binary files /dev/null and b/pc-client/src/assets/avatar/ic_avatar_04.png differ diff --git a/pc-client/src/assets/avatar/ic_avatar_05.png b/pc-client/src/assets/avatar/ic_avatar_05.png new file mode 100644 index 0000000..4f5bd5d Binary files /dev/null and b/pc-client/src/assets/avatar/ic_avatar_05.png differ diff --git a/pc-client/src/assets/avatar/ic_avatar_06.png b/pc-client/src/assets/avatar/ic_avatar_06.png new file mode 100644 index 0000000..23515e4 Binary files /dev/null and b/pc-client/src/assets/avatar/ic_avatar_06.png differ diff --git a/pc-client/src/assets/images/chatFooter/call_audio.png b/pc-client/src/assets/images/chatFooter/call_audio.png new file mode 100644 index 0000000..6f095ad Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/call_audio.png differ diff --git a/pc-client/src/assets/images/chatFooter/call_video.png b/pc-client/src/assets/images/chatFooter/call_video.png new file mode 100644 index 0000000..f63641d Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/call_video.png differ diff --git a/pc-client/src/assets/images/chatFooter/cancel.png b/pc-client/src/assets/images/chatFooter/cancel.png new file mode 100644 index 0000000..28ac8f8 Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/cancel.png differ diff --git a/pc-client/src/assets/images/chatFooter/card.png b/pc-client/src/assets/images/chatFooter/card.png new file mode 100644 index 0000000..0e83327 Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/card.png differ diff --git a/pc-client/src/assets/images/chatFooter/cricle_cancel.png b/pc-client/src/assets/images/chatFooter/cricle_cancel.png new file mode 100644 index 0000000..0768ca7 Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/cricle_cancel.png differ diff --git a/pc-client/src/assets/images/chatFooter/cut.png b/pc-client/src/assets/images/chatFooter/cut.png new file mode 100644 index 0000000..17dd45a Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/cut.png differ diff --git a/pc-client/src/assets/images/chatFooter/emoji.png b/pc-client/src/assets/images/chatFooter/emoji.png new file mode 100644 index 0000000..520691f Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/emoji.png differ diff --git a/pc-client/src/assets/images/chatFooter/emoji_pop.png b/pc-client/src/assets/images/chatFooter/emoji_pop.png new file mode 100644 index 0000000..80a2d05 Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/emoji_pop.png differ diff --git a/pc-client/src/assets/images/chatFooter/emoji_pop_active.png b/pc-client/src/assets/images/chatFooter/emoji_pop_active.png new file mode 100644 index 0000000..c6d417d Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/emoji_pop_active.png differ diff --git a/pc-client/src/assets/images/chatFooter/favorite.png b/pc-client/src/assets/images/chatFooter/favorite.png new file mode 100644 index 0000000..f1335b2 Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/favorite.png differ diff --git a/pc-client/src/assets/images/chatFooter/favorite_active.png b/pc-client/src/assets/images/chatFooter/favorite_active.png new file mode 100644 index 0000000..0e5dc4a Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/favorite_active.png differ diff --git a/pc-client/src/assets/images/chatFooter/favorite_add.png b/pc-client/src/assets/images/chatFooter/favorite_add.png new file mode 100644 index 0000000..f856d40 Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/favorite_add.png differ diff --git a/pc-client/src/assets/images/chatFooter/file.png b/pc-client/src/assets/images/chatFooter/file.png new file mode 100644 index 0000000..fea3d3d Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/file.png differ diff --git a/pc-client/src/assets/images/chatFooter/forward.png b/pc-client/src/assets/images/chatFooter/forward.png new file mode 100644 index 0000000..b2c4080 Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/forward.png differ diff --git a/pc-client/src/assets/images/chatFooter/image.png b/pc-client/src/assets/images/chatFooter/image.png new file mode 100644 index 0000000..37572e2 Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/image.png differ diff --git a/pc-client/src/assets/images/chatFooter/remove.png b/pc-client/src/assets/images/chatFooter/remove.png new file mode 100644 index 0000000..8e0d228 Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/remove.png differ diff --git a/pc-client/src/assets/images/chatFooter/rtc.png b/pc-client/src/assets/images/chatFooter/rtc.png new file mode 100644 index 0000000..9b417da Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/rtc.png differ diff --git a/pc-client/src/assets/images/chatFooter/video.png b/pc-client/src/assets/images/chatFooter/video.png new file mode 100644 index 0000000..960a0ea Binary files /dev/null and b/pc-client/src/assets/images/chatFooter/video.png differ diff --git a/pc-client/src/assets/images/chatHeader/cancel.png b/pc-client/src/assets/images/chatHeader/cancel.png new file mode 100644 index 0000000..c836038 Binary files /dev/null and b/pc-client/src/assets/images/chatHeader/cancel.png differ diff --git a/pc-client/src/assets/images/chatHeader/file_manage.png b/pc-client/src/assets/images/chatHeader/file_manage.png new file mode 100644 index 0000000..0a1ca88 Binary files /dev/null and b/pc-client/src/assets/images/chatHeader/file_manage.png differ diff --git a/pc-client/src/assets/images/chatHeader/group_member.png b/pc-client/src/assets/images/chatHeader/group_member.png new file mode 100644 index 0000000..9bec58f Binary files /dev/null and b/pc-client/src/assets/images/chatHeader/group_member.png differ diff --git a/pc-client/src/assets/images/chatHeader/group_notice.png b/pc-client/src/assets/images/chatHeader/group_notice.png new file mode 100644 index 0000000..affce6d Binary files /dev/null and b/pc-client/src/assets/images/chatHeader/group_notice.png differ diff --git a/pc-client/src/assets/images/chatHeader/launch_group.png b/pc-client/src/assets/images/chatHeader/launch_group.png new file mode 100644 index 0000000..b9bda55 Binary files /dev/null and b/pc-client/src/assets/images/chatHeader/launch_group.png differ diff --git a/pc-client/src/assets/images/chatHeader/search_history.png b/pc-client/src/assets/images/chatHeader/search_history.png new file mode 100644 index 0000000..855bb47 Binary files /dev/null and b/pc-client/src/assets/images/chatHeader/search_history.png differ diff --git a/pc-client/src/assets/images/chatHeader/settings.png b/pc-client/src/assets/images/chatHeader/settings.png new file mode 100644 index 0000000..a7e762c Binary files /dev/null and b/pc-client/src/assets/images/chatHeader/settings.png differ diff --git a/pc-client/src/assets/images/chatHeader/speaker.png b/pc-client/src/assets/images/chatHeader/speaker.png new file mode 100644 index 0000000..e82888a Binary files /dev/null and b/pc-client/src/assets/images/chatHeader/speaker.png differ diff --git a/pc-client/src/assets/images/chatSetting/copy.png b/pc-client/src/assets/images/chatSetting/copy.png new file mode 100644 index 0000000..0f51bc8 Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/copy.png differ diff --git a/pc-client/src/assets/images/chatSetting/edit_avatar.png b/pc-client/src/assets/images/chatSetting/edit_avatar.png new file mode 100644 index 0000000..cd8e6b7 Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/edit_avatar.png differ diff --git a/pc-client/src/assets/images/chatSetting/edit_name.png b/pc-client/src/assets/images/chatSetting/edit_name.png new file mode 100644 index 0000000..4afb4be Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/edit_name.png differ diff --git a/pc-client/src/assets/images/chatSetting/empty_announcement.png b/pc-client/src/assets/images/chatSetting/empty_announcement.png new file mode 100644 index 0000000..f5a2672 Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/empty_announcement.png differ diff --git a/pc-client/src/assets/images/chatSetting/invite.png b/pc-client/src/assets/images/chatSetting/invite.png new file mode 100644 index 0000000..a6fe589 Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/invite.png differ diff --git a/pc-client/src/assets/images/chatSetting/invite_header.png b/pc-client/src/assets/images/chatSetting/invite_header.png new file mode 100644 index 0000000..b97883c Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/invite_header.png differ diff --git a/pc-client/src/assets/images/chatSetting/kick.png b/pc-client/src/assets/images/chatSetting/kick.png new file mode 100644 index 0000000..e510b2c Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/kick.png differ diff --git a/pc-client/src/assets/images/chatSetting/member_admin.png b/pc-client/src/assets/images/chatSetting/member_admin.png new file mode 100644 index 0000000..087a6ab Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/member_admin.png differ diff --git a/pc-client/src/assets/images/chatSetting/member_admin_active.png b/pc-client/src/assets/images/chatSetting/member_admin_active.png new file mode 100644 index 0000000..0dc100d Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/member_admin_active.png differ diff --git a/pc-client/src/assets/images/chatSetting/member_delete.png b/pc-client/src/assets/images/chatSetting/member_delete.png new file mode 100644 index 0000000..35e0e8a Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/member_delete.png differ diff --git a/pc-client/src/assets/images/chatSetting/member_mute.png b/pc-client/src/assets/images/chatSetting/member_mute.png new file mode 100644 index 0000000..8fa697a Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/member_mute.png differ diff --git a/pc-client/src/assets/images/chatSetting/member_mute_active.png b/pc-client/src/assets/images/chatSetting/member_mute_active.png new file mode 100644 index 0000000..bef1fd7 Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/member_mute_active.png differ diff --git a/pc-client/src/assets/images/chatSetting/search.png b/pc-client/src/assets/images/chatSetting/search.png new file mode 100644 index 0000000..57c399f Binary files /dev/null and b/pc-client/src/assets/images/chatSetting/search.png differ diff --git a/pc-client/src/assets/images/chooseModal/friend.png b/pc-client/src/assets/images/chooseModal/friend.png new file mode 100644 index 0000000..49b6202 Binary files /dev/null and b/pc-client/src/assets/images/chooseModal/friend.png differ diff --git a/pc-client/src/assets/images/chooseModal/group.png b/pc-client/src/assets/images/chooseModal/group.png new file mode 100644 index 0000000..55846ee Binary files /dev/null and b/pc-client/src/assets/images/chooseModal/group.png differ diff --git a/pc-client/src/assets/images/chooseModal/recently.png b/pc-client/src/assets/images/chooseModal/recently.png new file mode 100644 index 0000000..8fdb743 Binary files /dev/null and b/pc-client/src/assets/images/chooseModal/recently.png differ diff --git a/pc-client/src/assets/images/common/bench.png b/pc-client/src/assets/images/common/bench.png new file mode 100644 index 0000000..203e62f Binary files /dev/null and b/pc-client/src/assets/images/common/bench.png differ diff --git a/pc-client/src/assets/images/common/bench_active.png b/pc-client/src/assets/images/common/bench_active.png new file mode 100644 index 0000000..88cdb33 Binary files /dev/null and b/pc-client/src/assets/images/common/bench_active.png differ diff --git a/pc-client/src/assets/images/common/call.png b/pc-client/src/assets/images/common/call.png new file mode 100644 index 0000000..05528c9 Binary files /dev/null and b/pc-client/src/assets/images/common/call.png differ diff --git a/pc-client/src/assets/images/common/call_active.png b/pc-client/src/assets/images/common/call_active.png new file mode 100644 index 0000000..dc0b962 Binary files /dev/null and b/pc-client/src/assets/images/common/call_active.png differ diff --git a/pc-client/src/assets/images/common/cancel.png b/pc-client/src/assets/images/common/cancel.png new file mode 100644 index 0000000..2d0df37 Binary files /dev/null and b/pc-client/src/assets/images/common/cancel.png differ diff --git a/pc-client/src/assets/images/common/cancel_active.png b/pc-client/src/assets/images/common/cancel_active.png new file mode 100644 index 0000000..0102535 Binary files /dev/null and b/pc-client/src/assets/images/common/cancel_active.png differ diff --git a/pc-client/src/assets/images/common/card.png b/pc-client/src/assets/images/common/card.png new file mode 100644 index 0000000..75ea556 Binary files /dev/null and b/pc-client/src/assets/images/common/card.png differ diff --git a/pc-client/src/assets/images/common/card_active.png b/pc-client/src/assets/images/common/card_active.png new file mode 100644 index 0000000..832fa28 Binary files /dev/null and b/pc-client/src/assets/images/common/card_active.png differ diff --git a/pc-client/src/assets/images/common/card_bg.png b/pc-client/src/assets/images/common/card_bg.png new file mode 100644 index 0000000..7705429 Binary files /dev/null and b/pc-client/src/assets/images/common/card_bg.png differ diff --git a/pc-client/src/assets/images/common/clock.png b/pc-client/src/assets/images/common/clock.png new file mode 100644 index 0000000..d1c1c91 Binary files /dev/null and b/pc-client/src/assets/images/common/clock.png differ diff --git a/pc-client/src/assets/images/common/member_etc.png b/pc-client/src/assets/images/common/member_etc.png new file mode 100644 index 0000000..80e7dbd Binary files /dev/null and b/pc-client/src/assets/images/common/member_etc.png differ diff --git a/pc-client/src/assets/images/common/sync.png b/pc-client/src/assets/images/common/sync.png new file mode 100644 index 0000000..b292ce0 Binary files /dev/null and b/pc-client/src/assets/images/common/sync.png differ diff --git a/pc-client/src/assets/images/common/sync_error.png b/pc-client/src/assets/images/common/sync_error.png new file mode 100644 index 0000000..20eff77 Binary files /dev/null and b/pc-client/src/assets/images/common/sync_error.png differ diff --git a/pc-client/src/assets/images/contact/arrowTopRight.png b/pc-client/src/assets/images/contact/arrowTopRight.png new file mode 100644 index 0000000..9d557c4 Binary files /dev/null and b/pc-client/src/assets/images/contact/arrowTopRight.png differ diff --git a/pc-client/src/assets/images/contact/frequent_contacts.png b/pc-client/src/assets/images/contact/frequent_contacts.png new file mode 100644 index 0000000..e2b12ab Binary files /dev/null and b/pc-client/src/assets/images/contact/frequent_contacts.png differ diff --git a/pc-client/src/assets/images/contact/group.png b/pc-client/src/assets/images/contact/group.png new file mode 100644 index 0000000..b25c5ec Binary files /dev/null and b/pc-client/src/assets/images/contact/group.png differ diff --git a/pc-client/src/assets/images/contact/group_notifications.png b/pc-client/src/assets/images/contact/group_notifications.png new file mode 100644 index 0000000..cadb0bd Binary files /dev/null and b/pc-client/src/assets/images/contact/group_notifications.png differ diff --git a/pc-client/src/assets/images/contact/label.png b/pc-client/src/assets/images/contact/label.png new file mode 100644 index 0000000..26c9d69 Binary files /dev/null and b/pc-client/src/assets/images/contact/label.png differ diff --git a/pc-client/src/assets/images/contact/my_friends.png b/pc-client/src/assets/images/contact/my_friends.png new file mode 100644 index 0000000..49b6202 Binary files /dev/null and b/pc-client/src/assets/images/contact/my_friends.png differ diff --git a/pc-client/src/assets/images/contact/my_groups.png b/pc-client/src/assets/images/contact/my_groups.png new file mode 100644 index 0000000..55846ee Binary files /dev/null and b/pc-client/src/assets/images/contact/my_groups.png differ diff --git a/pc-client/src/assets/images/contact/new_friends.png b/pc-client/src/assets/images/contact/new_friends.png new file mode 100644 index 0000000..dc88672 Binary files /dev/null and b/pc-client/src/assets/images/contact/new_friends.png differ diff --git a/pc-client/src/assets/images/contact/tuoyun.png b/pc-client/src/assets/images/contact/tuoyun.png new file mode 100644 index 0000000..8d43630 Binary files /dev/null and b/pc-client/src/assets/images/contact/tuoyun.png differ diff --git a/pc-client/src/assets/images/contact/union.png b/pc-client/src/assets/images/contact/union.png new file mode 100644 index 0000000..cf45626 Binary files /dev/null and b/pc-client/src/assets/images/contact/union.png differ diff --git a/pc-client/src/assets/images/disturb.png b/pc-client/src/assets/images/disturb.png new file mode 100644 index 0000000..b459be3 Binary files /dev/null and b/pc-client/src/assets/images/disturb.png differ diff --git a/pc-client/src/assets/images/empty_chat_bg.png b/pc-client/src/assets/images/empty_chat_bg.png new file mode 100644 index 0000000..2bb5612 Binary files /dev/null and b/pc-client/src/assets/images/empty_chat_bg.png differ diff --git a/pc-client/src/assets/images/login/login_bg.png b/pc-client/src/assets/images/login/login_bg.png new file mode 100644 index 0000000..f1a5345 Binary files /dev/null and b/pc-client/src/assets/images/login/login_bg.png differ diff --git a/pc-client/src/assets/images/login/login_pc.png b/pc-client/src/assets/images/login/login_pc.png new file mode 100644 index 0000000..b95e3fd Binary files /dev/null and b/pc-client/src/assets/images/login/login_pc.png differ diff --git a/pc-client/src/assets/images/login/login_qr.png b/pc-client/src/assets/images/login/login_qr.png new file mode 100644 index 0000000..0674e41 Binary files /dev/null and b/pc-client/src/assets/images/login/login_qr.png differ diff --git a/pc-client/src/assets/images/messageItem/file_download.png b/pc-client/src/assets/images/messageItem/file_download.png new file mode 100644 index 0000000..ca6f756 Binary files /dev/null and b/pc-client/src/assets/images/messageItem/file_download.png differ diff --git a/pc-client/src/assets/images/messageItem/file_downloaded.png b/pc-client/src/assets/images/messageItem/file_downloaded.png new file mode 100644 index 0000000..9dfa83a Binary files /dev/null and b/pc-client/src/assets/images/messageItem/file_downloaded.png differ diff --git a/pc-client/src/assets/images/messageItem/file_icon.png b/pc-client/src/assets/images/messageItem/file_icon.png new file mode 100644 index 0000000..9e6a0a9 Binary files /dev/null and b/pc-client/src/assets/images/messageItem/file_icon.png differ diff --git a/pc-client/src/assets/images/messageItem/location.png b/pc-client/src/assets/images/messageItem/location.png new file mode 100644 index 0000000..de15490 Binary files /dev/null and b/pc-client/src/assets/images/messageItem/location.png differ diff --git a/pc-client/src/assets/images/messageItem/play_video.png b/pc-client/src/assets/images/messageItem/play_video.png new file mode 100644 index 0000000..0053edc Binary files /dev/null and b/pc-client/src/assets/images/messageItem/play_video.png differ diff --git a/pc-client/src/assets/images/messageMenu/check.png b/pc-client/src/assets/images/messageMenu/check.png new file mode 100644 index 0000000..0b0f7ae Binary files /dev/null and b/pc-client/src/assets/images/messageMenu/check.png differ diff --git a/pc-client/src/assets/images/messageMenu/copy.png b/pc-client/src/assets/images/messageMenu/copy.png new file mode 100644 index 0000000..4fab7bd Binary files /dev/null and b/pc-client/src/assets/images/messageMenu/copy.png differ diff --git a/pc-client/src/assets/images/messageMenu/emoji.png b/pc-client/src/assets/images/messageMenu/emoji.png new file mode 100644 index 0000000..45570f2 Binary files /dev/null and b/pc-client/src/assets/images/messageMenu/emoji.png differ diff --git a/pc-client/src/assets/images/messageMenu/forward.png b/pc-client/src/assets/images/messageMenu/forward.png new file mode 100644 index 0000000..5e7a13d Binary files /dev/null and b/pc-client/src/assets/images/messageMenu/forward.png differ diff --git a/pc-client/src/assets/images/messageMenu/remove.png b/pc-client/src/assets/images/messageMenu/remove.png new file mode 100644 index 0000000..d338b37 Binary files /dev/null and b/pc-client/src/assets/images/messageMenu/remove.png differ diff --git a/pc-client/src/assets/images/messageMenu/reply.png b/pc-client/src/assets/images/messageMenu/reply.png new file mode 100644 index 0000000..42412e5 Binary files /dev/null and b/pc-client/src/assets/images/messageMenu/reply.png differ diff --git a/pc-client/src/assets/images/messageMenu/revoke.png b/pc-client/src/assets/images/messageMenu/revoke.png new file mode 100644 index 0000000..dabdb3b Binary files /dev/null and b/pc-client/src/assets/images/messageMenu/revoke.png differ diff --git a/pc-client/src/assets/images/moments/background.png b/pc-client/src/assets/images/moments/background.png new file mode 100644 index 0000000..2077c95 Binary files /dev/null and b/pc-client/src/assets/images/moments/background.png differ diff --git a/pc-client/src/assets/images/nav/nav_bar_contact.png b/pc-client/src/assets/images/nav/nav_bar_contact.png new file mode 100644 index 0000000..829e710 Binary files /dev/null and b/pc-client/src/assets/images/nav/nav_bar_contact.png differ diff --git a/pc-client/src/assets/images/nav/nav_bar_contact_active.png b/pc-client/src/assets/images/nav/nav_bar_contact_active.png new file mode 100644 index 0000000..8eb327c Binary files /dev/null and b/pc-client/src/assets/images/nav/nav_bar_contact_active.png differ diff --git a/pc-client/src/assets/images/nav/nav_bar_message.png b/pc-client/src/assets/images/nav/nav_bar_message.png new file mode 100644 index 0000000..0a9f67e Binary files /dev/null and b/pc-client/src/assets/images/nav/nav_bar_message.png differ diff --git a/pc-client/src/assets/images/nav/nav_bar_message_active.png b/pc-client/src/assets/images/nav/nav_bar_message_active.png new file mode 100644 index 0000000..6f2c211 Binary files /dev/null and b/pc-client/src/assets/images/nav/nav_bar_message_active.png differ diff --git a/pc-client/src/assets/images/nav/nav_bar_moments.png b/pc-client/src/assets/images/nav/nav_bar_moments.png new file mode 100644 index 0000000..0019cca Binary files /dev/null and b/pc-client/src/assets/images/nav/nav_bar_moments.png differ diff --git a/pc-client/src/assets/images/nav/nav_bar_moments_active.png b/pc-client/src/assets/images/nav/nav_bar_moments_active.png new file mode 100644 index 0000000..b4b88ae Binary files /dev/null and b/pc-client/src/assets/images/nav/nav_bar_moments_active.png differ diff --git a/pc-client/src/assets/images/nav/nav_bar_workbench.png b/pc-client/src/assets/images/nav/nav_bar_workbench.png new file mode 100644 index 0000000..bc731db Binary files /dev/null and b/pc-client/src/assets/images/nav/nav_bar_workbench.png differ diff --git a/pc-client/src/assets/images/nav/nav_bar_workbench_active.png b/pc-client/src/assets/images/nav/nav_bar_workbench_active.png new file mode 100644 index 0000000..0005636 Binary files /dev/null and b/pc-client/src/assets/images/nav/nav_bar_workbench_active.png differ diff --git a/pc-client/src/assets/images/profile/change_avatar.png b/pc-client/src/assets/images/profile/change_avatar.png new file mode 100644 index 0000000..dabf2a1 Binary files /dev/null and b/pc-client/src/assets/images/profile/change_avatar.png differ diff --git a/pc-client/src/assets/images/profile/logo.png b/pc-client/src/assets/images/profile/logo.png new file mode 100644 index 0000000..4770c19 Binary files /dev/null and b/pc-client/src/assets/images/profile/logo.png differ diff --git a/pc-client/src/assets/images/rtc/rtc_accept.png b/pc-client/src/assets/images/rtc/rtc_accept.png new file mode 100644 index 0000000..f7edffd Binary files /dev/null and b/pc-client/src/assets/images/rtc/rtc_accept.png differ diff --git a/pc-client/src/assets/images/rtc/rtc_camera.png b/pc-client/src/assets/images/rtc/rtc_camera.png new file mode 100644 index 0000000..add5dfe Binary files /dev/null and b/pc-client/src/assets/images/rtc/rtc_camera.png differ diff --git a/pc-client/src/assets/images/rtc/rtc_camera_off.png b/pc-client/src/assets/images/rtc/rtc_camera_off.png new file mode 100644 index 0000000..8b114dd Binary files /dev/null and b/pc-client/src/assets/images/rtc/rtc_camera_off.png differ diff --git a/pc-client/src/assets/images/rtc/rtc_hungup.png b/pc-client/src/assets/images/rtc/rtc_hungup.png new file mode 100644 index 0000000..e283e65 Binary files /dev/null and b/pc-client/src/assets/images/rtc/rtc_hungup.png differ diff --git a/pc-client/src/assets/images/rtc/rtc_mic.png b/pc-client/src/assets/images/rtc/rtc_mic.png new file mode 100644 index 0000000..698e579 Binary files /dev/null and b/pc-client/src/assets/images/rtc/rtc_mic.png differ diff --git a/pc-client/src/assets/images/rtc/rtc_mic_off.png b/pc-client/src/assets/images/rtc/rtc_mic_off.png new file mode 100644 index 0000000..5b9f5cd Binary files /dev/null and b/pc-client/src/assets/images/rtc/rtc_mic_off.png differ diff --git a/pc-client/src/assets/images/searchModal/empty.png b/pc-client/src/assets/images/searchModal/empty.png new file mode 100644 index 0000000..d120c0e Binary files /dev/null and b/pc-client/src/assets/images/searchModal/empty.png differ diff --git a/pc-client/src/assets/images/topSearchBar/add_friend.png b/pc-client/src/assets/images/topSearchBar/add_friend.png new file mode 100644 index 0000000..ee9ffbe Binary files /dev/null and b/pc-client/src/assets/images/topSearchBar/add_friend.png differ diff --git a/pc-client/src/assets/images/topSearchBar/add_group.png b/pc-client/src/assets/images/topSearchBar/add_group.png new file mode 100644 index 0000000..5e0af09 Binary files /dev/null and b/pc-client/src/assets/images/topSearchBar/add_group.png differ diff --git a/pc-client/src/assets/images/topSearchBar/create_group.png b/pc-client/src/assets/images/topSearchBar/create_group.png new file mode 100644 index 0000000..59a309b Binary files /dev/null and b/pc-client/src/assets/images/topSearchBar/create_group.png differ diff --git a/pc-client/src/assets/images/topSearchBar/meeting.png b/pc-client/src/assets/images/topSearchBar/meeting.png new file mode 100644 index 0000000..961642f Binary files /dev/null and b/pc-client/src/assets/images/topSearchBar/meeting.png differ diff --git a/pc-client/src/assets/images/topSearchBar/search.png b/pc-client/src/assets/images/topSearchBar/search.png new file mode 100644 index 0000000..ee18aa9 Binary files /dev/null and b/pc-client/src/assets/images/topSearchBar/search.png differ diff --git a/pc-client/src/assets/images/topSearchBar/show_more.png b/pc-client/src/assets/images/topSearchBar/show_more.png new file mode 100644 index 0000000..aefb05b Binary files /dev/null and b/pc-client/src/assets/images/topSearchBar/show_more.png differ diff --git a/pc-client/src/assets/images/topSearchBar/win_close.png b/pc-client/src/assets/images/topSearchBar/win_close.png new file mode 100644 index 0000000..2cfb85f Binary files /dev/null and b/pc-client/src/assets/images/topSearchBar/win_close.png differ diff --git a/pc-client/src/assets/images/topSearchBar/win_max.png b/pc-client/src/assets/images/topSearchBar/win_max.png new file mode 100644 index 0000000..2fec434 Binary files /dev/null and b/pc-client/src/assets/images/topSearchBar/win_max.png differ diff --git a/pc-client/src/assets/images/topSearchBar/win_min.png b/pc-client/src/assets/images/topSearchBar/win_min.png new file mode 100644 index 0000000..f945a0f Binary files /dev/null and b/pc-client/src/assets/images/topSearchBar/win_min.png differ diff --git a/pc-client/src/assets/node.svg b/pc-client/src/assets/node.svg new file mode 100644 index 0000000..38d4eaa --- /dev/null +++ b/pc-client/src/assets/node.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pc-client/src/config/index.ts b/pc-client/src/config/index.ts new file mode 100644 index 0000000..587e0b4 --- /dev/null +++ b/pc-client/src/config/index.ts @@ -0,0 +1,4 @@ +export const APP_NAME = "畅联"; +export const APP_VERSION = "v1.0.0"; +export const SDK_VERSION = "SDK(ffi) v3.8.3"; +export const isSaveLog = process.env.NODE_ENV !== "development"; diff --git a/pc-client/src/constants/errcode.ts b/pc-client/src/constants/errcode.ts new file mode 100644 index 0000000..d40f626 --- /dev/null +++ b/pc-client/src/constants/errcode.ts @@ -0,0 +1,15 @@ +import { t } from "i18next"; + +export const ErrCodeMap: Record = { + 20001: t("errCode.passwordError"), + 20002: t("errCode.accountNotExist"), + 20003: t("errCode.phoneNumberRegistered"), + 20004: t("errCode.accountRegistered"), + 20005: t("errCode.operationTooFrequent"), + 20012: t("errCode.operationRestriction"), + 20014: t("errCode.accountRegistered"), +}; + +export enum SendFailedErrCode { + Blacked = 1302, +} diff --git a/pc-client/src/constants/im.ts b/pc-client/src/constants/im.ts new file mode 100644 index 0000000..93c89fa --- /dev/null +++ b/pc-client/src/constants/im.ts @@ -0,0 +1,34 @@ +import { MessageType, SessionType } from "@openim/wasm-client-sdk"; + +export const GroupSessionTypes = [SessionType.Group, SessionType.WorkingGroup]; + +export const GroupSystemMessageTypes = [ + MessageType.GroupCreated, + MessageType.GroupInfoUpdated, + MessageType.MemberQuit, + MessageType.GroupOwnerTransferred, + MessageType.MemberKicked, + MessageType.MemberInvited, + MessageType.MemberEnter, + MessageType.GroupDismissed, + MessageType.GroupMemberMuted, + MessageType.GroupMuted, + MessageType.GroupCancelMuted, + MessageType.GroupMemberCancelMuted, + MessageType.GroupNameUpdated, +]; + +export const SystemMessageTypes = [ + MessageType.RevokeMessage, + MessageType.FriendAdded, + MessageType.BurnMessageChange, + ...GroupSystemMessageTypes, +]; + +export enum CustomType { + CallingInvite = 200, + CallingAccept = 201, + CallingReject = 202, + CallingCancel = 203, + CallingHungup = 204, +} diff --git a/pc-client/src/constants/index.ts b/pc-client/src/constants/index.ts new file mode 100644 index 0000000..cbe1c7a --- /dev/null +++ b/pc-client/src/constants/index.ts @@ -0,0 +1,2 @@ +export * from "./errcode"; +export * from "./im"; diff --git a/pc-client/src/hooks/useConversationToggle.ts b/pc-client/src/hooks/useConversationToggle.ts new file mode 100644 index 0000000..44b362c --- /dev/null +++ b/pc-client/src/hooks/useConversationToggle.ts @@ -0,0 +1,69 @@ +import type { SessionType } from "@openim/wasm-client-sdk"; +import { ConversationItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import { useCallback } from "react"; +import { useNavigate } from "react-router-dom"; + +import { IMSDK } from "@/layout/MainContentWrap"; +import { useConversationStore } from "@/store"; +import { feedbackToast } from "@/utils/common"; + +export type ToSpecifiedConversationParams = { + sourceID: string; + sessionType: SessionType; + isJump?: boolean; + isChildWindow?: boolean; +}; + +export function useConversationToggle() { + const navigate = useNavigate(); + const updateCurrentConversation = useConversationStore( + (state) => state.updateCurrentConversation, + ); + + const getConversation = async ({ + sourceID, + sessionType, + }: { + sourceID: string; + sessionType: SessionType; + }): Promise => { + let conversation = useConversationStore + .getState() + .conversationList.find( + (item) => item.userID === sourceID || item.groupID === sourceID, + ); + if (!conversation) { + try { + conversation = ( + await IMSDK.getOneConversation({ + sourceID, + sessionType, + }) + ).data; + } catch (error) { + feedbackToast({ error }); + } + } + return conversation; + }; + + const toSpecifiedConversation = useCallback( + async (params: ToSpecifiedConversationParams) => { + const { sourceID, sessionType, isJump } = params; + const conversation = await getConversation({ sourceID, sessionType }); + if ( + !conversation || + useConversationStore.getState().currentConversation?.conversationID === + conversation.conversationID + ) + return; + await updateCurrentConversation({ ...conversation }, isJump); + navigate(`/chat/${conversation.conversationID}`); + }, + [], + ); + + return { + toSpecifiedConversation, + }; +} diff --git a/pc-client/src/hooks/useCurrentMemberRole.ts b/pc-client/src/hooks/useCurrentMemberRole.ts new file mode 100644 index 0000000..7c0cb3d --- /dev/null +++ b/pc-client/src/hooks/useCurrentMemberRole.ts @@ -0,0 +1,25 @@ +import { GroupMemberRole } from "@openim/wasm-client-sdk"; + +import { useConversationStore } from "@/store"; + +export function useCurrentMemberRole() { + const currentMemberInGroup = useConversationStore( + (state) => state.currentMemberInGroup, + ); + + const isOwner = currentMemberInGroup?.roleLevel === GroupMemberRole.Owner; + const isAdmin = currentMemberInGroup?.roleLevel === GroupMemberRole.Admin; + const isNomal = currentMemberInGroup?.roleLevel === GroupMemberRole.Normal; + const currentRolevel = currentMemberInGroup?.roleLevel ?? 0; + const currentIsMuted = (currentMemberInGroup?.muteEndTime ?? 0) > Date.now(); + + return { + isOwner, + isAdmin, + isNomal, + isJoinGroup: Boolean(currentMemberInGroup?.userID), + currentRolevel, + currentIsMuted, + currentMemberInGroup, + }; +} diff --git a/pc-client/src/hooks/useGroupMembers.ts b/pc-client/src/hooks/useGroupMembers.ts new file mode 100644 index 0000000..d582371 --- /dev/null +++ b/pc-client/src/hooks/useGroupMembers.ts @@ -0,0 +1,92 @@ +import { + GroupMemberItem, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import { useLatest } from "ahooks"; +import { useCallback, useState } from "react"; + +import { IMSDK } from "@/layout/MainContentWrap"; +import { useConversationStore } from "@/store"; +import { feedbackToast } from "@/utils/common"; +export interface FetchStateType { + offset: number; + count: number; + loading: boolean; + hasMore: boolean; + groupMemberList: GroupMemberItem[]; +} + +interface UseGroupMembersProps { + groupID?: string; +} + +export default function useGroupMembers(props?: UseGroupMembersProps) { + const { groupID } = props ?? {}; + const [fetchState, setFetchState] = useState({ + offset: 0, + count: 20, + loading: false, + hasMore: true, + groupMemberList: [], + }); + const latestFetchState = useLatest(fetchState); + + const getMemberData = useCallback( + async (refresh = false) => { + const sourceID = + groupID ?? useConversationStore.getState().currentConversation?.groupID ?? ""; + if (!sourceID) return; + + if ( + (latestFetchState.current.loading || !latestFetchState.current.hasMore) && + !refresh + ) + return; + + setFetchState((state) => ({ + ...state, + loading: true, + })); + try { + const { data } = await IMSDK.getGroupMemberList({ + groupID: sourceID, + offset: refresh ? 0 : latestFetchState.current.offset, + count: refresh ? 500 : 100, + filter: 0, + }); + setFetchState((state) => ({ + ...state, + groupMemberList: [...(refresh ? [] : state.groupMemberList), ...data], + hasMore: data.length === (refresh ? 500 : 100), + offset: state.offset + (refresh ? 500 : 100), + loading: false, + })); + } catch (error) { + feedbackToast({ + msg: "getMemberFailed", + error, + }); + setFetchState((state) => ({ + ...state, + loading: false, + })); + } + }, + [groupID], + ); + + const resetState = () => { + setFetchState({ + offset: 0, + count: 20, + loading: false, + hasMore: true, + groupMemberList: [], + }); + }; + + return { + fetchState, + getMemberData, + resetState, + }; +} diff --git a/pc-client/src/hooks/useOverlayVisible.ts b/pc-client/src/hooks/useOverlayVisible.ts new file mode 100644 index 0000000..de2b475 --- /dev/null +++ b/pc-client/src/hooks/useOverlayVisible.ts @@ -0,0 +1,30 @@ +import { ForwardedRef, useCallback, useImperativeHandle, useState } from "react"; + +export interface OverlayVisibleHandle { + isOverlayOpen: boolean; + openOverlay: () => void; + closeOverlay: () => void; +} + +export function useOverlayVisible(ref: ForwardedRef) { + const [isOverlayOpen, setIsOverlayOpen] = useState(false); + + const openOverlay = useCallback(() => { + setIsOverlayOpen(true); + }, []); + const closeOverlay = useCallback(() => { + setIsOverlayOpen(false); + }, []); + + useImperativeHandle(ref, () => ({ + isOverlayOpen, + openOverlay, + closeOverlay, + })); + + return { + isOverlayOpen, + openOverlay, + closeOverlay, + }; +} diff --git a/pc-client/src/i18n/index.ts b/pc-client/src/i18n/index.ts new file mode 100644 index 0000000..67a931d --- /dev/null +++ b/pc-client/src/i18n/index.ts @@ -0,0 +1,41 @@ +import "dayjs/locale/zh-cn"; + +import dayjs from "dayjs"; +import i18n from "i18next"; +// import LanguageDetector from "i18next-browser-languagedetector"; +import { initReactI18next } from "react-i18next"; + +import { getLocale } from "@/utils/storage"; + +import translation_en from "./resources/en.json"; +import translation_zh from "./resources/zh.json"; + +const resources = { + "en-US": { + translation: translation_en, + }, + "zh-CN": { + translation: translation_zh, + }, + zh: { + translation: translation_zh, + }, +}; + +i18n + .use(initReactI18next) + // .use(LanguageDetector) + .init({ + resources, + lng: getLocale(), + fallbackLng: "zh-CN", + interpolation: { + escapeValue: false, + }, + }) + .then(() => dayjs.locale(i18n.language)) + .catch(() => console.error("i18n init error")); + +i18n.on("languageChanged", () => dayjs.locale(i18n.language)); + +export default i18n; diff --git a/pc-client/src/i18n/resources/en.json b/pc-client/src/i18n/resources/en.json new file mode 100644 index 0000000..51a0877 --- /dev/null +++ b/pc-client/src/i18n/resources/en.json @@ -0,0 +1,499 @@ +{ + "me": "I", + "you": "You", + "yes": "Yes", + "no": "No", + "confirm": "Confirm", + "retry": "Retry", + "cancel": "Cancel", + "canceled": "Canceled", + "pieces": "Pieces", + "open": "Open", + "close": "Close", + "clear": "Clear", + "answer": "Answer", + "hangUp": "Hang up", + "notStart": "Not started", + "waitingStart": "Awaiting", + "alreadyStarted": "Already", + "finished": "Finished", + "clickToView": "Click to view", + "jumpToMessage": "Jump to message", + "connect": { + "syncing": "Syncing", + "syncFailed": "Sync Failed", + "connecting": "Connecting", + "connectFailed": "Connect Failed" + }, + "toast": { + "accessSuccess": "Operation successful!", + "accessFailed": "Operation failed!", + "getConversationFailed": "Failed to get conversation list!", + "getGroupInfoFailed": "Failed to get group information!", + "getGroupMemberFailed": "Failed to get group member information!", + "getHistoryMessageFailed": "Failed to get history messages!", + "getSelfInfoFailed": "Failed to get personal information!", + "getFriendListFailed": "Failed to get friend list!", + "getBlackListFailed": "Failed to get blacklist!", + "getGroupListFailed": "Failed to get group list!", + "getOnlineStatusFailed": "Failed to get online status!", + "getMemberListFailed": "Failed to get group members!", + "getUserInfoFailed": "Failed to get user information!", + "pinConversationFailed": "Failed to modify pinned conversation status!", + "setConversationRecvMessageOptFailed": "Failed to modify conversation message reception status!", + "clearConversationMessagesFailed": "Failed to delete conversation messages!", + "deleteConversationFailed": "Failed to delete conversation!", + "updateGroupVerificationFailed": "Failed to modify group verification method!", + "updateGroupInfoFailed": "Failed to modify group information!", + "updateConversationPrivateStateFailed": "Failed to modify after-reading burn status!", + "updateBlackStateFailed": "Failed to modify blacklist status!", + "unfriendFailed": "Failed to unfriend!", + "getMessageListFailed": "Failed to get message list!", + "sendApplicationFailed": "Failed to send request!", + "loading": "Logging in...", + "syncing": "Syncing...", + "syncFailed": "Sync failed!", + "appUpdate": "App update", + "updateVersion": "New version {{version}} found. Update now?", + "updateContent": "Update content:", + "isCancelUpdate": "Are you sure you want to cancel the update?", + "clearChatHistory": "Clear chat history", + "confirmClearChatHistory": "Are you sure you want to clear chat history?", + "downloading": "Downloading...", + "applyUpdateSuccess": "Download complete, effective after restart, are you sure you want to restart now?", + "later": "Later", + "applyDownloadSuccess": "Download complete, follow the installer to update!", + "applyDownloadFailed": "Download failed!", + "loginExpiration": "Current login has expired, please log in again!", + "accountKicked": "Your account has logged in on another device, please log in again!", + "updatePasswordSuccess": "Password updated successfully, please log in again!", + "inputOldPassword": "Please enter your old password!", + "passwordRules": "6-20 characters ,at least including numbers and letters", + "reconfirmPassword": "Please confirm your password again", + "passwordsDifferent": "Passwords do not match!", + "confirmlogOut": "Are you sure you want to log out of the current account?", + "updateAvatarFailed": "Failed to change avatar!", + "notCanSendMessage": "Cannot send messages in a group chat that you have quit!", + "groupMuted": "The administrator or group owner has muted everyone!", + "currentMuted": "You have been muted by the administrator or group owner!", + "messagesDeleteFailed": "Some messages failed to delete!", + "confirmkickMember": "Are you sure you want to kick {{name}} from the group chat?", + "addSuccess": "Added successfully!", + "copySuccess": "Copied successfully!", + "copyFailed": "Copy failed!", + "confirmAllMuted": "Are you sure you want to mute everyone?", + "confirmDisbandGroup": "Are you sure you want to disband this group?", + "confirmExitGroup": "Are you sure you want to exit this group?", + "confirmMoveBlacklist": "Are you sure you want to add this friend to the blacklist?", + "userBlacked": "This user has been added to the blacklist!", + "confirmUnfriend": "Are you sure you want to unfriend?", + "selectLeastOne": "Please select at least one option!", + "inputGroupName": "Please enter a group name", + "inputContent": "Please enter a content", + "sendSuccess": "Sent successfully!", + "beyondSelectionLimit": "Selection limit exceeded!", + "sendJoinGroupRequestSuccess": "Sent group join request successfully!", + "inputNickName": "Please enter a nickname", + "inputPhoneNumber": "Please enter phone number", + "inputCorrectPhoneNumber": "Please enter a valid phone number!", + "inputEmail": "Please enter email address", + "inputCorrectEmail": "Please enter a valid email address!", + "inputVerifyCode": "Please enter your verification code", + "inputPassword": "Please enter your password", + "sendFreiendRequestSuccess": "Friend request sent successfully!", + "registerSuccess": "Registration successful!", + "inputInvitationCode": "Please enter your invitation code", + "downloadFailed": "Download failed!", + "beingBlacklist": "The other party has added you to the blacklist!", + "usingFriendVerification": "Friend verification is enabled, you are not yet their friend!", + "confirmDeleteMoment": "Are you sure you want to delete this moment?", + "uploadFailed": "Upload failed!", + "somethingError": "Seems like there was a small issue~", + "getLogFailed": "Failed to retrieve the log file!", + "publishFailed": "Failed to publish!", + "notCanAddFriend": "The other party has been set up not to be added as a friend!", + "fileTypeError": "Unsupported file type or folder!", + "inputStaffNo": "请输入工号", + "noMicrophone": "No microphone detected, cannot record", + "recordTooShort": "Recording is too short" + }, + "placeholder": { + "conversation": "Conversation", + "leaveMessage": "Leave a message", + "recover": "Click to recover", + "someInCall": "{{count}} people are on a call", + "compere": "Host", + "watchUser": "Watch him only", + "removeWatchUser": "Stop watching him only", + "fold": "Fold", + "participantCanUnmuteSelf": "Allow members to unmute themselves", + "participantCanEnableVideo": "Allow members to enable video", + "onlyHostShareScreen": "Only the host can share screen", + "onlyHostInviteUser": "Only the host can invite participants", + "joinDisableMicrophone": "Mute members upon joining", + "member": "Member", + "microphone": "Microphone", + "camera": "Camera", + "sharedScreen": "Share screen", + "endSharing": "End sharing", + "connecting": "Connecting...", + "uploadSuccess": "Upload successful", + "reportLog": "Report log", + "reportSpecificLog": "Report specific log", + "viewingLocalLogs": "View local logs", + "totalNumPhoto": "Total of {{num}} photos", + "somePersonLike": "{{num}} likes", + "whoCanWatch": "Who can see", + "remindWhoToWatch": "Remind who to see", + "publishMomentsToast": "Thoughts at this moment...", + "public": "Public", + "publicToast": "Visible to everyone", + "privacy": "Private", + "privacyToast": "Visible to you only", + "partlyVisible": "Visible to selected", + "partlyVisibleToast": "Only selected can see", + "hiddenSome": "Hide from selected", + "hiddenSomeToast": "Selected cannot see", + "comment": "Comment", + "hint": "Hint", + "toLike": "Like", + "byLike": "Liked your post", + "mentioned": "Mentioned", + "atYou": "Mentioned you", + "replied": "Replied", + "publishImages": "Post photos", + "publishVideo": "Post video", + "details": "Details", + "messageDestruct": "Automatically delete messages regularly", + "messageDestructTime": "Set time to auto-delete messages", + "messageDestructToast": "Messages sent after this will be deleted after the set time", + "moments": "Moments", + "somePerson": "{{num}} people", + "selectMember": "Select member", + "setInfo": "Set information", + "regain": "Retrieve again", + "optional": "(Optional)", + "invitationCode": "Invitation code", + "getBack": "Return", + "nextStep": "Next step", + "register": "Register new user", + "registerToast": "Don't have an account yet?", + "toRegister": "Register now", + "login": "Login", + "pleaseEnterSendTo": "Please enter sent to", + "verifyCode": "Verification code", + "verifyValidity": "6-digit verification code, valid for 10 minutes", + "sendVerifyCode": "Send verification code", + "qrCodeLogin": "QR code login", + "qrCodeLoginTitle": "Please scan the QR code using OpenCorp mobile", + "welcome": "欢迎使用畅联", + "title": "畅联", + "subTitle": "公司内部通讯工具", + "myCreated": "I created", + "myJoined": "I joined", + "newFriends": "New friends", + "groupNotification": "Group notification", + "friendVerification": "Friend verification", + "groupInfo": "Group information", + "personalInfo": "Personal information", + "inviteToGroup": " Invite to group", + "qrCodeToGroup": "Join group by scanning QR code", + "selectIDToGroup": "Search group ID", + "remark": "Remark", + "email": "Email", + "phoneNumber": "Phone Number", + "verifyPhoneNumber": "Verify phone number", + "verifyEmail": "Verify email", + "birth": "Birthday", + "gender": "Gender", + "man": "Male", + "female": "Female", + "unknown": "Unknown", + "nickName": "Nickname", + "groupNickName": "Group Nickname", + "joinGroupTime": "Joined Time", + "joinGroupMode": "Joined Method", + "editInfo": "Edit profile", + "message": "Chat information", + "relevantMessage": "{{count}} related chat records", + "overview": "Overview", + "latestChat": "Recent Chats", + "myFriend": "My Friends", + "myGroup": "My Groups", + "groupName": "Group Name", + "groupAvatar": "Group Avatar", + "groupMember": "Group Members", + "selected": "Selected", + "moveBlacklist": "Add to Blacklist", + "willFilterThisUserMessage": "You will not receive messages from this friend.", + "unfriend": "Unfriend", + "setStarFriend": "Set as Starred Friend", + "shieldConversation": "Block this Conversation", + "privateChat": "Burn after Reading", + "privateChatTime": "Burn after Reading Time", + "isRead": "Read", + "isReadList": "Message Read List", + "allIsRead": "All Read", + "isReadNum": "{{num}} have read", + "unreadNum": "{{num}} unread", + "unread": "Unread", + "revoke": "Revoke", + "copy": "Copy", + "check": "Multiple Selection", + "sendMessage": "Send Message", + "save": "Save", + "group": "Group", + "groupTppe": "Group Type", + "workGroup": "Work Group", + "myGroupNickname": "My Group Nickname", + "notNotify": "Mute Notifications", + "allMuted": "Mute All", + "allMutedClose": "Unmute All", + "groupVerification": "Group Verification", + "groupMemberPermissions": "Group Member Permissions", + "transferGroup": "Transfer Group", + "exitGroup": "Leave Group", + "exitGroupToast": "After exiting, you will no longer receive messages from this group.", + "disbandGroup": "Disband Group", + "disbandGroupToast": "All group members will be removed.", + "and": "{{someone}} and {{otherone}}", + "groupOwner": "Group Owner", + "administrator": "Administrator", + "setAdministrator": "Set as Administrator", + "mute": "Mute", + "cancelMute": "Unmute", + "setMute": "Set Mute", + "onlyManageCanSend": "Only group owner and administrators can send messages.", + "publish": "Publish", + "edit": "Edit", + "call": "Call", + "file": "File", + "document": "Documents", + "emoji": "Emoji", + "image": "Image", + "video": "Video", + "card": "Card", + "personalCard": "Personal Card", + "screenshot": "Screenshot", + "sticky": "Sticky on Top", + "removeSticky": "Remove from Top", + "draft": "Draft", + "pleaseEnter": "Please Enter", + "enterGroupName": "Choose a group name for easy to searches", + "clickToModify": "Click to Modify", + "search": "Search", + "about": "About Us", + "password": "Password", + "forgetPassword": "Forget Password", + "changePassword": "Change Password", + "checkNewVersion": "Check for New Version", + "viewMore": "View More", + "add": "Add", + "remove": "Remove", + "delete": "Delete", + "close": "Close", + "finder": "View", + "blackList": "Contact Blacklist", + "oldPassword": "Old Password:", + "newPassword": "New Password:", + "confirmPassword": "Confirm Password:", + "chat": "Messages", + "contact": "Contacts", + "contacts": "Contacts", + "myInfo": "My Information", + "accountSetting": "Account Settings", + "logOut": "Log Out", + "personalSetting": "Personal Settings", + "chooseLanguage": "Choose Language", + "closeButtonEvent": "Event when clicking the close button", + "exitApplication": "Exit Application", + "minimize": "Minimize to Tray", + "messageToast": "Message Alert", + "messageAllowBeep": "New Message Sound Alert", + "messageNotNotify": "Do Not Disturb Mode", + "addFriends": "Add Friends", + "verifyAdd": "Add", + "addGroup": "Add Group", + "createGroup": "Create Group Chat", + "createNow": "Create Now", + "createGroupToast": "Create a group to start online collaboration.", + "addFriendsSetting": "Add Friend Settings", + "refuseAddFriend": "Disallow Adding Me as a Friend", + "markAsRead": "Mark as Read", + "send": "Send", + "sendTo": "Send To:", + "groupAnnouncement": "Group Announcement", + "noGroupAnnouncement": "No group announcements yet~", + "needManageEdit": "Only the group owner and administrators can edit", + "loosenToSend": "Release to Send", + "reEdit": "Re-edit", + "multipleNewMessages": "{{count}} new messages", + "reply": "Reply", + "sendShortcutkey": "Enter to Send/Shift+Enter for New Line", + "sendWithEnter": "Send with Enter", + "sendWithShiftEnter": "Send with Shift+Enter", + "mentionAll": "Everyone", + "forward": "Forward", + "mergeForward": "Merge and Forward", + "messageHistory": "Chat History", + "whosMessageHistory": "Chat History for {{who}} ", + "launch": "Launched by", + "launchPerson": "Launcher", + "inviteYou": "Invites you for", + "videoCall": "Video Call", + "voiceCall": "Voice Call", + "meeting": "Video Meeting", + "meetingSetting": "Meeting Settings", + "someInMeeting": "{{count}} people are in the meeting", + "finishMeeting": "End meeting", + "leaveMeeting": "Leave meeting", + "meetingName": "Meeting topic", + "initiatedMeeting": "Initiated meeting", + "meetingTime": "Meeting duration", + "meetingID": "Meeting ID", + "meetingDetail": "Meeting details", + "changeMeetingDetail": "Change meeting details", + "underWay": "In progress", + "joinCall": "Join call", + "joinMeeting": "Join meeting", + "quickMeeting": "Quick meeting", + "orderMeeting": "Book a meeting", + "orderSuccess": "Scheduled successfully", + "callTimeout": "Unanswered after timeout", + "callTime": "Call duration", + "handleByOtherDevice": "Handled on another device", + "screenshotHideWindow": "Hide current window screenshot", + "historyList": "History", + "memberList": "Group member list", + "meetingInvitation": "Call invitation", + "invitation": "Invite", + "share": "Share contact card", + "selectUser": "Select user", + "setting": "Settings", + "offLine": "Offline", + "online": "Online", + "typing": "Typing...", + "kick": "Kick out", + "kickMember": "Kick out member", + "forbidLookMemberInfo": "Forbidden to view other group member's details", + "forbidAddMember": "Forbidden to add group members as friends", + "applyNeedInvite": "Group member invitation doesn't need verification", + "applyNeedVerification": "Verification message required", + "applyAll": "Allow everyone to join the group", + "staffNo": "工号", + "sendToName": "Message {{name}}", + "enterToSendTip": "Press Enter to send, Ctrl + Enter for a new line", + "dropToSend": "Release to send file", + "viewProfile": "View profile", + "groupSetting": "Group settings" + }, + "empty": { + "noMoments": "No moments available", + "noMoreMessage": "No more messages", + "showAllResults": "All results displayed!", + "noSearchResults": "No relevant results found!", + "fileContentEmpty": "File is empty!" + }, + "messageDescription": { + "imageMessage": "[Image]", + "voiceMessage": "[Voice]", + "fileMessage": "[File]{{file}}", + "locationMessage": "[Location]{{location}}", + "videoMessage": "[Video]", + "cardMessage": "[Card]", + "faceMessage": "[Emoji]", + "rtcMessage": "[Call]", + "quoteMessage": "[Quoted Message]", + "massMessage": "[Group Notification]", + "mergeMessage": "[Chat History]", + "callMessage": "[Call]", + "meetingMessage": "[Meeting Invitation]", + "customMessage": "[Custom Message]", + "notSupMessage": "[Unsupported Message Type]", + "drftPrefix": "[Draft]", + "atAllPrefix": "[Everyone]", + "atYouPrefix": "[Someone @you]", + "unreadCount": "[{{count}} messages]", + "catchMessage": "[Unsupported Message Type]", + "forwardMessage": "[Forward] {{additional}}", + "addtionalCardMessage": "[Card] {{additional}}", + "quoteMessageRevoke": "The cited content has been deleted", + "groupAnnouncementPrefix": "[Group Announcement]", + "revokeMessage": "{{revoker}} recalled a message", + "advanceRevokeMessage": "{{operator}} recalled a message sent by {{revoker}}", + "alreadyFriendMessage": "You are now friends and can start chatting!", + "createGroupMessage": "{{creator}} created a group chat", + "updateGroupInfoMessage": "{{operator}} updated the group info", + "updateGroupNameMessage": "{{operator}} changed the group name to {{name}}", + "updateGroupAnnouncementMessage": "{{operator}} updated the group announcement", + "transferGroupMessage": "{{owner}} transferred group ownership to {{newOwner}}", + "quitGroupMessage": "{{name}} quit the group chat", + "invitedToGroupMessage": "{{operator}} invited {{invitedUser}} to join the group chat", + "kickInGroupMessage": "{{operator}} was removed from the group by {{kickedUser}}", + "joinGroupMessage": "{{name}} joined the group chat", + "disbanedGroupMessage": "{{operator}} disbanded the group chat", + "allMuteMessage": "{{operator}} enabled group mute", + "cancelAllMuteMessage": "{{operator}} disabled group mute", + "singleMuteMessage": "{{name}} was muted by {{operator}} for {{muteTime}}", + "cancelSingleMuteMessage": "{{name}} had their mute canceled by {{operator}}", + "burnReadStatus": "Burn after reading is {{status}}", + "videoNotSupport": "[Video] Not supported yet" + }, + "time": { + "day": "Day", + "week": "Week", + "month": "Month", + "today": "Today", + "yesterday": "Yesterday", + "startTime": "Start Time" + }, + "date": { + "second": "{{num}} second(s)", + "minute": "{{num}} minute(s)", + "hour": "{{num}} hour(s)", + "day": "{{num}} day(s)", + "weeks": "{{num}} week(s)", + "month": "{{num}} month(s)", + "justNow": "Just now", + "thisWeek": "This week", + "thisMonth": "This month", + "earlier": "Earlier", + "custom": "Custom" + }, + "application": { + "agree": "Agree", + "refuse": "Refuse", + "agreed": "Agreed", + "refused": "Refused", + "information": "Verification Information", + "pending": "Pending Verification", + "applyToJoin": "Apply to Join", + "applyToAdd": "Apply to Add", + "applyToFriend": "Applied to Add You as a Friend" + }, + "errCode": { + "passwordError": "Password error", + "accountNotExist": "Account doesn't exist", + "phoneNumberRegistered": "Phone already register", + "accountRegistered": "Account already registered", + "operationTooFrequent": "Operation too frequent, please try again later", + "verificationCodeError": "Incorrect verification code", + "verificationCodeExpired": "Verification code expired", + "verificationCodeErrorLimitExceed": "Verification code error limit exceeded, please try again later", + "verificationCodeUsed": "Verification code already used", + "invitationCodeUsed": "Invitation code already used", + "invitationCodeNotExist": "Invitation code does not exist", + "operationRestriction": "Operation restricted" + }, + "states": { + "noMessage": "No messages yet", + "noMessageTip": "Find a colleague in Contacts to chat with", + "findColleague": "Find colleagues", + "loading": "Loading", + "loadingTip": "Messages are on the way, please wait", + "loadFailed": "Messages failed to load", + "loadFailedTip": "Check your network, then tap retry", + "offline": "Network unavailable, please check your connection", + "offlineTip": "Old messages are still available; new ones will arrive once back online" + } +} \ No newline at end of file diff --git a/pc-client/src/i18n/resources/zh.json b/pc-client/src/i18n/resources/zh.json new file mode 100644 index 0000000..adcfba4 --- /dev/null +++ b/pc-client/src/i18n/resources/zh.json @@ -0,0 +1,500 @@ +{ + "me": "我", + "you": "你", + "yes": "是", + "no": "否", + "confirm": "确认", + "retry": "重试", + "states": { + "noMessage": "还没有消息", + "noMessageTip": "去通讯录找同事聊聊吧", + "findColleague": "去找同事", + "loading": "正在加载", + "loadingTip": "消息马上就好,请稍等", + "loadFailed": "消息没加载出来", + "loadFailedTip": "检查一下网络,再点重试", + "offline": "当前网络不可用,请检查网络连接", + "offlineTip": "老消息还能看,新消息联网后自动收到" + }, + "cancel": "取消", + "canceled": "已取消", + "pieces": "条", + "open": "开启", + "close": "关闭", + "clear": "清空", + "answer": "接听", + "hangUp": "挂断", + "notStart": "未开始", + "waitingStart": "待开始", + "alreadyStarted": "已开始", + "finished": "已结束", + "clickToView": "点击查看", + "jumpToMessage": "跳转到消息", + "connect": { + "syncing": "同步中", + "syncFailed": "同步失败", + "connecting": "连接中", + "connectFailed": "连接失败" + }, + "toast": { + "accessSuccess": "操作成功!", + "accessFailed": "操作失败!", + "getConversationFailed": "获取会话列表失败!", + "getGroupInfoFailed": "获取群信息失败!", + "getGroupMemberFailed": "获取群成员信息失败!", + "getHistoryMessageFailed": "获取历史消息失败!", + "getSelfInfoFailed": "获取个人信息失败!", + "getFriendListFailed": "获取好友列表失败!", + "getBlackListFailed": "获取黑名单列表失败!", + "getGroupListFailed": "获取群列表失败!", + "getOnlineStatusFailed": "获取在线状态失败!", + "getMemberListFailed": "获取群成员失败!", + "getUserInfoFailed": "获取用户信息失败!", + "pinConversationFailed": "修改会话置顶状态失败!", + "setConversationRecvMessageOptFailed": "修改会话消息接收状态失败!", + "clearConversationMessagesFailed": "删除会话消息失败!", + "deleteConversationFailed": "删除会话失败!", + "updateGroupVerificationFailed": "修改群验证方式失败!", + "updateGroupInfoFailed": "修改群信息失败!", + "updateConversationPrivateStateFailed": "修改阅后即焚状态失败!", + "updateBlackStateFailed": "修改黑名单状态失败!", + "unfriendFailed": "解除好友失败!", + "getMessageListFailed": "获取消息列表失败!", + "sendApplicationFailed": "发送请求失败!", + "loading": "登录中...", + "syncing": "同步中...", + "syncFailed": "同步失败!", + "appUpdate": "应用程序更新", + "updateVersion": "发现新版本{{version}},是否立即更新?", + "updateContent": "更新内容:", + "isCancelUpdate": "确认要取消更新吗?", + "clearChatHistory": "清空聊天记录", + "confirmClearChatHistory": "确认清空聊天记录吗?", + "downloading": "下载中...", + "applyUpdateSuccess": "下载完成,重启应用生效,是否立即重启?", + "later": "稍后", + "applyDownloadSuccess": "下载完成,请跟随安装程序继续更新!", + "applyDownloadFailed": "下载失败!", + "loginExpiration": "当前登录已过期,请重新登录!", + "accountKicked": "您的账号已在其他设备登录,请重新登录!", + "updatePasswordSuccess": "修改密码成功,请重新登录!", + "inputOldPassword": "请输入原密码!", + "passwordRules": "6-20位,至少包含数字、字母", + "reconfirmPassword": "请再次确认您的密码", + "passwordsDifferent": "两次输入的密码不一致!", + "confirmlogOut": "确认退出登录当前账号吗?", + "updateAvatarFailed": "修改头像失败!", + "notCanSendMessage": "无法在已退出的群聊发消息!", + "groupMuted": "管理员或群主已开启全体禁言!", + "currentMuted": "您已被管理员或群主禁言!", + "messagesDeleteFailed": "部分消息删除失败!", + "confirmkickMember": "确认将{{name}}踢出群聊吗?", + "addSuccess": "添加成功!", + "copySuccess": "复制成功!", + "copyFailed": "复制失败!", + "confirmAllMuted": "确认开启全体禁言吗?", + "confirmDisbandGroup": "确认解散该群组吗?", + "confirmExitGroup": "确认退出该群组吗?", + "confirmMoveBlacklist": "确认将好友加入黑名单吗?", + "userBlacked": "该用户已被加入黑名单!", + "confirmUnfriend": "确认解除好友吗?", + "selectLeastOne": "请至少选择一项!", + "inputGroupName": "请输入群名称", + "inputContent": "请输入内容", + "sendSuccess": "发送成功!", + "beyondSelectionLimit": "超出选择限制!", + "sendJoinGroupRequestSuccess": "发送入群请求成功!", + "inputNickName": "请输入昵称", + "inputPhoneNumber": "请输入手机号", + "inputCorrectPhoneNumber": "请输入正确的手机号!", + "inputEmail": "请输入邮箱账号", + "inputCorrectEmail": "请输入正确的邮箱账号!", + "inputVerifyCode": "请输入您的验证码", + "inputPassword": "请输入您的密码", + "inputStaffNo": "请输入工号", + "sendFreiendRequestSuccess": "发送好友请求成功!", + "registerSuccess": "注册成功!", + "inputInvitationCode": "请输入您的邀请码", + "downloadFailed": "下载失败!", + "beingBlacklist": "对方已将你加入黑名单", + "usingFriendVerification": "对方开启了好友验证,你还不是他的好友", + "confirmDeleteMoment": "确认删除该条朋友圈吗?", + "uploadFailed": "上传失败!", + "somethingError": "似乎出现了一点问题~", + "getLogFailed": "获取日志文件失败!", + "publishFailed": "发布失败!", + "notCanAddFriend": "对方已设置不允许被添加为好友!", + "isJoinCalling": "群通话进行中,是否直接加入?", + "fileTypeError": "不支持的文件类型或文件夹!", + "noMicrophone": "没有检测到麦克风,无法录音", + "recordTooShort": "说话时间太短了" + }, + "placeholder": { + "conversation": "会话", + "leaveMessage": "留言", + "recover": "点击恢复", + "someInCall": "{{count}}人正在通话", + "compere": "主持人", + "watchUser": "全部看他", + "removeWatchUser": "取消全部看他", + "fold": "收起", + "participantCanUnmuteSelf": "允许成员自我解除静音", + "participantCanEnableVideo": "允许成员开启视频", + "onlyHostShareScreen": "仅主持人可以共享屏幕", + "onlyHostInviteUser": "仅主持人可邀请会议人员", + "joinDisableMicrophone": "成员入会静音", + "member": "成员", + "microphone": "麦克风", + "camera": "摄像头", + "sharedScreen": "共享屏幕", + "endSharing": "结束共享", + "connecting": "连接中...", + "uploadSuccess": "上传成功", + "reportLog": "上报日志", + "reportSpecificLog": "上报指定日志", + "viewingLocalLogs": "查看本地日志", + "totalNumPhoto": "共{{num}}张", + "somePersonLike": "等{{num}}人点赞", + "whoCanWatch": "谁可以看", + "remindWhoToWatch": "提醒谁看", + "publishMomentsToast": "这一刻的想法...", + "public": "公开", + "publicToast": "所有人可见", + "privacy": "私密", + "privacyToast": "仅自己可见", + "partlyVisible": "部分可见", + "partlyVisibleToast": "仅选中的人可见", + "hiddenSome": "不给谁看", + "hiddenSomeToast": "仅选中的人不可见", + "comment": "评论", + "hint": "提示", + "toLike": "点赞", + "byLike": "为你点了赞", + "mentioned": "提到了", + "atYou": "提到了你", + "replied": "回复了", + "publishImages": "发布图文", + "publishVideo": "发布视频", + "details": "详情", + "messageDestruct": "定期删除消息记录", + "messageDestructTime": "定期删除消息记录时间", + "messageDestructToast": "在此之后发送的消息会在选择的时间之后自动删除", + "moments": "工作圈", + "somePerson": "等{{num}}人", + "selectMember": "选择成员", + "setInfo": "设置信息", + "regain": "重新获取", + "optional": "(选填)", + "invitationCode": "邀请码", + "getBack": "返回", + "nextStep": "下一步", + "register": "新用户注册", + "registerToast": "还没有注册?", + "toRegister": "立即注册", + "login": "登录", + "pleaseEnterSendTo": "请输入发送至", + "verifyCode": "验证码", + "verifyValidity": "的 6 位验证码,有效期 10 分钟", + "sendVerifyCode": "发送验证码", + "qrCodeLogin": "扫码登录", + "qrCodeLoginTitle": "请使用OpenCorp移动端扫描二维码", + "welcome": "欢迎使用畅联", + "title": "畅联", + "subTitle": "公司内部通讯工具", + "myCreated": "我创建的", + "myJoined": "我加入的", + "newFriends": "新的好友", + "groupNotification": "群通知", + "friendVerification": "好友验证", + "groupInfo": "群组信息", + "personalInfo": "个人信息", + "inviteToGroup": "邀请入群", + "qrCodeToGroup": "扫码入群", + "selectIDToGroup": "搜索群组ID", + "remark": "备注", + "email": "邮箱", + "phoneNumber": "手机号", + "verifyPhoneNumber": "验证手机号", + "verifyEmail": "验证邮箱", + "birth": "生日", + "gender": "性别", + "man": "男", + "female": "女", + "unknown": "未知", + "nickName": "昵称", + "groupNickName": "群昵称", + "joinGroupTime": "入群时间", + "joinGroupMode": "入群方式", + "editInfo": "编辑资料", + "message": "聊天信息", + "relevantMessage": "{{count}}条相关聊天记录", + "overview": "综合", + "latestChat": "最近聊天", + "myFriend": "我的好友", + "myGroup": "我的群组", + "groupName": "群名称", + "groupAvatar": "群头像", + "groupMember": "群成员", + "selected": "已选择", + "moveBlacklist": "加入黑名单", + "willFilterThisUserMessage": "将无法接收该好友消息。", + "unfriend": "解除好友", + "setStarFriend": "设置为星标好友", + "shieldConversation": "屏蔽该会话", + "privateChat": "阅后即焚", + "privateChatTime": "阅后即焚时间", + "isRead": "已读", + "isReadList": "消息已读列表", + "allIsRead": "全部已读", + "isReadNum": "{{num}}人已读", + "unreadNum": "{{num}}人未读", + "unread": "未读", + "revoke": "撤回", + "copy": "复制", + "check": "多选", + "sendMessage": "发送消息", + "save": "保存", + "group": "群组", + "groupTppe": "群类型", + "workGroup": "工作群", + "myGroupNickname": "我的群聊昵称", + "notNotify": "消息免打扰", + "allMuted": "全体禁音", + "allMutedClose": "解除全体静音", + "groupVerification": "群聊验证", + "groupMemberPermissions": "群成员权限", + "transferGroup": "转让群组", + "exitGroup": "退出群组", + "exitGroupToast": "退出后你将不再接收该群组消息。", + "disbandGroup": "解散群组", + "disbandGroupToast": "解除后将移除所有群成员。", + "and": "{{someone}}和{{otherone}}", + "groupOwner": "群主", + "administrator": "管理员", + "setAdministrator": "设为管理员", + "mute": "禁言", + "cancelMute": "取消禁言", + "setMute": "设置禁言", + "onlyManageCanSend": "开启后仅群主和管理员可发言。", + "publish": "发布", + "edit": "编辑", + "call": "通话", + "file": "文件", + "document": "文档", + "emoji": "表情", + "image": "图片", + "video": "视频", + "card": "名片", + "personalCard": "个人名片", + "screenshot": "截图", + "sticky": "置顶", + "removeSticky": "取消置顶", + "draft": "草稿", + "pleaseEnter": "请输入", + "enterGroupName": "取个群名称方便后续搜索", + "clickToModify": "点击修改", + "search": "搜索", + "about": "关于我们", + "staffNo": "工号", + "password": "密码", + "forgetPassword": "忘记密码", + "changePassword": "修改密码", + "checkNewVersion": "检查新版本", + "viewMore": "查看更多", + "add": "添加", + "remove": "移除", + "delete": "删除", + "close": "关闭", + "finder": "查看", + "blackList": "通讯录黑名单", + "oldPassword": "原密码:", + "newPassword": "新密码:", + "confirmPassword": "确认密码:", + "chat": "消息", + "contact": "通讯录", + "contacts": "联系人", + "myInfo": "我的资料", + "accountSetting": "账号设置", + "logOut": "退出登录", + "personalSetting": "个人设置", + "chooseLanguage": "选择语言", + "closeButtonEvent": "点击关闭按钮时的事件", + "exitApplication": "退出应用", + "minimize": "最小化托盘", + "messageToast": "消息提示", + "messageAllowBeep": "新消息提示音", + "messageNotNotify": "勿扰模式", + "addFriends": "添加好友", + "verifyAdd": "验证添加", + "addGroup": "添加群组", + "createGroup": "创建群聊", + "createNow": "立即创建", + "createGroupToast": "创建群组,立即开启在线化办公", + "addFriendsSetting": "添加好友设置", + "refuseAddFriend": "禁止添加我为好友", + "markAsRead": "标为已读", + "send": "发送", + "sendTo": "发送给:", + "groupAnnouncement": "群公告", + "noGroupAnnouncement": "还没有群公告哦~", + "needManageEdit": "只有群主及管理员可以编辑", + "loosenToSend": "松开发送给", + "reEdit": "重新编辑", + "multipleNewMessages": "{{count}}新消息", + "reply": "回复", + "sendShortcutkey": "Enter发送/Shift+Enter换行", + "sendWithEnter": "按Enter发送", + "sendWithShiftEnter": "按Shift+Enter发送", + "mentionAll": "所有人", + "forward": "转发", + "mergeForward": "合并转发", + "messageHistory": "聊天记录", + "whosMessageHistory": "{{who}}的聊天记录", + "launch": "发起的", + "launchPerson": "发起人", + "inviteYou": "邀请你进行", + "videoCall": "视频通话", + "voiceCall": "语音通话", + "meeting": "视频会议", + "meetingSetting": "会议设置", + "someInMeeting": "{{count}}人正在开会", + "finishMeeting": "结束会议", + "leaveMeeting": "离开会议", + "meetingName": "会议主题", + "initiatedMeeting": "发起的会议", + "meetingTime": "会议时长", + "meetingID": "会议号", + "meetingDetail": "会议详情", + "changeMeetingDetail": "修改会议信息", + "underWay": "正在进行中", + "joinCall": "加入通话", + "joinMeeting": "进入会议", + "quickMeeting": "快速会议", + "orderMeeting": "预约会议", + "orderSuccess": "预约成功", + "callTimeout": "超时未接听", + "callTime": "通话时长", + "handleByOtherDevice": "已在其他设备处理", + "screenshotHideWindow": "隐藏当前窗口截图", + "historyList": "历史记录", + "memberList": "群成员列表", + "meetingInvitation": "通话邀请", + "invitation": "邀请", + "share": "分享名片", + "selectUser": "选择用户", + "setting": "设置", + "offLine": "离线", + "online": "在线", + "typing": "正在输入", + "kick": "踢出", + "kickMember": "踢出成员", + "forbidLookMemberInfo": "不允许查看其他群成员资料", + "forbidAddMember": "不允许添加群成员为好友", + "applyNeedInvite": "群成员邀请无需验证", + "applyNeedVerification": "需要发送验证消息", + "applyAll": "允许所有人加群", + "sendToName": "给 {{name}} 发消息", + "enterToSendTip": "按 Enter 发送,按 Ctrl + Enter 换行", + "dropToSend": "松开鼠标发送文件", + "viewProfile": "查看资料", + "groupSetting": "群聊设置" + }, + "empty": { + "noMoments": "暂无动态", + "noMoreMessage": "没有更多消息了", + "showAllResults": "已展示全部结果!", + "noSearchResults": "未搜索到相关结果", + "fileContentEmpty": "文件为空!" + }, + "messageDescription": { + "imageMessage": "[图片]", + "voiceMessage": "[语音]", + "fileMessage": "[文件]{{file}}", + "locationMessage": "[位置]{{location}}", + "videoMessage": "[视频]", + "cardMessage": "[名片]", + "faceMessage": "[表情]", + "rtcMessage": "[通话]", + "quoteMessage": "[引用消息]", + "massMessage": "[群发通知]", + "mergeMessage": "[聊天记录]", + "callMessage": "[通话]", + "meetingMessage": "[会议邀请]", + "customMessage": "[自定义消息]", + "notSupMessage": "[暂不支持的消息类型]", + "drftPrefix": "[草稿]", + "atAllPrefix": "[所有人]", + "atYouPrefix": "[有人@你]", + "unreadCount": "[{{count}}条]", + "catchMessage": "[暂未支持的消息类型]", + "videoNotSupport": "[视频]暂不支持查看", + "forwardMessage": "[转发] {{additional}}", + "addtionalCardMessage": "[名片] {{additional}}", + "quoteMessageRevoke": "引用内容已被删除", + "groupAnnouncementPrefix": "[群公告]", + "revokeMessage": "{{revoker}}撤回了一条消息", + "advanceRevokeMessage": "{{operator}}撤回了一条{{revoker}}发送的消息", + "alreadyFriendMessage": "你们已经成为好友,可以开始聊天了!", + "createGroupMessage": "{{creator}}创建了群聊", + "updateGroupInfoMessage": "{{operator}}修改了群信息", + "updateGroupNameMessage": "{{operator}}修改了群名称为{{name}}", + "updateGroupAnnouncementMessage": "{{operator}}修改了群公告", + "transferGroupMessage": "{{owner}}转让了群主给{{newOwner}}", + "quitGroupMessage": "{{name}}退出了群聊", + "invitedToGroupMessage": "{{operator}}邀请了{{invitedUser}}加入群聊", + "kickInGroupMessage": "{{kickedUser}}被{{operator}}踢出群聊", + "joinGroupMessage": "{{name}}加入了群聊", + "disbanedGroupMessage": "{{operator}}解散了群聊", + "allMuteMessage": "{{operator}}开启了全体禁言", + "cancelAllMuteMessage": "{{operator}}关闭了全体禁言", + "singleMuteMessage": "{{name}}被{{operator}}禁言{{muteTime}}", + "cancelSingleMuteMessage": "{{name}}被{{operator}}取消了禁言", + "burnReadStatus": "已{{status}}阅后即焚" + }, + "time": { + "day": "天", + "week": "周", + "month": "月", + "today": "今日", + "yesterday": "昨日", + "startTime": "开始时间" + }, + "date": { + "second": "{{num}}秒", + "minute": "{{num}}分钟", + "hour": "{{num}}小时", + "day": "{{num}}天", + "weeks": "{{num}}周", + "month": "{{num}}月", + "justNow": "刚刚", + "thisWeek": "本周", + "thisMonth": "本月", + "earlier": "更早", + "custom": "自定义" + }, + "application": { + "agree": "同意", + "refuse": "拒绝", + "agreed": "已同意", + "refused": "已拒绝", + "information": "验证信息", + "pending": "等待验证", + "applyToJoin": "申请加入", + "applyToAdd": "申请添加", + "applyToFriend": "申请添加您为好友" + }, + "errCode": { + "passwordError": "密码错误", + "accountNotExist": "账号不存在", + "phoneNumberRegistered": "手机号已注册", + "accountRegistered": "账号已注册", + "operationTooFrequent": "操作过于频繁,请稍后再试", + "verificationCodeError": "验证码错误", + "verificationCodeExpired": "验证码已过期", + "verificationCodeErrorLimitExceed": "验证码错误次数超过限制,请稍后再试", + "verificationCodeUsed": "验证码已被使用", + "invitationCodeUsed": "邀请码已被使用", + "invitationCodeNotExist": "邀请码不存在", + "operationRestriction": "操作限制" + } +} diff --git a/pc-client/src/index.scss b/pc-client/src/index.scss new file mode 100644 index 0000000..a5fffa1 --- /dev/null +++ b/pc-client/src/index.scss @@ -0,0 +1,7 @@ +@use "./styles/global.scss"; +@use "./styles/antd.scss"; +@use "./styles/svg.scss"; + +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/pc-client/src/layout/GlobalModals.tsx b/pc-client/src/layout/GlobalModals.tsx new file mode 100644 index 0000000..afd0311 --- /dev/null +++ b/pc-client/src/layout/GlobalModals.tsx @@ -0,0 +1,121 @@ +import { CbEvents, MessageType } from "@openim/wasm-client-sdk"; +import { + GroupItem, + MessageItem, + RtcInvite, + WSEvent, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import { useCallback, useEffect, useRef, useState } from "react"; + +import { getBusinessUserInfo } from "@/api/login"; +import { CustomType } from "@/constants"; +import { OverlayVisibleHandle } from "@/hooks/useOverlayVisible"; +import ChooseModal, { ChooseModalState } from "@/pages/common/ChooseModal"; +import GroupCardModal from "@/pages/common/GroupCardModal"; +import RtcCallModal from "@/pages/common/RtcCallModal"; +import { InviteData } from "@/pages/common/RtcCallModal/data"; +import UserCardModal, { CardInfo } from "@/pages/common/UserCardModal"; +import { useContactStore, useUserStore } from "@/store"; +import emitter, { OpenUserCardParams } from "@/utils/events"; + +import { IMSDK } from "./MainContentWrap"; + +type UserCardState = OpenUserCardParams & { + cardInfo?: CardInfo; +}; + +/** + * 全局弹窗挂载点:名片/群组卡片、选人弹窗、语音通话, + * 以及来电(CallingInvite 自定义消息)监听。 + */ +const GlobalModals = () => { + const userCardRef = useRef(null); + const groupCardRef = useRef(null); + const chooseModalRef = useRef(null); + const rtcRef = useRef(null); + const [chooseModalState, setChooseModalState] = useState({ + type: "CRATE_GROUP", + }); + const [userCardState, setUserCardState] = useState(); + const [groupCardData, setGroupCardData] = useState< + GroupItem & { inGroup?: boolean } + >(); + const [inviteData, setInviteData] = useState({} as InviteData); + + const openGroupCardWithData = useCallback((group: GroupItem) => { + const inGroup = useContactStore + .getState() + .groupList.some((g) => g.groupID === group.groupID); + setGroupCardData({ ...group, inGroup }); + groupCardRef.current?.openOverlay(); + }, []); + + useEffect(() => { + const userCardHandler = (params: OpenUserCardParams) => { + setUserCardState({ ...params }); + userCardRef.current?.openOverlay(); + }; + const chooseModalHandler = (params: ChooseModalState) => { + setChooseModalState({ ...params }); + chooseModalRef.current?.openOverlay(); + }; + const callRtcHandler = (inviteData: InviteData) => { + if (rtcRef.current?.isOverlayOpen) return; + setInviteData(inviteData); + rtcRef.current?.openOverlay(); + }; + const newMessageHandler = ({ data }: WSEvent) => { + if (rtcRef.current?.isOverlayOpen) return; + let rtcInvite = undefined as undefined | RtcInvite; + data.map((message) => { + if (message.contentType === MessageType.CustomMessage) { + const customData = JSON.parse(message.customElem!.data); + if (customData.customType === CustomType.CallingInvite) { + rtcInvite = customData.data; + } + } + }); + if (rtcInvite) { + getBusinessUserInfo([rtcInvite.inviterUserID]).then(({ data: { users } }) => { + if (users.length === 0) return; + setInviteData({ + invitation: rtcInvite, + participant: { + userInfo: { + nickname: users[0].nickname, + faceURL: users[0].faceURL, + userID: users[0].userID, + ex: "", + }, + }, + }); + rtcRef.current?.openOverlay(); + }); + } + }; + + emitter.on("OPEN_USER_CARD", userCardHandler); + emitter.on("OPEN_GROUP_CARD", openGroupCardWithData); + emitter.on("OPEN_CHOOSE_MODAL", chooseModalHandler); + emitter.on("OPEN_RTC_MODAL", callRtcHandler); + IMSDK.on(CbEvents.OnRecvNewMessages, newMessageHandler); + return () => { + emitter.off("OPEN_USER_CARD", userCardHandler); + emitter.off("OPEN_GROUP_CARD", openGroupCardWithData); + emitter.off("OPEN_CHOOSE_MODAL", chooseModalHandler); + emitter.off("OPEN_RTC_MODAL", callRtcHandler); + IMSDK.off(CbEvents.OnRecvNewMessages, newMessageHandler); + }; + }, []); + + return ( + <> + + + + + + ); +}; + +export default GlobalModals; diff --git a/pc-client/src/layout/LeftNavBar/About.tsx b/pc-client/src/layout/LeftNavBar/About.tsx new file mode 100644 index 0000000..ccb01f2 --- /dev/null +++ b/pc-client/src/layout/LeftNavBar/About.tsx @@ -0,0 +1,178 @@ +import { CloseOutlined, RightOutlined } from "@ant-design/icons"; +import { CbEvents } from "@openim/wasm-client-sdk"; +import { WSEvent } from "@openim/wasm-client-sdk/lib/types/entity"; +import { useRequest } from "ahooks"; +import { App, Button, Divider, Form, Input, Modal, Space, Spin } from "antd"; +import { t } from "i18next"; +import { forwardRef, ForwardRefRenderFunction, memo, useEffect, useState } from "react"; +import { useCopyToClipboard } from "react-use"; + +import logo from "@/assets/images/profile/logo.png"; +import { APP_NAME, APP_VERSION, SDK_VERSION } from "@/config"; +import { feedbackToast } from "@/utils/common"; + +import { OverlayVisibleHandle, useOverlayVisible } from "../../hooks/useOverlayVisible"; +import { IMSDK } from "../MainContentWrap"; + +const About: ForwardRefRenderFunction = (_, ref) => { + const [form] = Form.useForm(); + + const { isOverlayOpen, closeOverlay } = useOverlayVisible(ref); + + return ( + form.resetFields()} + styles={{ + mask: { + opacity: 0, + transition: "none", + }, + }} + width={360} + className="no-padding-modal" + maskTransitionName="" + > + + + ); +}; + +export default memo(forwardRef(About)); + +export const AboutContent = ({ closeOverlay }: { closeOverlay?: () => void }) => { + const { modal } = App.useApp(); + const [progress, setProgress] = useState(0); + + const [_, copyToClipboard] = useCopyToClipboard(); + + const { loading, runAsync } = useRequest(IMSDK.uploadLogs, { + manual: true, + }); + + const tryLogReport = async (line: number) => { + try { + await runAsync({ line, ex: "" }); + feedbackToast({ + msg: t("placeholder.uploadSuccess"), + }); + } catch (error) { + feedbackToast({ + msg: t("placeholder.uploadFailed"), + error: error, + }); + } + setProgress(0); + }; + + useEffect(() => { + const uploadHandler = ({ + data: { current, size }, + }: WSEvent<{ current: number; size: number }>) => { + const progress = (current / size) * 100; + console.log("OnUploadLogsProgress", Number(progress.toFixed(0)), current, size); + setProgress(Number(progress.toFixed(0))); + }; + IMSDK.on(CbEvents.OnUploadLogsProgress, uploadHandler); + return () => { + IMSDK.off(CbEvents.OnUploadLogsProgress, uploadHandler); + }; + }, []); + + const Modal = ({ close }: { close: () => void }) => { + const [line, setLine] = useState(100); + return ( +
+ { + setLine(Number(e.target.value)); + }} + type="number" + /> + + + + +
+ ); + }; + + const openSelectLine = () => { + const current = modal.info({ + title: null, + icon: null, + footer: null, + width: 300, + className: "no-padding-modal", + centered: true, + maskTransitionName: "", + content: current.destroy()} />, + }); + }; + + const handleCopy = () => { + copyToClipboard(`${`${APP_NAME} ${APP_VERSION}`}/${SDK_VERSION}`); + feedbackToast({ msg: t("toast.copySuccess") }); + }; + + return ( + +
+
+ {t("placeholder.about")} + +
+
+ +
+
{`${APP_NAME} ${APP_VERSION}`}
+
{SDK_VERSION}
+
+
+ + + + {window.electronAPI && ( + <> +
tryLogReport(10000)} + > +
{t("placeholder.reportLog")}
+ +
+
+
{t("placeholder.reportSpecificLog")}
+ +
+ + )} +
+
+ ); +}; diff --git a/pc-client/src/layout/LeftNavBar/BlackList.tsx b/pc-client/src/layout/LeftNavBar/BlackList.tsx new file mode 100644 index 0000000..f2b8427 --- /dev/null +++ b/pc-client/src/layout/LeftNavBar/BlackList.tsx @@ -0,0 +1,103 @@ +import { CloseOutlined } from "@ant-design/icons"; +import { BlackUserItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import { Button, Empty, Modal } from "antd"; +import { t } from "i18next"; +import { forwardRef, ForwardRefRenderFunction, memo, useState } from "react"; + +import OIMAvatar from "@/components/OIMAvatar"; +import { useContactStore } from "@/store/contact"; +import { feedbackToast } from "@/utils/common"; + +import { OverlayVisibleHandle, useOverlayVisible } from "../../hooks/useOverlayVisible"; +import { IMSDK } from "../MainContentWrap"; + +const BlackList: ForwardRefRenderFunction = (_, ref) => { + const { isOverlayOpen, closeOverlay } = useOverlayVisible(ref); + + return ( + + + + ); +}; + +export default memo(forwardRef(BlackList)); + +const BlackItem = ({ + black, + removeBlack, +}: { + black: BlackUserItem; + removeBlack: (userID: string) => Promise; +}) => { + const [loading, setLoading] = useState(false); + + const tryRemove = async () => { + setLoading(true); + await removeBlack(black.userID); + setLoading(false); + }; + + return ( +
+
+ +
{black.nickname}
+
+ +
+ ); +}; + +export const BlackListContent = ({ closeOverlay }: { closeOverlay?: () => void }) => { + const blackList = useContactStore((state) => state.blackList); + + const removeBlack = async (userID: string) => { + try { + await IMSDK.removeBlack(userID); + } catch (error) { + feedbackToast({ error }); + } + }; + + return ( +
+
+ {t("placeholder.blackList")} + +
+
+ {blackList.length > 0 ? ( + blackList.map((black) => ( + + )) + ) : ( + + )} +
+
+ ); +}; diff --git a/pc-client/src/layout/LeftNavBar/PersonalSettings.tsx b/pc-client/src/layout/LeftNavBar/PersonalSettings.tsx new file mode 100644 index 0000000..40a7fb7 --- /dev/null +++ b/pc-client/src/layout/LeftNavBar/PersonalSettings.tsx @@ -0,0 +1,105 @@ +import { CloseOutlined } from "@ant-design/icons"; +import { Checkbox, Modal } from "antd"; +import { t } from "i18next"; +import { forwardRef, ForwardRefRenderFunction, memo } from "react"; + +import { useUserStore } from "@/store"; + +import { OverlayVisibleHandle, useOverlayVisible } from "../../hooks/useOverlayVisible"; + +const PersonalSettings: ForwardRefRenderFunction = ( + _, + ref, +) => { + const { isOverlayOpen, closeOverlay } = useOverlayVisible(ref); + + return ( + + + + ); +}; + +export default memo(forwardRef(PersonalSettings)); + +export const PersonalSettingsContent = ({ + closeOverlay, +}: { + closeOverlay?: () => void; +}) => { + const closeAction = useUserStore((state) => state.appSettings.closeAction); + const updateAppSettings = useUserStore((state) => state.updateAppSettings); + + const closeActionChange = (checked: boolean, action: "miniSize" | "quit") => { + if (checked) { + window.electronAPI?.ipcInvoke("setKeyStore", { + key: "closeAction", + data: action, + }); + updateAppSettings({ + closeAction: action, + }); + } + }; + + return ( +
+
+ {t("placeholder.accountSetting")} + +
+
+
+
+
+ {t("placeholder.personalSetting")} +
+ {Boolean(window.electronAPI) && ( +
+
+ {t("placeholder.closeButtonEvent")} +
+
+ closeActionChange(e.target.checked, "quit")} + > + {t("placeholder.exitApplication")} + + closeActionChange(e.target.checked, "miniSize")} + > + {t("placeholder.minimize")} + +
+
+ )} +
+
+
+
+ ); +}; diff --git a/pc-client/src/layout/LeftNavBar/index.tsx b/pc-client/src/layout/LeftNavBar/index.tsx new file mode 100644 index 0000000..3ce30ea --- /dev/null +++ b/pc-client/src/layout/LeftNavBar/index.tsx @@ -0,0 +1,307 @@ +import { + ContactsFilled, + ContactsOutlined, + MessageFilled, + MessageOutlined, + RightOutlined, +} from "@ant-design/icons"; +import { Badge, Divider, Popover, Upload } from "antd"; +import clsx from "clsx"; +import i18n, { t } from "i18next"; +import React, { memo, useRef, useState } from "react"; +import ImageResizer from "react-image-file-resizer"; +import { UNSAFE_NavigationContext, useResolvedPath } from "react-router-dom"; + +import { modal } from "@/AntdGlobalComp"; +import { updateBusinessUserInfo } from "@/api/login"; +import change_avatar from "@/assets/images/profile/change_avatar.png"; +import OIMAvatar from "@/components/OIMAvatar"; +import { useContactStore, useConversationStore, useUserStore } from "@/store"; +import { feedbackToast } from "@/utils/common"; +import { emit } from "@/utils/events"; +import { uploadFile } from "@/utils/imCommon"; + +import { OverlayVisibleHandle } from "../../hooks/useOverlayVisible"; +import About from "./About"; +import styles from "./left-nav-bar.module.scss"; +import PersonalSettings from "./PersonalSettings"; + +const AppIcon = () => ( +
+ + + +
+); + +const NavList = [ + { + icon: MessageOutlined, + icon_active: MessageFilled, + title: t("placeholder.chat"), + path: "/chat", + }, + { + icon: ContactsOutlined, + icon_active: ContactsFilled, + title: t("placeholder.contact"), + path: "/contact", + }, +]; + +i18n.on("languageChanged", () => { + NavList[0].title = t("placeholder.chat"); + NavList[1].title = t("placeholder.contact"); +}); + +const resizeFile = (file: File): Promise => + new Promise((resolve) => { + ImageResizer.imageFileResizer( + file, + 400, + 400, + "webp", + 90, + 0, + (uri) => { + resolve(uri as File); + }, + "file", + ); + }); + +type NavItemType = (typeof NavList)[0]; + +const NavItem = ({ nav: { icon: Icon, icon_active: ActiveIcon, title, path } }: { nav: NavItemType }) => { + const resolvedPath = useResolvedPath(path); + const { navigator } = React.useContext(UNSAFE_NavigationContext); + const toPathname = navigator.encodeLocation + ? navigator.encodeLocation(path).pathname + : resolvedPath.pathname; + const locationPathname = location.pathname; + const isActive = + locationPathname === toPathname || + (locationPathname.startsWith(toPathname) && + locationPathname.charAt(toPathname.length) === "/") || + location.hash.startsWith(`#${toPathname}`); + + const unReadCount = useConversationStore((state) => state.unReadCount); + const unHandleFriendApplicationCount = useContactStore( + (state) => state.unHandleFriendApplicationCount, + ); + const unHandleGroupApplicationCount = useContactStore( + (state) => state.unHandleGroupApplicationCount, + ); + + const tryNavigate = () => { + if (isActive) { + return; + } + navigator.push(path); + }; + + const getBadge = () => { + if (path === "/chat") { + return unReadCount; + } + if (path === "/contact") { + return unHandleFriendApplicationCount + unHandleGroupApplicationCount; + } + return 0; + }; + + const NavIcon = isActive ? ActiveIcon : Icon; + + return ( +
+ + + +
+ ); +}; + +const profileMenuList = [ + { + title: t("placeholder.myInfo"), + gap: true, + idx: 0, + }, + { + title: t("placeholder.accountSetting"), + gap: true, + idx: 1, + }, + { + title: t("placeholder.about"), + gap: false, + idx: 2, + }, + { + title: t("placeholder.logOut"), + gap: false, + idx: 3, + }, +]; + +i18n.on("languageChanged", () => { + profileMenuList[0].title = t("placeholder.myInfo"); + profileMenuList[1].title = t("placeholder.accountSetting"); + profileMenuList[2].title = t("placeholder.about"); + profileMenuList[3].title = t("placeholder.logOut"); +}); + +const LeftNavBar = memo(() => { + const aboutRef = useRef(null); + const personalSettingsRef = useRef(null); + const [showProfile, setShowProfile] = useState(false); + const selfInfo = useUserStore((state) => state.selfInfo); + const userLogout = useUserStore((state) => state.userLogout); + const updateSelfInfo = useUserStore((state) => state.updateSelfInfo); + + const profileMenuClick = (idx: number) => { + switch (idx) { + case 0: + emit("OPEN_USER_CARD", { + isSelf: true, + userID: useUserStore.getState().selfInfo.userID, + }); + break; + case 1: + personalSettingsRef.current?.openOverlay(); + break; + case 2: + aboutRef.current?.openOverlay(); + break; + case 3: + tryLogout(); + break; + default: + break; + } + setShowProfile(false); + }; + + const tryLogout = () => { + modal.confirm({ + title: t("placeholder.logOut"), + content: t("toast.confirmlogOut"), + onOk: async () => { + try { + await userLogout(); + } catch (error) { + feedbackToast({ error }); + } + }, + }); + }; + + const customUpload = async ({ file }: { file: File }) => { + const resizedFile = await resizeFile(file); + const filePath = await window.electronAPI?.saveFileToDisk({ + sync: true, + file, + }); + + try { + const { + data: { url }, + } = await uploadFile(resizedFile, filePath); + const newInfo = { + faceURL: url, + }; + await updateBusinessUserInfo(newInfo); + updateSelfInfo(newInfo); + } catch (error) { + feedbackToast({ error: t("toast.updateAvatarFailed") }); + } + }; + + const ProfileContent = ( +
+
+ +
+ +
+ +
+
+
+
+
{selfInfo.nickname}
+
+
+ {profileMenuList.map((menu) => ( +
+
profileMenuClick(menu.idx)} + > +
{menu.title}
+ +
+ {menu.gap && ( +
+ +
+ )} +
+ ))} +
+ ); + + return ( +
+ + +
+ {NavList.map((nav) => ( + + ))} +
+ + setShowProfile(vis)} + > + + + + +
+ ); +}); + +export default LeftNavBar; diff --git a/pc-client/src/layout/LeftNavBar/left-nav-bar.module.scss b/pc-client/src/layout/LeftNavBar/left-nav-bar.module.scss new file mode 100644 index 0000000..dd6befe --- /dev/null +++ b/pc-client/src/layout/LeftNavBar/left-nav-bar.module.scss @@ -0,0 +1,13 @@ +.avatar-wrapper { + @apply mr-4 relative; + + &:hover { + .mask { + @apply opacity-100 cursor-pointer; + } + } + + .mask { + @apply flex justify-center items-center bg-[rgba(0,0,0,.6)] absolute z-10 top-0 left-0 w-full h-full rounded-md opacity-0 transition-opacity; + } +} diff --git a/pc-client/src/layout/MainContentLayout.tsx b/pc-client/src/layout/MainContentLayout.tsx new file mode 100644 index 0000000..28ec79d --- /dev/null +++ b/pc-client/src/layout/MainContentLayout.tsx @@ -0,0 +1,49 @@ +import { useMount } from "ahooks"; +import { Layout, Spin } from "antd"; +import { t } from "i18next"; +import { Outlet, useMatches, useNavigate } from "react-router-dom"; + +import WindowControlBar from "@/components/WindowControlBar"; +import { useUserStore } from "@/store"; + +import GlobalModals from "./GlobalModals"; +import LeftNavBar from "./LeftNavBar"; +import { useGlobalEvent } from "./useGlobalEvents"; + +export const MainContentLayout = () => { + useGlobalEvent(); + const matches = useMatches(); + const navigate = useNavigate(); + + const progress = useUserStore((state) => state.progress); + const syncState = useUserStore((state) => state.syncState); + const reinstall = useUserStore((state) => state.reinstall); + const isLogining = useUserStore((state) => state.isLogining); + + useMount(() => { + const isRoot = !matches.find((item) => item.pathname !== "/"); + const inConversation = matches.some((item) => item.params.conversationID); + if (isRoot || inConversation) { + navigate("chat", { + replace: true, + }); + } + }); + + const loadingTip = isLogining ? t("toast.loading") : `${progress}%`; + const showLockLoading = isLogining || (reinstall && syncState === "loading"); + + return ( + + + + + {/* 悬浮窗口控制条:无边框窗口的拖动区 + 最小化/关闭 */} +
+ +
+ +
+
+ ); +}; diff --git a/pc-client/src/layout/MainContentWrap.tsx b/pc-client/src/layout/MainContentWrap.tsx new file mode 100644 index 0000000..e892ba0 --- /dev/null +++ b/pc-client/src/layout/MainContentWrap.tsx @@ -0,0 +1,78 @@ +import { getWithRenderProcess } from "@openim/electron-client-sdk/lib/render"; +import { AllowType } from "@openim/wasm-client-sdk"; +import { useEffect } from "react"; +import { Outlet, useLocation, useNavigate } from "react-router-dom"; + +import { useConversationStore, useUserStore } from "@/store"; +import { emit } from "@/utils/events"; +import { getIMToken, getIMUserID } from "@/utils/storage"; + +// const isElectronProd = import.meta.env.MODE !== "development" && window.electronAPI; + +const { instance } = getWithRenderProcess({ + wasmConfig: { + coreWasmPath: "./openIM.wasm", + sqlWasmPath: `/sql-wasm.wasm`, + }, +}); +const openIMSDK = instance; + +export const IMSDK = openIMSDK; + +export const MainContentWrap = () => { + const updateAppSettings = useUserStore((state) => state.updateAppSettings); + + const navigate = useNavigate(); + const location = useLocation(); + + useEffect(() => { + const loginCheck = async () => { + const IMToken = await getIMToken(); + const IMUserID = await getIMUserID(); + if (!IMToken || !IMUserID) { + navigate("/login"); + return; + } + }; + + loginCheck(); + }, [location.pathname]); + + useEffect(() => { + window.userClick = (userID?: string, groupID?: string) => { + if (!userID || userID === "AtAllTag") return; + + const currentGroupInfo = useConversationStore.getState().currentGroupInfo; + + if (groupID && currentGroupInfo?.lookMemberInfo === AllowType.NotAllowed) { + return; + } + + emit("OPEN_USER_CARD", { + userID, + groupID, + isSelf: userID === useUserStore.getState().selfInfo.userID, + notAdd: + Boolean(groupID) && + currentGroupInfo?.applyMemberFriend === AllowType.NotAllowed, + }); + }; + }, []); + + useEffect(() => { + const initSettingStore = async () => { + if (!window.electronAPI) return; + updateAppSettings({ + closeAction: + (await window.electronAPI?.ipcInvoke("getKeyStore", { + key: "closeAction", + })) || "miniSize", + }); + window.electronAPI?.ipcInvoke("main-win-ready"); + }; + + initSettingStore(); + }, []); + + return ; +}; diff --git a/pc-client/src/layout/useGlobalEvents.tsx b/pc-client/src/layout/useGlobalEvents.tsx new file mode 100644 index 0000000..b236ec3 --- /dev/null +++ b/pc-client/src/layout/useGlobalEvents.tsx @@ -0,0 +1,485 @@ +import { CbEvents, LogLevel } from "@openim/wasm-client-sdk"; +import { MessageType, SessionType } from "@openim/wasm-client-sdk"; +import { + BlackUserItem, + ConversationItem, + FriendApplicationItem, + FriendUserItem, + GroupApplicationItem, + GroupItem, + GroupMemberItem, + MessageItem, + RevokedInfo, + SelfUserInfo, + WSEvent, + WsResponse, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import { t } from "i18next"; +import { useEffect, useRef } from "react"; +import { useNavigate } from "react-router-dom"; + +import { CustomType } from "@/constants"; +import { + pushNewMessage, + updateOneMessage, +} from "@/pages/chat/queryChat/useHistoryMessageList"; +import { useConversationStore, useUserStore } from "@/store"; +import { useContactStore } from "@/store/contact"; +import { feedbackToast } from "@/utils/common"; +import { initStore } from "@/utils/imCommon"; +import { clearIMProfile, getIMToken, getIMUserID } from "@/utils/storage"; + +import { IMSDK } from "./MainContentWrap"; + +export function useGlobalEvent() { + const navigate = useNavigate(); + const resume = useRef(false); + + // user + const updateSyncState = useUserStore((state) => state.updateSyncState); + const updateProgressState = useUserStore((state) => state.updateProgressState); + const updateReinstallState = useUserStore((state) => state.updateReinstallState); + const updateIsLogining = useUserStore((state) => state.updateIsLogining); + const updateConnectState = useUserStore((state) => state.updateConnectState); + const updateSelfInfo = useUserStore((state) => state.updateSelfInfo); + const userLogout = useUserStore((state) => state.userLogout); + // conversation + const updateConversationList = useConversationStore( + (state) => state.updateConversationList, + ); + const updateUnReadCount = useConversationStore((state) => state.updateUnReadCount); + const updateCurrentGroupInfo = useConversationStore( + (state) => state.updateCurrentGroupInfo, + ); + const getCurrentGroupInfoByReq = useConversationStore( + (state) => state.getCurrentGroupInfoByReq, + ); + const setCurrentMemberInGroup = useConversationStore( + (state) => state.setCurrentMemberInGroup, + ); + const getCurrentMemberInGroupByReq = useConversationStore( + (state) => state.getCurrentMemberInGroupByReq, + ); + const tryUpdateCurrentMemberInGroup = useConversationStore( + (state) => state.tryUpdateCurrentMemberInGroup, + ); + const getConversationListByReq = useConversationStore( + (state) => state.getConversationListByReq, + ); + const getUnReadCountByReq = useConversationStore( + (state) => state.getUnReadCountByReq, + ); + // contact + const getFriendListByReq = useContactStore((state) => state.getFriendListByReq); + const getGroupListByReq = useContactStore((state) => state.getGroupListByReq); + const updateFriend = useContactStore((state) => state.updateFriend); + const pushNewFriend = useContactStore((state) => state.pushNewFriend); + const updateBlack = useContactStore((state) => state.updateBlack); + const pushNewBlack = useContactStore((state) => state.pushNewBlack); + const updateGroup = useContactStore((state) => state.updateGroup); + const pushNewGroup = useContactStore((state) => state.pushNewGroup); + const updateRecvFriendApplication = useContactStore( + (state) => state.updateRecvFriendApplication, + ); + const updateSendFriendApplication = useContactStore( + (state) => state.updateSendFriendApplication, + ); + const updateRecvGroupApplication = useContactStore( + (state) => state.updateRecvGroupApplication, + ); + const updateSendGroupApplication = useContactStore( + (state) => state.updateSendGroupApplication, + ); + + useEffect(() => { + loginCheck(); + setIMListener(); + setIpcListener(); + + window.addEventListener("online", () => { + IMSDK.networkStatusChanged(); + }); + window.addEventListener("offline", () => { + IMSDK.networkStatusChanged(); + }); + return () => { + disposeIMListener(); + }; + }, []); + + const loginCheck = async () => { + const IMToken = (await getIMToken()) as string; + const IMUserID = (await getIMUserID()) as string; + if (!IMToken || !IMUserID) { + clearIMProfile(); + navigate("/login"); + return; + } + tryLogin(); + }; + + const tryLogin = async () => { + updateIsLogining(true); + const IMToken = (await getIMToken()) as string; + const IMUserID = (await getIMUserID()) as string; + try { + const apiAddr = import.meta.env.VITE_API_URL; + const wsAddr = import.meta.env.VITE_WS_URL; + if (window.electronAPI) { + await IMSDK.initSDK({ + platformID: window.electronAPI?.getPlatform() ?? 5, + apiAddr, + wsAddr, + dataDir: window.electronAPI.getDataPath("sdkResources") || "./", + logFilePath: window.electronAPI.getDataPath("logsPath") || "./", + logLevel: LogLevel.Debug, + isLogStandardOutput: false, + systemType: "electron", + }); + await IMSDK.login({ + userID: IMUserID, + token: IMToken, + }); + } else { + await IMSDK.login({ + userID: IMUserID, + token: IMToken, + platformID: 5, + apiAddr, + wsAddr, + logLevel: LogLevel.Debug, + }); + } + initStore(); + } catch (error) { + console.error(error); + if ((error as WsResponse).errCode !== 10102) { + navigate("/login"); + } + } + updateIsLogining(false); + }; + + const setIMListener = () => { + // account + IMSDK.on(CbEvents.OnSelfInfoUpdated, selfUpdateHandler); + IMSDK.on(CbEvents.OnConnecting, connectingHandler); + IMSDK.on(CbEvents.OnConnectFailed, connectFailedHandler); + IMSDK.on(CbEvents.OnConnectSuccess, connectSuccessHandler); + IMSDK.on(CbEvents.OnKickedOffline, kickHandler); + IMSDK.on(CbEvents.OnUserTokenExpired, expiredHandler); + IMSDK.on(CbEvents.OnUserTokenInvalid, expiredHandler); + // sync + IMSDK.on(CbEvents.OnSyncServerStart, syncStartHandler); + IMSDK.on(CbEvents.OnSyncServerProgress, syncProgressHandler); + IMSDK.on(CbEvents.OnSyncServerFinish, syncFinishHandler); + IMSDK.on(CbEvents.OnSyncServerFailed, syncFailedHandler); + // message + IMSDK.on(CbEvents.OnRecvNewMessages, newMessageHandler); + IMSDK.on(CbEvents.OnNewRecvMessageRevoked, revokedMessageHandler); + // conversation + IMSDK.on(CbEvents.OnConversationChanged, conversationChnageHandler); + IMSDK.on(CbEvents.OnNewConversation, newConversationHandler); + IMSDK.on(CbEvents.OnTotalUnreadMessageCountChanged, totalUnreadChangeHandler); + // friend + IMSDK.on(CbEvents.OnFriendInfoChanged, friednInfoChangeHandler); + IMSDK.on(CbEvents.OnFriendAdded, friednAddedHandler); + IMSDK.on(CbEvents.OnFriendDeleted, friednDeletedHandler); + // blacklist + IMSDK.on(CbEvents.OnBlackAdded, blackAddedHandler); + IMSDK.on(CbEvents.OnBlackDeleted, blackDeletedHandler); + // group + IMSDK.on(CbEvents.OnJoinedGroupAdded, joinedGroupAddedHandler); + IMSDK.on(CbEvents.OnJoinedGroupDeleted, joinedGroupDeletedHandler); + IMSDK.on(CbEvents.OnGroupDismissed, joinedGroupDismissHandler); + IMSDK.on(CbEvents.OnGroupInfoChanged, groupInfoChangedHandler); + IMSDK.on(CbEvents.OnGroupMemberAdded, groupMemberAddedHandler); + IMSDK.on(CbEvents.OnGroupMemberDeleted, groupMemberDeletedHandler); + IMSDK.on(CbEvents.OnGroupMemberInfoChanged, groupMemberInfoChangedHandler); + // application + IMSDK.on(CbEvents.OnFriendApplicationAdded, friendApplicationProcessedHandler); + IMSDK.on(CbEvents.OnFriendApplicationAccepted, friendApplicationProcessedHandler); + IMSDK.on(CbEvents.OnFriendApplicationRejected, friendApplicationProcessedHandler); + IMSDK.on(CbEvents.OnGroupApplicationAdded, groupApplicationProcessedHandler); + IMSDK.on(CbEvents.OnGroupApplicationAccepted, groupApplicationProcessedHandler); + IMSDK.on(CbEvents.OnGroupApplicationRejected, groupApplicationProcessedHandler); + }; + + const selfUpdateHandler = ({ data }: WSEvent) => { + updateSelfInfo(data); + }; + const connectingHandler = () => { + updateConnectState("loading"); + console.log("connecting..."); + }; + const connectFailedHandler = ({ errCode, errMsg }: WSEvent) => { + updateConnectState("failed"); + console.error("connectFailedHandler", errCode, errMsg); + + if (errCode === 705) { + tryOut(t("toast.loginExpiration")); + } + }; + const connectSuccessHandler = () => { + updateConnectState("success"); + console.log("connect success..."); + }; + const kickHandler = () => tryOut(t("toast.accountKicked")); + const expiredHandler = () => tryOut(t("toast.loginExpiration")); + + const tryOut = (msg: string) => + feedbackToast({ + msg, + error: msg, + onClose: () => { + userLogout(true); + }, + }); + + // sync + const syncStartHandler = ({ data }: WSEvent) => { + updateSyncState("loading"); + updateReinstallState(data); + }; + const syncProgressHandler = ({ data }: WSEvent) => { + updateProgressState(data); + }; + const syncFinishHandler = () => { + updateSyncState("success"); + getFriendListByReq(); + getGroupListByReq(); + getConversationListByReq(false); + getUnReadCountByReq(); + }; + const syncFailedHandler = () => { + updateSyncState("failed"); + feedbackToast({ msg: t("toast.syncFailed"), error: t("toast.syncFailed") }); + }; + + // message + const newMessageHandler = ({ data }: WSEvent) => { + if (useUserStore.getState().syncState === "loading" || resume.current) { + return; + } + data.map((message) => handleNewMessage(message)); + }; + + const revokedMessageHandler = ({ data }: WSEvent) => { + updateOneMessage({ + clientMsgID: data.clientMsgID, + contentType: MessageType.RevokeMessage, + notificationElem: { + detail: JSON.stringify(data), + }, + } as MessageItem); + }; + + const notPushType = [MessageType.TypingMessage, MessageType.RevokeMessage]; + + const handleNewMessage = (newServerMsg: MessageItem) => { + if (newServerMsg.contentType === MessageType.CustomMessage) { + const customData = JSON.parse(newServerMsg.customElem!.data); + if ( + CustomType.CallingInvite <= customData.customType && + customData.customType <= CustomType.CallingHungup + ) { + return; + } + } + + if (!inCurrentConversation(newServerMsg)) return; + + if (!notPushType.includes(newServerMsg.contentType)) { + pushNewMessage(newServerMsg); + } + }; + + const inCurrentConversation = (newServerMsg: MessageItem) => { + switch (newServerMsg.sessionType) { + case SessionType.Single: + return ( + newServerMsg.sendID === + useConversationStore.getState().currentConversation?.userID || + (newServerMsg.sendID === useUserStore.getState().selfInfo.userID && + newServerMsg.recvID === + useConversationStore.getState().currentConversation?.userID) + ); + case SessionType.Group: + case SessionType.WorkingGroup: + return ( + newServerMsg.groupID === + useConversationStore.getState().currentConversation?.groupID + ); + case SessionType.Notification: + return ( + newServerMsg.sendID === + useConversationStore.getState().currentConversation?.userID + ); + default: + return false; + } + }; + + // conversation + const conversationChnageHandler = ({ data }: WSEvent) => { + updateConversationList(data, "filter"); + }; + const newConversationHandler = ({ data }: WSEvent) => { + updateConversationList(data, "push"); + }; + const totalUnreadChangeHandler = ({ data }: WSEvent) => { + if (data === useConversationStore.getState().unReadCount) return; + updateUnReadCount(data); + }; + + // friend + const friednInfoChangeHandler = ({ data }: WSEvent) => { + updateFriend(data); + }; + const friednAddedHandler = ({ data }: WSEvent) => { + pushNewFriend(data); + }; + const friednDeletedHandler = ({ data }: WSEvent) => { + updateFriend(data, true); + }; + + // blacklist + const blackAddedHandler = ({ data }: WSEvent) => { + pushNewBlack(data); + }; + const blackDeletedHandler = ({ data }: WSEvent) => { + IMSDK.getSpecifiedFriendsInfo({ + friendUserIDList: [data.userID], + }).then(({ data }) => { + if (data.length) { + pushNewFriend(data[0]); + } + }); + updateBlack(data, true); + }; + + // group + const joinedGroupAddedHandler = ({ data }: WSEvent) => { + if (data.groupID === useConversationStore.getState().currentConversation?.groupID) { + updateCurrentGroupInfo(data); + getCurrentMemberInGroupByReq(data.groupID); + } + pushNewGroup(data); + }; + const joinedGroupDeletedHandler = ({ data }: WSEvent) => { + if (data.groupID === useConversationStore.getState().currentConversation?.groupID) { + getCurrentGroupInfoByReq(data.groupID); + setCurrentMemberInGroup(); + } + updateGroup(data, true); + }; + const joinedGroupDismissHandler = ({ data }: WSEvent) => { + if (data.groupID === useConversationStore.getState().currentConversation?.groupID) { + getCurrentMemberInGroupByReq(data.groupID); + } + }; + const groupInfoChangedHandler = ({ data }: WSEvent) => { + updateGroup(data); + if (data.groupID === useConversationStore.getState().currentConversation?.groupID) { + updateCurrentGroupInfo(data); + } + }; + const groupMemberAddedHandler = ({ data }: WSEvent) => { + if ( + data.groupID === useConversationStore.getState().currentConversation?.groupID && + data.userID === useUserStore.getState().selfInfo.userID + ) { + getCurrentMemberInGroupByReq(data.groupID); + } + }; + const groupMemberDeletedHandler = ({ data }: WSEvent) => { + if ( + data.groupID === useConversationStore.getState().currentConversation?.groupID && + data.userID === useUserStore.getState().selfInfo.userID + ) { + getCurrentMemberInGroupByReq(data.groupID); + } + }; + const groupMemberInfoChangedHandler = ({ data }: WSEvent) => { + if (data.groupID === useConversationStore.getState().currentConversation?.groupID) { + tryUpdateCurrentMemberInGroup(data); + } + }; + + //application + const friendApplicationProcessedHandler = ({ + data, + }: WSEvent) => { + const isRecv = data.toUserID === useUserStore.getState().selfInfo.userID; + if (isRecv) { + updateRecvFriendApplication(data); + } else { + updateSendFriendApplication(data); + } + }; + const groupApplicationProcessedHandler = ({ + data, + }: WSEvent) => { + const isRecv = data.userID !== useUserStore.getState().selfInfo.userID; + if (isRecv) { + updateRecvGroupApplication(data); + } else { + updateSendGroupApplication(data); + } + }; + + const disposeIMListener = () => { + IMSDK.off(CbEvents.OnSelfInfoUpdated, selfUpdateHandler); + IMSDK.off(CbEvents.OnConnecting, connectingHandler); + IMSDK.off(CbEvents.OnConnectFailed, connectFailedHandler); + IMSDK.off(CbEvents.OnConnectSuccess, connectSuccessHandler); + IMSDK.off(CbEvents.OnKickedOffline, kickHandler); + IMSDK.off(CbEvents.OnUserTokenExpired, expiredHandler); + IMSDK.off(CbEvents.OnUserTokenInvalid, expiredHandler); + // sync + IMSDK.off(CbEvents.OnSyncServerStart, syncStartHandler); + IMSDK.off(CbEvents.OnSyncServerProgress, syncProgressHandler); + IMSDK.off(CbEvents.OnSyncServerFinish, syncFinishHandler); + IMSDK.off(CbEvents.OnSyncServerFailed, syncFailedHandler); + // message + IMSDK.off(CbEvents.OnRecvNewMessages, newMessageHandler); + // conversation + IMSDK.off(CbEvents.OnConversationChanged, conversationChnageHandler); + IMSDK.off(CbEvents.OnNewConversation, newConversationHandler); + IMSDK.off(CbEvents.OnTotalUnreadMessageCountChanged, totalUnreadChangeHandler); + // friend + IMSDK.off(CbEvents.OnFriendInfoChanged, friednInfoChangeHandler); + IMSDK.off(CbEvents.OnFriendAdded, friednAddedHandler); + IMSDK.off(CbEvents.OnFriendDeleted, friednDeletedHandler); + // blacklist + IMSDK.off(CbEvents.OnBlackAdded, blackAddedHandler); + IMSDK.off(CbEvents.OnBlackDeleted, blackDeletedHandler); + // group + IMSDK.off(CbEvents.OnJoinedGroupAdded, joinedGroupAddedHandler); + IMSDK.off(CbEvents.OnJoinedGroupDeleted, joinedGroupDeletedHandler); + IMSDK.off(CbEvents.OnGroupDismissed, joinedGroupDismissHandler); + IMSDK.off(CbEvents.OnGroupInfoChanged, groupInfoChangedHandler); + IMSDK.off(CbEvents.OnGroupMemberAdded, groupMemberAddedHandler); + IMSDK.off(CbEvents.OnGroupMemberDeleted, groupMemberDeletedHandler); + IMSDK.off(CbEvents.OnGroupMemberInfoChanged, groupMemberInfoChangedHandler); + // application + IMSDK.off(CbEvents.OnFriendApplicationAdded, friendApplicationProcessedHandler); + IMSDK.off(CbEvents.OnFriendApplicationAccepted, friendApplicationProcessedHandler); + IMSDK.off(CbEvents.OnFriendApplicationRejected, friendApplicationProcessedHandler); + IMSDK.off(CbEvents.OnGroupApplicationAdded, groupApplicationProcessedHandler); + IMSDK.off(CbEvents.OnGroupApplicationAccepted, groupApplicationProcessedHandler); + IMSDK.off(CbEvents.OnGroupApplicationRejected, groupApplicationProcessedHandler); + }; + + const setIpcListener = () => { + window.electronAPI?.subscribe("appResume", () => { + if (resume.current) { + return; + } + resume.current = true; + setTimeout(() => { + resume.current = false; + }, 5000); + }); + }; +} diff --git a/pc-client/src/main.tsx b/pc-client/src/main.tsx new file mode 100644 index 0000000..32d5d46 --- /dev/null +++ b/pc-client/src/main.tsx @@ -0,0 +1,21 @@ +import "./processShim"; +import "./index.scss"; +import "./i18n/index"; + +import log from "electron-log/renderer"; +import ReactDOM from "react-dom/client"; + +import App from "./App"; +import { isSaveLog } from "./config"; + +if (window.electronAPI && isSaveLog) { + const sdkLogger = log.scope("openim-sdk-core"); + console.debug = sdkLogger.debug.bind(sdkLogger); + const rendererLogger = log.scope("renderer"); + console.info = rendererLogger.info.bind(rendererLogger); + console.error = rendererLogger.error.bind(rendererLogger); +} + +ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(); + +postMessage({ payload: "removeLoading" }, "*"); diff --git a/pc-client/src/pages/chat/ConversationSider/ConversationItem.tsx b/pc-client/src/pages/chat/ConversationSider/ConversationItem.tsx new file mode 100644 index 0000000..983adb2 --- /dev/null +++ b/pc-client/src/pages/chat/ConversationSider/ConversationItem.tsx @@ -0,0 +1,97 @@ +import type { + ConversationItem as ConversationItemType, + MessageItem, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import { Badge } from "antd"; +import clsx from "clsx"; +import { t } from "i18next"; +import { memo, useMemo } from "react"; +import { useNavigate } from "react-router-dom"; +import OIMAvatar from "@/components/OIMAvatar"; +import { useConversationStore, useUserStore } from "@/store"; +import { formatConversionTime, getConversationContent } from "@/utils/imCommon"; + +import styles from "./conversation-item.module.scss"; + +interface IConversationProps { + isActive: boolean; + conversation: ConversationItemType; +} + +const ConversationItem = ({ isActive, conversation }: IConversationProps) => { + const navigate = useNavigate(); + const updateCurrentConversation = useConversationStore( + (state) => state.updateCurrentConversation, + ); + const currentUser = useUserStore((state) => state.selfInfo.userID); + + const toSpecifiedConversation = async () => { + if (isActive) { + return; + } + await updateCurrentConversation({ ...conversation }); + navigate(`/chat/${conversation.conversationID}`); + }; + + const latestMessageContent = useMemo(() => { + let content = ""; + if (!conversation.latestMsg) { + return ""; + } + try { + content = getConversationContent( + JSON.parse(conversation.latestMsg) as MessageItem, + ); + } catch (error) { + content = t("messageDescription.catchMessage"); + } + return content; + }, [conversation.draftText, conversation.latestMsg, isActive, currentUser]); + + const latestMessageTime = formatConversionTime(conversation.latestMsgSendTime); + + return ( +
+ + +
+
+
+ {conversation.showName} +
+
{latestMessageTime}
+
+ +
+
+
+
+ +
+
+
+ ); +}; + +export default memo(ConversationItem); diff --git a/pc-client/src/pages/chat/ConversationSider/conversation-item.module.scss b/pc-client/src/pages/chat/ConversationSider/conversation-item.module.scss new file mode 100644 index 0000000..ddeadfe --- /dev/null +++ b/pc-client/src/pages/chat/ConversationSider/conversation-item.module.scss @@ -0,0 +1,19 @@ +.conversation-item { + @apply relative mx-2 my-0.5 flex cursor-pointer items-center rounded-lg px-3 py-2.5; + + &-pined { + &::after { + content: ""; + position: absolute; + right: 0; + top: 0; + border: 4px solid; + border-color: var(--primary) var(--primary) transparent transparent; + } + } + + :global(.emojione) { + width: 16px; + height: 16px; + } +} diff --git a/pc-client/src/pages/chat/ConversationSider/index.module.scss b/pc-client/src/pages/chat/ConversationSider/index.module.scss new file mode 100644 index 0000000..cbcab2b --- /dev/null +++ b/pc-client/src/pages/chat/ConversationSider/index.module.scss @@ -0,0 +1,13 @@ +@keyframes loading { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + +.loading { + animation: loading 1.5s infinite; +} diff --git a/pc-client/src/pages/chat/ConversationSider/index.tsx b/pc-client/src/pages/chat/ConversationSider/index.tsx new file mode 100644 index 0000000..f7ff480 --- /dev/null +++ b/pc-client/src/pages/chat/ConversationSider/index.tsx @@ -0,0 +1,168 @@ +import { SearchOutlined } from "@ant-design/icons"; +import { Button, Input, Spin } from "antd"; +import { t } from "i18next"; +import { useMemo, useRef, useState } from "react"; +import { useNavigate, useParams } from "react-router-dom"; +import { Virtuoso, VirtuosoHandle } from "react-virtuoso"; + +import FlexibleSider from "@/components/FlexibleSider"; +import { useConversationStore, useUserStore } from "@/store"; + +import ConversationItemComp from "./ConversationItem"; + +// 断网时顶部的深色提示横条 +const OfflineBar = () => ( +
+
+ + + + + + {t("states.offline")} +
+
+ {t("states.offlineTip")} +
+
+); + +const EmptyIcon = () => ( + + + + + + +); + +const ConversationSider = () => { + const { conversationID } = useParams(); + const navigate = useNavigate(); + const conversationList = useConversationStore((state) => state.conversationList); + const getConversationListByReq = useConversationStore( + (state) => state.getConversationListByReq, + ); + const syncState = useUserStore((state) => state.syncState); + const connectState = useUserStore((state) => state.connectState); + const [keyword, setKeyword] = useState(""); + const virtuoso = useRef(null); + const hasmore = useRef(true); + const loading = useRef(false); + + const filteredList = useMemo(() => { + const word = keyword.trim(); + if (!word) return conversationList; + return conversationList.filter((conversation) => + conversation.showName?.toLowerCase().includes(word.toLowerCase()), + ); + }, [conversationList, keyword]); + + const endReached = async () => { + if (!hasmore.current || loading.current || keyword.trim()) return; + loading.current = true; + hasmore.current = await getConversationListByReq(true); + loading.current = false; + }; + + const renderBody = () => { + if (syncState === "loading" && conversationList.length === 0) { + return ( +
+ +
{t("states.loading")}
+
+ {t("states.loadingTip")} +
+
+ ); + } + if (syncState === "failed" && conversationList.length === 0) { + return ( +
+ +
{t("states.loadFailed")}
+
+ {t("states.loadFailedTip")} +
+ +
+ ); + } + if (conversationList.length === 0) { + return ( +
+ +
{t("states.noMessage")}
+
+ {t("states.noMessageTip")} +
+ +
+ ); + } + return ( + item.conversationID} + itemContent={(_, conversation) => ( + + )} + /> + ); + }; + + return ( + + {connectState === "failed" && } +
+
{t("placeholder.chat")}
+ } + placeholder={t("placeholder.search")} + allowClear + value={keyword} + onChange={(e) => setKeyword(e.target.value)} + /> +
+ {renderBody()} +
+ ); +}; + +export default ConversationSider; diff --git a/pc-client/src/pages/chat/EmptyChat.tsx b/pc-client/src/pages/chat/EmptyChat.tsx new file mode 100644 index 0000000..16dc3bf --- /dev/null +++ b/pc-client/src/pages/chat/EmptyChat.tsx @@ -0,0 +1,25 @@ +import { Layout } from "antd"; +import { useTranslation } from "react-i18next"; + +export const EmptyChat = () => { + const { t } = useTranslation(); + + return ( + +
+
+ + + +
+
{t("placeholder.title")}
+
+ {t("placeholder.subTitle")} +
+
+
+ ); +}; diff --git a/pc-client/src/pages/chat/index.tsx b/pc-client/src/pages/chat/index.tsx new file mode 100644 index 0000000..ea13ddd --- /dev/null +++ b/pc-client/src/pages/chat/index.tsx @@ -0,0 +1,13 @@ +import { Layout } from "antd"; +import { Outlet } from "react-router-dom"; + +import ConversationSider from "./ConversationSider"; + +export const Chat = () => { + return ( + + + + + ); +}; diff --git a/pc-client/src/pages/chat/queryChat/ChatContent.tsx b/pc-client/src/pages/chat/queryChat/ChatContent.tsx new file mode 100644 index 0000000..138fecd --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/ChatContent.tsx @@ -0,0 +1,152 @@ +import { SessionType } from "@openim/wasm-client-sdk"; +import { Button, Layout, Spin } from "antd"; +import clsx from "clsx"; +import { t } from "i18next"; +import { memo, useEffect, useRef } from "react"; +import { Virtuoso, VirtuosoHandle } from "react-virtuoso"; + +import { SystemMessageTypes } from "@/constants/im"; +import { useUserStore } from "@/store"; +import emitter from "@/utils/events"; +import { formatMessageTime } from "@/utils/imCommon"; + +import MessageItem from "./MessageItem"; +import NotificationMessage from "./NotificationMessage"; +import { useHistoryMessageList } from "./useHistoryMessageList"; + +// 两条消息间隔超过 5 分钟则显示时间分隔 +const TIME_DIVIDER_GAP = 5 * 60 * 1000; + +const ChatContent = () => { + const virtuoso = useRef(null); + const selfUserID = useUserStore((state) => state.selfInfo.userID); + + const scrollToBottom = () => { + setTimeout(() => { + virtuoso.current?.scrollToIndex({ + index: 9999, + align: "end", + behavior: "auto", + }); + }); + }; + + const { + SPLIT_COUNT, + conversationID, + loadState, + moreOldLoading, + getMoreOldMessages, + loadError, + } = useHistoryMessageList(); + + useEffect(() => { + emitter.on("CHAT_LIST_SCROLL_TO_BOTTOM", scrollToBottom); + return () => { + emitter.off("CHAT_LIST_SCROLL_TO_BOTTOM", scrollToBottom); + }; + }, []); + + const loadMoreMessage = () => { + if (!loadState.hasMoreOld || moreOldLoading) return; + + getMoreOldMessages().catch(() => undefined); + }; + + const renderBody = () => { + if (loadState.initLoading) { + return ( +
+ +
{t("states.loading")}
+
+ {t("states.loadingTip")} +
+
+ ); + } + if (loadError) { + return ( +
+
{t("states.loadFailed")}
+
+ {t("states.loadFailedTip")} +
+ +
+ ); + } + return ( + + loadState.hasMoreOld ? ( +
+ +
+ ) : null, + }} + computeItemKey={(_, item) => item.clientMsgID} + itemContent={(index, message) => { + const dataIndex = index - loadState.firstItemIndex; + const prevMessage = loadState.messageList[dataIndex - 1]; + const showTimeDivider = + !prevMessage || + message.sendTime - prevMessage.sendTime > TIME_DIVIDER_GAP; + + return ( +
+ {showTimeDivider && ( +
+ {formatMessageTime(message.sendTime)} +
+ )} + {SystemMessageTypes.includes(message.contentType) ? ( + + ) : ( + + )} +
+ ); + }} + /> + ); + }; + + return ( + + {renderBody()} + + ); +}; + +export default memo(ChatContent); diff --git a/pc-client/src/pages/chat/queryChat/ChatFooter/SendActionBar/useFileMessage.ts b/pc-client/src/pages/chat/queryChat/ChatFooter/SendActionBar/useFileMessage.ts new file mode 100644 index 0000000..a46e17c --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/ChatFooter/SendActionBar/useFileMessage.ts @@ -0,0 +1,105 @@ +import { MessageItem } from "@openim/wasm-client-sdk"; +import { v4 as uuidV4 } from "uuid"; + +import { IMSDK } from "@/layout/MainContentWrap"; +import { uploadFile } from "@/utils/imCommon"; + +export interface FileWithPath extends File { + path?: string; +} + +const getPicInfo = (file: File): Promise => + new Promise((resolve, reject) => { + const _URL = window.URL || window.webkitURL; + const img = new Image(); + img.onload = function () { + resolve(img); + }; + img.onerror = reject; + img.src = _URL.createObjectURL(file); + }); + +export function useFileMessage() { + const getImageMessage = async (file: FileWithPath): Promise => { + if (window.electronAPI && file.path) { + const imageMessage = (await IMSDK.createImageMessageFromFullPath(file.path)) + .data as MessageItem; + imageMessage.pictureElem!.sourcePicture.url = URL.createObjectURL(file); + return imageMessage; + } + + const { width, height } = await getPicInfo(file); + const { + data: { url }, + } = await uploadFile(file); + const baseInfo = { + uuid: uuidV4(), + type: file.type, + size: file.size, + width, + height, + url: URL.createObjectURL(file), + }; + const imageMessage = ( + await IMSDK.createImageMessageByURL({ + sourcePicture: { ...baseInfo, url }, + bigPicture: { ...baseInfo, url }, + snapshotPicture: { ...baseInfo, url }, + sourcePath: "", + }) + ).data as MessageItem; + // 本地预览用 blob 地址,避免发送中图片空白 + imageMessage.pictureElem!.snapshotPicture!.url = baseInfo.url; + return imageMessage; + }; + + const getFileMessage = async (file: FileWithPath): Promise => { + if (window.electronAPI && file.path) { + return (await IMSDK.createFileMessageFromFullPath(file.path, file.name)) + .data as MessageItem; + } + const { + data: { url }, + } = await uploadFile(file); + return ( + await IMSDK.createFileMessageByURL({ + filePath: "", + fileName: file.name, + uuid: uuidV4(), + sourceUrl: url, + fileSize: file.size, + fileType: file.type, + }) + ).data as MessageItem; + }; + + const getSoundMessage = async ( + file: FileWithPath, + duration: number, + ): Promise => { + if (window.electronAPI) { + const filePath = file.path ?? (await window.electronAPI.saveFileToDisk({ file, sync: true })); + return (await IMSDK.createSoundMessageFromFullPath(filePath, duration)) + .data as MessageItem; + } + const { + data: { url }, + } = await uploadFile(file); + return ( + await IMSDK.createSoundMessageByURL({ + uuid: uuidV4(), + soundPath: "", + sourceUrl: url, + dataSize: file.size, + duration, + soundType: file.type, + }) + ).data as MessageItem; + }; + + return { + getImageMessage, + getFileMessage, + getSoundMessage, + }; +} diff --git a/pc-client/src/pages/chat/queryChat/ChatFooter/index.tsx b/pc-client/src/pages/chat/queryChat/ChatFooter/index.tsx new file mode 100644 index 0000000..ab5a0e8 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/ChatFooter/index.tsx @@ -0,0 +1,237 @@ +import { + AudioOutlined, + FileOutlined, + PictureOutlined, + SmileOutlined, +} from "@ant-design/icons"; +import { Button, Input, Popover, Upload } from "antd"; +import { TextAreaRef } from "antd/es/input/TextArea"; +import { t } from "i18next"; +import { UploadRequestOption } from "rc-upload/lib/interface"; +import { forwardRef, ForwardRefRenderFunction, memo, useRef, useState } from "react"; + +import { IMSDK } from "@/layout/MainContentWrap"; +import { useConversationStore } from "@/store"; +import { canSendImageTypeList, feedbackToast } from "@/utils/common"; + +import { useFileMessage } from "./SendActionBar/useFileMessage"; +import { useSendMessage } from "./useSendMessage"; +import { useVoiceRecorder } from "./useVoiceRecorder"; + +const EMOJI_LIST = [ + "😀", "😁", "😂", "🤣", "😃", "😄", "😅", "😆", + "😉", "😊", "😋", "😎", "😍", "😘", "🥰", "😗", + "🙂", "🤗", "🤔", "😐", "😑", "😶", "🙄", "😏", + "😮", "😪", "😴", "😌", "😜", "🤤", "🙃", "😇", + "🥳", "🤠", "😭", "😢", "😤", "😠", "😡", "🤯", + "👍", "👎", "👌", "✌️", "🤝", "👏", "🙏", "💪", + "❤️", "💔", "💯", "🎉", "🎊", "🔥", "✨", "🌹", +]; + +const EmojiPanel = ({ onSelect }: { onSelect: (emoji: string) => void }) => ( +
+ {EMOJI_LIST.map((emoji) => ( +
onSelect(emoji)} + > + {emoji} +
+ ))} +
+); + +const ChatFooter: ForwardRefRenderFunction = (_, ref) => { + const [text, setText] = useState(""); + const [sending, setSending] = useState(false); + const [emojiVisible, setEmojiVisible] = useState(false); + const textareaRef = useRef(null); + + const currentConversation = useConversationStore( + (state) => state.currentConversation, + ); + + const { getImageMessage, getFileMessage, getSoundMessage } = useFileMessage(); + const { sendMessage } = useSendMessage(); + + const sendSound = async (file: File, duration: number) => { + try { + const message = await getSoundMessage(file, duration); + sendMessage({ message }); + } catch (error) { + feedbackToast({ error }); + } + }; + + const { recording, seconds, start, finish, cancel } = useVoiceRecorder( + ({ file, duration }) => sendSound(file, duration), + ); + + const sendText = async () => { + const cleanText = text.trim(); + if (!cleanText || sending) return; + setSending(true); + try { + const message = (await IMSDK.createTextMessage(cleanText)).data; + setText(""); + sendMessage({ message }); + } catch (error) { + feedbackToast({ error }); + } finally { + setSending(false); + } + }; + + const onKeyDown = (e: React.KeyboardEvent) => { + if (e.key === "Enter" && !e.ctrlKey && !e.metaKey && !e.shiftKey) { + e.preventDefault(); + sendText(); + return; + } + if (e.key === "Enter" && (e.ctrlKey || e.metaKey)) { + e.preventDefault(); + insertAtCursor("\n"); + } + }; + + const insertAtCursor = (value: string) => { + const textarea = textareaRef.current?.resizableTextArea?.textArea; + if (!textarea) { + setText((prev) => prev + value); + return; + } + const startPos = textarea.selectionStart ?? text.length; + const endPos = textarea.selectionEnd ?? text.length; + const next = text.slice(0, startPos) + value + text.slice(endPos); + setText(next); + setTimeout(() => { + textarea.focus(); + const pos = startPos + value.length; + textarea.setSelectionRange(pos, pos); + }); + }; + + const onEmojiSelect = (emoji: string) => { + insertAtCursor(emoji); + }; + + const sendFileMessage = async (file: File) => { + try { + const message = await getFileMessage(file); + sendMessage({ message }); + } catch (error) { + feedbackToast({ error }); + } + }; + + const sendImageMessage = async (options: UploadRequestOption) => { + const file = options.file as File; + const ext = file.name.split(".").pop()?.toLowerCase() ?? ""; + if (file.type.startsWith("image/") || canSendImageTypeList.includes(ext)) { + try { + const message = await getImageMessage(file); + sendMessage({ message }); + } catch (error) { + feedbackToast({ error }); + } + return; + } + sendFileMessage(file); + }; + + const toolIconClass = + "cursor-pointer text-xl text-[#8e9ab0] hover:text-[#515E70]"; + + return ( +
+
+ {/* 工具栏 */} +
+ } + title={null} + arrow={false} + trigger="click" + placement="topLeft" + open={emojiVisible} + onOpenChange={setEmojiVisible} + > + + + sendFileMessage(options.file as File)} + multiple + className="flex" + > + + + + + + start()} + /> +
+ + {/* 录音条 */} + {recording && ( +
+ + + {t("placeholder.microphone")} {seconds}″ + + + +
+ )} + + {/* 输入框 */} +
+ setText(e.target.value)} + onKeyDown={onKeyDown} + /> +
+ + {/* 底部提示 + 发送按钮 */} +
+ + {t("placeholder.enterToSendTip")} + + +
+
+
+ ); +}; + +export default memo(forwardRef(ChatFooter)); diff --git a/pc-client/src/pages/chat/queryChat/ChatFooter/useSendMessage.ts b/pc-client/src/pages/chat/queryChat/ChatFooter/useSendMessage.ts new file mode 100644 index 0000000..4c34eeb --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/ChatFooter/useSendMessage.ts @@ -0,0 +1,55 @@ +import { MessageStatus } from "@openim/wasm-client-sdk"; +import { MessageItem, WsResponse } from "@openim/wasm-client-sdk/lib/types/entity"; +import { SendMsgParams } from "@openim/wasm-client-sdk/lib/types/params"; +import { useCallback } from "react"; + +import { IMSDK } from "@/layout/MainContentWrap"; +import { useConversationStore } from "@/store"; +import { emit } from "@/utils/events"; + +import { pushNewMessage, updateOneMessage } from "../useHistoryMessageList"; + +export type SendMessageParams = Partial> & { + message: MessageItem; + needPush?: boolean; +}; + +export function useSendMessage() { + const sendMessage = useCallback( + async ({ recvID, groupID, message, needPush }: SendMessageParams) => { + const currentConversation = useConversationStore.getState().currentConversation; + const sourceID = recvID || groupID; + const inCurrentConversation = + currentConversation?.userID === sourceID || + currentConversation?.groupID === sourceID || + !sourceID; + needPush = needPush ?? inCurrentConversation; + + if (needPush) { + pushNewMessage(message); + emit("CHAT_LIST_SCROLL_TO_BOTTOM"); + } + + const options = { + recvID: recvID ?? currentConversation?.userID ?? "", + groupID: groupID ?? currentConversation?.groupID ?? "", + message, + }; + + try { + const { data: successMessage } = await IMSDK.sendMessage(options); + updateOneMessage(successMessage); + } catch (error) { + updateOneMessage({ + ...message, + status: MessageStatus.Failed, + }); + } + }, + [], + ); + + return { + sendMessage, + }; +} diff --git a/pc-client/src/pages/chat/queryChat/ChatFooter/useVoiceRecorder.ts b/pc-client/src/pages/chat/queryChat/ChatFooter/useVoiceRecorder.ts new file mode 100644 index 0000000..f2d3a31 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/ChatFooter/useVoiceRecorder.ts @@ -0,0 +1,112 @@ +import { t } from "i18next"; +import { useEffect, useRef, useState } from "react"; + +import { feedbackToast } from "@/utils/common"; + +const MAX_DURATION = 60; + +export interface RecorderResult { + file: File; + duration: number; +} + +export function useVoiceRecorder(onFinish: (result: RecorderResult) => void) { + const [recording, setRecording] = useState(false); + const [seconds, setSeconds] = useState(0); + const recorderRef = useRef(); + const chunksRef = useRef([]); + const timerRef = useRef(); + const secondsRef = useRef(0); + const canceledRef = useRef(false); + + const clearTimer = () => { + if (timerRef.current) { + clearInterval(timerRef.current); + timerRef.current = undefined; + } + }; + + const stopTracks = () => { + recorderRef.current?.stream.getTracks().forEach((track) => track.stop()); + }; + + useEffect(() => { + return () => { + clearTimer(); + if (recorderRef.current && recorderRef.current.state !== "inactive") { + canceledRef.current = true; + recorderRef.current.stop(); + } + stopTracks(); + }; + }, []); + + const start = async () => { + if (recording) return; + try { + const stream = await navigator.mediaDevices.getUserMedia({ audio: true }); + const mimeType = MediaRecorder.isTypeSupported("audio/webm;codecs=opus") + ? "audio/webm;codecs=opus" + : "audio/webm"; + const recorder = new MediaRecorder(stream, { mimeType }); + recorderRef.current = recorder; + chunksRef.current = []; + canceledRef.current = false; + secondsRef.current = 0; + setSeconds(0); + + recorder.ondataavailable = (e) => { + if (e.data.size > 0) chunksRef.current.push(e.data); + }; + recorder.onstop = () => { + stopTracks(); + clearTimer(); + setRecording(false); + if (canceledRef.current) return; + const duration = secondsRef.current; + if (duration < 1) { + feedbackToast({ msg: t("toast.recordTooShort"), error: t("toast.recordTooShort") }); + return; + } + const blob = new Blob(chunksRef.current, { type: mimeType }); + const file = new File([blob], `voice-${Date.now()}.webm`, { + type: mimeType, + }); + onFinish({ file, duration }); + }; + + recorder.start(); + setRecording(true); + timerRef.current = setInterval(() => { + secondsRef.current += 1; + setSeconds(secondsRef.current); + if (secondsRef.current >= MAX_DURATION) { + recorderRef.current?.stop(); + } + }, 1000); + } catch (error) { + feedbackToast({ msg: t("toast.noMicrophone"), error }); + } + }; + + const finish = () => { + if (recorderRef.current?.state === "recording") { + recorderRef.current.stop(); + } + }; + + const cancel = () => { + canceledRef.current = true; + if (recorderRef.current?.state === "recording") { + recorderRef.current.stop(); + } + }; + + return { + recording, + seconds, + start, + finish, + cancel, + }; +} diff --git a/pc-client/src/pages/chat/queryChat/ChatHeader/index.tsx b/pc-client/src/pages/chat/queryChat/ChatHeader/index.tsx new file mode 100644 index 0000000..b1c5bcb --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/ChatHeader/index.tsx @@ -0,0 +1,111 @@ +import { MoreOutlined } from "@ant-design/icons"; +import { SessionType } from "@openim/wasm-client-sdk"; +import { Dropdown, Layout } from "antd"; +import { t } from "i18next"; +import { memo, useEffect, useRef } from "react"; +import { v4 as uuidV4 } from "uuid"; + +import { OverlayVisibleHandle } from "@/hooks/useOverlayVisible"; +import { useConversationStore, useUserStore } from "@/store"; +import emitter, { emit } from "@/utils/events"; + +import GroupSetting from "../GroupSetting"; +import SingleSetting from "../SingleSetting"; + +const ChatHeader = () => { + const singleSettingRef = useRef(null); + const groupSettingRef = useRef(null); + + const currentConversation = useConversationStore( + (state) => state.currentConversation, + ); + + useEffect(() => { + if (singleSettingRef.current?.isOverlayOpen) { + singleSettingRef.current?.closeOverlay(); + } + if (groupSettingRef.current?.isOverlayOpen) { + groupSettingRef.current?.closeOverlay(); + } + }, [currentConversation?.conversationID]); + + const isSingleSession = currentConversation?.conversationType === SessionType.Single; + + const startVoiceCall = () => { + if (!currentConversation?.userID) return; + emitter.emit("OPEN_RTC_MODAL", { + invitation: { + inviterUserID: useUserStore.getState().selfInfo.userID, + inviteeUserIDList: [currentConversation.userID], + groupID: "", + roomID: uuidV4(), + timeout: 60, + mediaType: "audio", + sessionType: SessionType.Single, + platformID: window.electronAPI?.getPlatform() ?? 5, + }, + participant: { + userInfo: { + nickname: currentConversation.showName, + userID: currentConversation.userID, + faceURL: currentConversation.faceURL, + ex: "", + }, + }, + }); + }; + + const menuItems = isSingleSession + ? [ + { key: "voiceCall", label: t("placeholder.voiceCall") }, + { key: "viewProfile", label: t("placeholder.viewProfile") }, + ] + : [{ key: "groupSetting", label: t("placeholder.groupSetting") }]; + + const onMenuClick = ({ key }: { key: string }) => { + switch (key) { + case "voiceCall": + startVoiceCall(); + break; + case "viewProfile": + emit("OPEN_USER_CARD", { + userID: currentConversation?.userID, + isSelf: false, + }); + break; + case "groupSetting": + groupSettingRef.current?.openOverlay(); + break; + default: + break; + } + }; + + return ( + +
+
+
+ {currentConversation?.showName} +
+
+ + + + {/* 给悬浮窗口控制条留出空间 */} + {Boolean(window.electronAPI) &&
} +
+ + + + ); +}; + +export default memo(ChatHeader); diff --git a/pc-client/src/pages/chat/queryChat/GroupSetting/GroupMemberList.tsx b/pc-client/src/pages/chat/queryChat/GroupSetting/GroupMemberList.tsx new file mode 100644 index 0000000..5e54d6e --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/GroupSetting/GroupMemberList.tsx @@ -0,0 +1,84 @@ +import { GroupMemberItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import { Empty, Spin } from "antd"; +import { t } from "i18next"; +import { FC, memo, useEffect } from "react"; +import { Virtuoso } from "react-virtuoso"; + +import OIMAvatar from "@/components/OIMAvatar"; +import { useCurrentMemberRole } from "@/hooks/useCurrentMemberRole"; +import useGroupMembers from "@/hooks/useGroupMembers"; +import { useUserStore } from "@/store"; + +import styles from "./group-setting.module.scss"; +import { GroupMemberRole } from "@openim/wasm-client-sdk"; + +const GroupMemberList: FC = () => { + const selfUserID = useUserStore((state) => state.selfInfo.userID); + const { currentMemberInGroup } = useCurrentMemberRole(); + const { fetchState, getMemberData, resetState } = useGroupMembers(); + + useEffect(() => { + if (currentMemberInGroup?.groupID) { + getMemberData(true); + } + return () => { + resetState(); + }; + }, [currentMemberInGroup?.groupID]); + + const endReached = () => { + getMemberData(); + }; + + return ( +
+ {fetchState.groupMemberList.length === 0 ? ( + + ) : ( + (fetchState.loading ? : null), + }} + itemContent={(_, member) => ( + + )} + /> + )} +
+ ); +}; + +export default GroupMemberList; + +interface IMemberItemProps { + member: GroupMemberItem; + selfUserID: string; +} + +const MemberItem = memo(({ member }: IMemberItemProps) => { + const isOwner = member.roleLevel === GroupMemberRole.Owner; + return ( +
+
window.userClick(member.userID, member.groupID)} + > + +
+
{member.nickname}
+ {isOwner && ( + + {t("placeholder.groupOwner")} + + )} +
+
+
+ ); +}); diff --git a/pc-client/src/pages/chat/queryChat/GroupSetting/GroupMemberListHeader.tsx b/pc-client/src/pages/chat/queryChat/GroupSetting/GroupMemberListHeader.tsx new file mode 100644 index 0000000..b4ba518 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/GroupSetting/GroupMemberListHeader.tsx @@ -0,0 +1,38 @@ +import { LeftOutlined } from "@ant-design/icons"; +import { t } from "i18next"; +import { memo } from "react"; + +import invite_header from "@/assets/images/chatSetting/invite_header.png"; +import { useConversationStore } from "@/store"; +import { emit } from "@/utils/events"; + +const GroupMemberListHeader = ({ back2Settings }: { back2Settings: () => void }) => { + return ( +
+
+ +
{t("placeholder.memberList")}
+
+
+ + emit("OPEN_CHOOSE_MODAL", { + type: "INVITE_TO_GROUP", + extraData: useConversationStore.getState().currentConversation?.groupID, + }) + } + /> +
+
+ ); +}; + +export default memo(GroupMemberListHeader); diff --git a/pc-client/src/pages/chat/queryChat/GroupSetting/GroupMemberRow.tsx b/pc-client/src/pages/chat/queryChat/GroupSetting/GroupMemberRow.tsx new file mode 100644 index 0000000..2a07974 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/GroupSetting/GroupMemberRow.tsx @@ -0,0 +1,103 @@ +import { GroupItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import clsx from "clsx"; +import { t } from "i18next"; +import { memo, useEffect } from "react"; + +import invite from "@/assets/images/chatSetting/invite.png"; +import kick from "@/assets/images/chatSetting/kick.png"; +import OIMAvatar from "@/components/OIMAvatar"; +import useGroupMembers from "@/hooks/useGroupMembers"; +import { emit } from "@/utils/events"; + +import styles from "./group-setting.module.scss"; + +const GroupMemberRow = ({ + currentGroupInfo, + isNomal, + updateTravel, +}: { + currentGroupInfo: GroupItem; + isNomal: boolean; + updateTravel: () => void; +}) => { + const { fetchState, getMemberData, resetState } = useGroupMembers(); + + useEffect(() => { + if (currentGroupInfo?.groupID) { + getMemberData(true); + } + return () => { + resetState(); + }; + }, [currentGroupInfo?.groupID]); + + const sliceCount = isNomal ? 17 : 16; + + const inviteMember = (e: React.MouseEvent) => { + e.stopPropagation(); + emit("OPEN_CHOOSE_MODAL", { + type: "INVITE_TO_GROUP", + extraData: currentGroupInfo.groupID, + }); + }; + + const kickMember = (e: React.MouseEvent) => { + e.stopPropagation(); + emit("OPEN_CHOOSE_MODAL", { + type: "KICK_FORM_GROUP", + extraData: currentGroupInfo.groupID, + }); + }; + + return ( +
+
+ {t("placeholder.groupMember")} + {currentGroupInfo?.memberCount} +
+
+ {fetchState.groupMemberList.slice(0, sliceCount).map((member) => ( +
window.userClick(member.userID, member.groupID)} + > + +
+ {member.nickname} +
+
+ ))} +
+ invite +
+ {t("placeholder.add")} +
+
+ {!isNomal && ( +
+ kick +
+ {t("placeholder.remove")} +
+
+ )} +
+
+ {t("placeholder.viewMore")} +
+
+ ); +}; + +export default memo(GroupMemberRow); diff --git a/pc-client/src/pages/chat/queryChat/GroupSetting/GroupSettings.tsx b/pc-client/src/pages/chat/queryChat/GroupSetting/GroupSettings.tsx new file mode 100644 index 0000000..83b3a8e --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/GroupSetting/GroupSettings.tsx @@ -0,0 +1,167 @@ +import { RightOutlined } from "@ant-design/icons"; +import { Button, Divider, Upload } from "antd"; +import clsx from "clsx"; +import { t } from "i18next"; +import { memo, useCallback } from "react"; +import { useCopyToClipboard } from "react-use"; + +import copy from "@/assets/images/chatSetting/copy.png"; +import edit_avatar from "@/assets/images/chatSetting/edit_avatar.png"; +import EditableContent from "@/components/EditableContent"; +import OIMAvatar from "@/components/OIMAvatar"; +import SettingRow from "@/components/SettingRow"; +import { useCurrentMemberRole } from "@/hooks/useCurrentMemberRole"; +import { feedbackToast } from "@/utils/common"; +import { emit } from "@/utils/events"; +import { uploadFile } from "@/utils/imCommon"; + +import { FileWithPath } from "../ChatFooter/SendActionBar/useFileMessage"; +import GroupMemberRow from "./GroupMemberRow"; +import { useGroupSettings } from "./useGroupSettings"; + +const GroupSettings = ({ + updateTravel, + closeOverlay, +}: { + updateTravel: () => void; + closeOverlay: () => void; +}) => { + const { isNomal, isOwner, isAdmin, isJoinGroup } = useCurrentMemberRole(); + + const { currentGroupInfo, updateGroupInfo, tryQuitGroup, tryDismissGroup } = + useGroupSettings({ closeOverlay }); + + const [_, copyToClipboard] = useCopyToClipboard(); + + const customUpload = async ({ file }: { file: FileWithPath }) => { + try { + const { + data: { url }, + } = await uploadFile(file); + await updateGroupInfo({ faceURL: url }); + } catch (error) { + feedbackToast({ error: t("toast.updateAvatarFailed") }); + } + }; + + const updateGroupName = useCallback( + async (groupName: string) => { + await updateGroupInfo({ groupName }); + }, + [updateGroupInfo], + ); + + const transferGroup = () => { + emit("OPEN_CHOOSE_MODAL", { + type: "TRANSFER_IN_GROUP", + extraData: currentGroupInfo?.groupID, + }); + }; + + const hasPermissions = isAdmin || isOwner; + + return ( +
+
+
+ +
+ + {hasPermissions && ( + edit avatar + )} +
+
+ + +
+
+ + + {currentGroupInfo && isJoinGroup && ( + + )} + + + + +
+ + {currentGroupInfo?.groupID} + + { + copyToClipboard(currentGroupInfo?.groupID ?? ""); + feedbackToast({ msg: t("toast.copySuccess") }); + }} + /> +
+
+ + + {t("placeholder.workGroup")} + + + + + + {isOwner && ( + <> + + + + + + )} + +
+ {isJoinGroup && ( +
+ {!isOwner ? ( + + ) : ( + + )} +
+ )} +
+ ); +}; + +export default memo(GroupSettings); diff --git a/pc-client/src/pages/chat/queryChat/GroupSetting/group-setting.module.scss b/pc-client/src/pages/chat/queryChat/GroupSetting/group-setting.module.scss new file mode 100644 index 0000000..59781e7 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/GroupSetting/group-setting.module.scss @@ -0,0 +1,23 @@ +.member-item { + @apply flex flex-col items-center w-9 mr-3 mb-3; + + &:nth-child(9n) { + margin-right: 0; + } +} + +.list-member-item { + @apply flex items-center justify-between px-3.5 py-1 rounded-md; + + .tools-row { + @apply flex items-center invisible; + } + + &:hover { + @apply bg-[var(--primary-active)]; + + .tools-row { + @apply visible; + } + } +} diff --git a/pc-client/src/pages/chat/queryChat/GroupSetting/index.tsx b/pc-client/src/pages/chat/queryChat/GroupSetting/index.tsx new file mode 100644 index 0000000..afe3a43 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/GroupSetting/index.tsx @@ -0,0 +1,61 @@ +import { Drawer } from "antd"; +import { t } from "i18next"; +import { forwardRef, ForwardRefRenderFunction, memo, useRef, useState } from "react"; + +import { OverlayVisibleHandle, useOverlayVisible } from "@/hooks/useOverlayVisible"; + +import GroupMemberList from "./GroupMemberList"; +import GroupMemberListHeader from "./GroupMemberListHeader"; +import GroupSettings from "./GroupSettings"; + +const GroupSetting: ForwardRefRenderFunction = ( + _, + ref, +) => { + const [isPreviewMembers, setIsPreviewMembers] = useState(false); + + const { isOverlayOpen, closeOverlay } = useOverlayVisible(ref); + + const closePreviewMembers = () => { + setIsPreviewMembers(false); + }; + + return ( + + ) + } + destroyOnClose + placement="right" + rootClassName="chat-drawer" + onClose={closeOverlay} + afterOpenChange={(visible) => { + if (!visible) { + closePreviewMembers(); + } + }} + open={isOverlayOpen} + maskClassName="opacity-0" + maskMotion={{ + visible: false, + }} + width={460} + getContainer={"#chat-container"} + > + {!isPreviewMembers ? ( + setIsPreviewMembers(true)} + /> + ) : ( + + )} + + ); +}; + +export default memo(forwardRef(GroupSetting)); diff --git a/pc-client/src/pages/chat/queryChat/GroupSetting/useGroupSettings.tsx b/pc-client/src/pages/chat/queryChat/GroupSetting/useGroupSettings.tsx new file mode 100644 index 0000000..1b384a7 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/GroupSetting/useGroupSettings.tsx @@ -0,0 +1,96 @@ +import { GroupItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import { t } from "i18next"; +import { useCallback, useRef } from "react"; + +import { modal } from "@/AntdGlobalComp"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { useConversationStore } from "@/store"; +import { feedbackToast } from "@/utils/common"; + +export type PermissionField = "applyMemberFriend" | "lookMemberInfo"; + +export function useGroupSettings({ closeOverlay }: { closeOverlay: () => void }) { + const currentGroupInfo = useConversationStore((state) => state.currentGroupInfo); + + const modalRef = useRef<{ + destroy: () => void; + } | null>(null); + + const updateGroupInfo = useCallback( + async (value: Partial) => { + if (!currentGroupInfo) return; + try { + await IMSDK.setGroupInfo({ + ...value, + groupID: currentGroupInfo.groupID, + }); + } catch (error) { + feedbackToast({ error, msg: t("toast.updateGroupInfoFailed") }); + } + }, + [currentGroupInfo?.groupID], + ); + + const tryDismissGroup = () => { + if (!currentGroupInfo || modalRef.current) return; + + modalRef.current = modal.confirm({ + title: t("placeholder.disbandGroup"), + content: ( +
+
{t("toast.confirmDisbandGroup")}
+ + {t("placeholder.disbandGroupToast")} + +
+ ), + onOk: async () => { + try { + await IMSDK.dismissGroup(currentGroupInfo.groupID); + closeOverlay(); + } catch (error) { + feedbackToast({ error }); + } + modalRef.current = null; + }, + onCancel: () => { + modalRef.current = null; + }, + }); + }; + + const tryQuitGroup = () => { + if (!currentGroupInfo || modalRef.current) return; + + modalRef.current = modal.confirm({ + title: t("placeholder.exitGroup"), + content: ( +
+
{t("toast.confirmExitGroup")}
+ + {t("placeholder.exitGroupToast")} + +
+ ), + onOk: async () => { + try { + await IMSDK.quitGroup(currentGroupInfo.groupID); + closeOverlay(); + } catch (error) { + feedbackToast({ error }); + } + modalRef.current = null; + }, + onCancel: () => { + modalRef.current = null; + }, + }); + }; + + return { + currentGroupInfo, + updateGroupInfo, + tryQuitGroup, + tryDismissGroup, + }; +} diff --git a/pc-client/src/pages/chat/queryChat/MessageItem/CatchMsgRenderer.tsx b/pc-client/src/pages/chat/queryChat/MessageItem/CatchMsgRenderer.tsx new file mode 100644 index 0000000..15a0597 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/MessageItem/CatchMsgRenderer.tsx @@ -0,0 +1,19 @@ +import { MessageType } from "@openim/wasm-client-sdk"; +import { FC } from "react"; +import { useTranslation } from "react-i18next"; + +import { IMessageItemProps } from "."; +import styles from "./message-item.module.scss"; + +const CatchMessageRender: FC = ({ message }) => { + const { t } = useTranslation(); + + const text = + message.contentType === MessageType.VideoMessage + ? t("messageDescription.videoNotSupport") + : t("messageDescription.catchMessage"); + + return
{text}
; +}; + +export default CatchMessageRender; diff --git a/pc-client/src/pages/chat/queryChat/MessageItem/FileMessageRender.tsx b/pc-client/src/pages/chat/queryChat/MessageItem/FileMessageRender.tsx new file mode 100644 index 0000000..a2f1ce1 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/MessageItem/FileMessageRender.tsx @@ -0,0 +1,90 @@ +import { FC, useState } from "react"; + +import { feedbackToast } from "@/utils/common"; + +import { IMessageItemProps } from "."; + +const formatFileSize = (size: number) => { + if (!size && size !== 0) return ""; + if (size < 1024) return `${size} B`; + if (size < 1024 * 1024) return `${(size / 1024).toFixed(1)} KB`; + if (size < 1024 * 1024 * 1024) return `${(size / 1024 / 1024).toFixed(1)} MB`; + return `${(size / 1024 / 1024 / 1024).toFixed(1)} GB`; +}; + +const FileIcon = () => ( +
+ + + + + +
+); + +const FileMessageRender: FC = ({ message }) => { + const [downloading, setDownloading] = useState(false); + const fileElem = message.fileElem; + + const saveFile = async () => { + if (!fileElem || downloading) return; + setDownloading(true); + try { + let url = fileElem.sourceUrl; + let revoke = false; + if (!url && fileElem.filePath && window.electronAPI) { + const file = await window.electronAPI.getFileByPath(fileElem.filePath); + if (file) { + url = URL.createObjectURL(file); + revoke = true; + } + } + if (!url) throw new Error("no file url"); + + const link = document.createElement("a"); + link.href = url; + link.download = fileElem.fileName || "file"; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + if (revoke) { + setTimeout(() => URL.revokeObjectURL(url), 5000); + } + } catch (error) { + feedbackToast({ error }); + } finally { + setDownloading(false); + } + }; + + if (!fileElem) return null; + + return ( +
+ +
+
+ {fileElem.fileName} +
+
+ {formatFileSize(fileElem.fileSize)} +
+
+
+ ); +}; + +export default FileMessageRender; diff --git a/pc-client/src/pages/chat/queryChat/MessageItem/MediaMessageRender.tsx b/pc-client/src/pages/chat/queryChat/MessageItem/MediaMessageRender.tsx new file mode 100644 index 0000000..c535b9f --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/MessageItem/MediaMessageRender.tsx @@ -0,0 +1,41 @@ +import { MessageStatus } from "@openim/wasm-client-sdk"; +import { Image, Spin } from "antd"; +import { FC } from "react"; + +import { IMessageItemProps } from "."; + +const min = (a: number, b: number) => (a > b ? b : a); + +const MediaMessageRender: FC = ({ message }) => { + const imageHeight = message.pictureElem!.sourcePicture.height; + const imageWidth = message.pictureElem!.sourcePicture.width; + const snapshotMaxHeight = message.pictureElem!.snapshotPicture?.height ?? imageHeight; + const minHeight = min(200, imageWidth) * (imageHeight / imageWidth) + 2; + const adaptedHight = min(minHeight, snapshotMaxHeight) + 10; + const adaptedWidth = min(imageWidth, 200) + 10; + + const sourceUrl = + message.pictureElem!.snapshotPicture?.url || message.pictureElem!.sourcePicture.url; + const isSending = message.status === MessageStatus.Sending; + const minStyle = { minHeight: `${adaptedHight}px`, minWidth: `${adaptedWidth}px` }; + + return ( + +
+ + +
+ } + /> +
+ + ); +}; + +export default MediaMessageRender; diff --git a/pc-client/src/pages/chat/queryChat/MessageItem/MessageItemErrorBoundary.tsx b/pc-client/src/pages/chat/queryChat/MessageItem/MessageItemErrorBoundary.tsx new file mode 100644 index 0000000..a9b5afe --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/MessageItem/MessageItemErrorBoundary.tsx @@ -0,0 +1,42 @@ +import { MessageItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import { Component, ErrorInfo, ReactNode } from "react"; + +import CatchMessageRender from "./CatchMsgRenderer"; + +type MessageItemErrorBoundaryProps = { + children: ReactNode; + message: MessageItem; +}; + +type MessageItemErrorBoundaryState = { + hasError: boolean; + message: MessageItem; +}; + +class MessageItemErrorBoundary extends Component< + MessageItemErrorBoundaryProps, + MessageItemErrorBoundaryState +> { + constructor(props: MessageItemErrorBoundaryProps) { + super(props); + this.state = { hasError: false, message: props.message }; + } + + componentDidCatch(error: Error, errorInfo: ErrorInfo) { + console.error("MessageItemErrorBoundary:::"); + console.error(this.state.message); + console.error(error); + + this.setState({ hasError: true }); + } + + render() { + if (this.state.hasError) { + return ; + } + + return this.props.children; + } +} + +export default MessageItemErrorBoundary; diff --git a/pc-client/src/pages/chat/queryChat/MessageItem/MessageSuffix.tsx b/pc-client/src/pages/chat/queryChat/MessageItem/MessageSuffix.tsx new file mode 100644 index 0000000..023d373 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/MessageItem/MessageSuffix.tsx @@ -0,0 +1,65 @@ +import { ExclamationCircleFilled, LoadingOutlined } from "@ant-design/icons"; +import { MessageStatus } from "@openim/wasm-client-sdk"; +import { Spin, Tooltip } from "antd"; +import { t } from "i18next"; +import { FC, useEffect, useState } from "react"; + +import { IMSDK } from "@/layout/MainContentWrap"; +import { useConversationStore } from "@/store"; + +import { IMessageItemProps } from "."; +import styles from "./message-item.module.scss"; +import { updateOneMessage } from "../useHistoryMessageList"; + +const MessageSuffix: FC = ({ message }) => { + const [showSending, setShowSending] = useState(false); + + useEffect(() => { + if (message.status !== MessageStatus.Sending) return; + const timer = setTimeout(() => { + if (message.status === MessageStatus.Sending) { + setShowSending(true); + } + }, 1000); + return () => { + clearTimeout(timer); + }; + }, [message.status]); + + const resendMessage = async () => { + const currentConversation = useConversationStore.getState().currentConversation; + updateOneMessage({ ...message, status: MessageStatus.Sending }); + try { + const { data: successMessage } = await IMSDK.sendMessage({ + recvID: currentConversation?.userID ?? "", + groupID: currentConversation?.groupID ?? "", + message, + }); + updateOneMessage(successMessage); + } catch (error) { + updateOneMessage({ ...message, status: MessageStatus.Failed }); + } + }; + + return ( +
+ {showSending && message.status === MessageStatus.Sending && ( + } + /> + )} + {message.status === MessageStatus.Failed && ( + + + + )} +
+ ); +}; + +export default MessageSuffix; diff --git a/pc-client/src/pages/chat/queryChat/MessageItem/SoundMessageRender.tsx b/pc-client/src/pages/chat/queryChat/MessageItem/SoundMessageRender.tsx new file mode 100644 index 0000000..0b58f5d --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/MessageItem/SoundMessageRender.tsx @@ -0,0 +1,97 @@ +import clsx from "clsx"; +import { t } from "i18next"; +import { FC, useEffect, useRef, useState } from "react"; + +import { feedbackToast } from "@/utils/common"; + +import { IMessageItemProps } from "."; +import styles from "./message-item.module.scss"; + +const PLAYED_KEY = "chaglian_played_sounds"; + +const getPlayedMap = (): Record => { + try { + return JSON.parse(localStorage.getItem(PLAYED_KEY) ?? "{}"); + } catch (error) { + return {}; + } +}; + +const markPlayed = (clientMsgID: string) => { + const map = getPlayedMap(); + map[clientMsgID] = true; + localStorage.setItem(PLAYED_KEY, JSON.stringify(map)); +}; + +const SoundIcon = ({ className }: { className?: string }) => ( + + + + +); + +const SoundMessageRender: FC = ({ message, isSender }) => { + const soundElem = message.soundElem; + const duration = Math.max(1, Math.round(soundElem?.duration ?? 0)); + const [playing, setPlaying] = useState(false); + const [played, setPlayed] = useState( + () => Boolean(getPlayedMap()[message.clientMsgID]), + ); + const audioRef = useRef(); + + useEffect(() => { + return () => { + audioRef.current?.pause(); + audioRef.current = undefined; + }; + }, []); + + // 宽度随时长微变:60~180px + const width = Math.min(180, 60 + duration * 6); + + const play = () => { + const url = soundElem?.sourceUrl || soundElem?.soundPath; + if (!url || playing) return; + const audio = new Audio(url); + audioRef.current = audio; + setPlaying(true); + audio.onended = () => setPlaying(false); + audio.onerror = () => { + setPlaying(false); + feedbackToast({ msg: t("toast.accessFailed"), error: new Error("audio error") }); + }; + audio.play().catch(() => setPlaying(false)); + markPlayed(message.clientMsgID); + setPlayed(true); + }; + + return ( +
+
+ + {duration}″ +
+ {!isSender && !played && ( + + )} +
+ ); +}; + +export default SoundMessageRender; diff --git a/pc-client/src/pages/chat/queryChat/MessageItem/TextMessageRender.tsx b/pc-client/src/pages/chat/queryChat/MessageItem/TextMessageRender.tsx new file mode 100644 index 0000000..684d5ff --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/MessageItem/TextMessageRender.tsx @@ -0,0 +1,18 @@ +import { FC } from "react"; + +import { formatBr } from "@/utils/common"; + +import { IMessageItemProps } from "."; +import styles from "./message-item.module.scss"; + +const TextMessageRender: FC = ({ message }) => { + let content = message.textElem?.content; + + content = formatBr(content!); + + return ( +
+ ); +}; + +export default TextMessageRender; diff --git a/pc-client/src/pages/chat/queryChat/MessageItem/index.tsx b/pc-client/src/pages/chat/queryChat/MessageItem/index.tsx new file mode 100644 index 0000000..b2d0432 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/MessageItem/index.tsx @@ -0,0 +1,93 @@ +import { MessageItem as MessageItemType, MessageType } from "@openim/wasm-client-sdk"; +import clsx from "clsx"; +import { FC, memo } from "react"; + +import OIMAvatar from "@/components/OIMAvatar"; + +import CatchMessageRender from "./CatchMsgRenderer"; +import FileMessageRender from "./FileMessageRender"; +import MediaMessageRender from "./MediaMessageRender"; +import styles from "./message-item.module.scss"; +import MessageItemErrorBoundary from "./MessageItemErrorBoundary"; +import MessageSuffix from "./MessageSuffix"; +import SoundMessageRender from "./SoundMessageRender"; +import TextMessageRender from "./TextMessageRender"; + +export interface IMessageItemProps { + message: MessageItemType; + isSender: boolean; + disabled?: boolean; + conversationID?: string; + messageUpdateFlag?: string; +} + +const components: Record> = { + [MessageType.TextMessage]: TextMessageRender, + [MessageType.PictureMessage]: MediaMessageRender, + [MessageType.FileMessage]: FileMessageRender, + [MessageType.VoiceMessage]: SoundMessageRender, +}; + +const MessageItem: FC = ({ + message, + disabled, + isSender, + conversationID, +}) => { + const MessageRenderComponent = components[message.contentType] || CatchMessageRender; + const isGroupMessage = Boolean(message.groupID); + const showNickname = isGroupMessage && !isSender; + + return ( +
+
+ + +
+ {showNickname && ( +
+
+ {message.senderNickname} +
+
+ )} + +
+ + + + + +
+
+
+
+ ); +}; + +export default memo(MessageItem); diff --git a/pc-client/src/pages/chat/queryChat/MessageItem/message-item.module.scss b/pc-client/src/pages/chat/queryChat/MessageItem/message-item.module.scss new file mode 100644 index 0000000..35d1258 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/MessageItem/message-item.module.scss @@ -0,0 +1,73 @@ +.message-container { + @apply flex flex-1 overflow-hidden; + + .message-wrap { + @apply mx-3 flex flex-1 flex-col overflow-hidden; + + .message-profile { + @apply mb-1 flex w-full text-xs; + } + + .bubble { + @apply w-fit rounded-xl p-2.5; + word-break: break-word; + background-color: var(--chat-bubble); + } + + .suffix { + @apply ml-3 flex items-center; + } + } + + .menu-wrap { + @apply flex w-fit items-center; + } + + &-sender { + @apply flex-row-reverse; + + .message-wrap { + @apply items-end; + + .message-profile { + @apply flex-row-reverse; + } + + .bubble { + background-color: var(--chat-bubble-sender); + } + + .suffix { + @apply ml-0 mr-3; + } + } + + .menu-wrap { + @apply flex-row-reverse; + } + } +} + +.animate-container { + // background-color: var(--primary-active); + animation: animate 2s ease-in-out; +} +@keyframes animate { + from { + background-color: var(--primary-active); + } + to { + background-color: transparent; + } +} + +.card-shadow { + @apply w-60 cursor-pointer overflow-hidden rounded-md shadow-md; + box-shadow: 3px 3px 8px 1px rgba(81, 94, 112, 0.1); +} + +.bubble { + word-wrap: break-word; + word-break: break-word; + white-space: pre-wrap; +} diff --git a/pc-client/src/pages/chat/queryChat/NotificationMessage.tsx b/pc-client/src/pages/chat/queryChat/NotificationMessage.tsx new file mode 100644 index 0000000..8b64045 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/NotificationMessage.tsx @@ -0,0 +1,25 @@ +import { MessageItem } from "@openim/wasm-client-sdk"; +import clsx from "clsx"; +import { FC, memo, useRef } from "react"; + +import { notificationMessageFormat } from "@/utils/imCommon"; + +const NotificationMessage: FC<{ + message: MessageItem; +}> = ({ message }) => { + const messageWrapRef = useRef(null); + + return ( +
+
+
+ ); +}; + +export default memo(NotificationMessage); diff --git a/pc-client/src/pages/chat/queryChat/SingleSetting/index.tsx b/pc-client/src/pages/chat/queryChat/SingleSetting/index.tsx new file mode 100644 index 0000000..ec1b004 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/SingleSetting/index.tsx @@ -0,0 +1,133 @@ +import { RightOutlined } from "@ant-design/icons"; +import { Button, Divider, Drawer } from "antd"; +import { t } from "i18next"; +import { forwardRef, ForwardRefRenderFunction, memo } from "react"; + +import { modal } from "@/AntdGlobalComp"; +import OIMAvatar from "@/components/OIMAvatar"; +import SettingRow from "@/components/SettingRow"; +import { OverlayVisibleHandle, useOverlayVisible } from "@/hooks/useOverlayVisible"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { useContactStore } from "@/store/contact"; +import { feedbackToast } from "@/utils/common"; +import { emit } from "@/utils/events"; +import { useConversationStore } from "@/store"; + +// export interface SingleSettingProps {} + +const SingleSetting: ForwardRefRenderFunction = ( + _, + ref, +) => { + const currentConversation = useConversationStore( + (state) => state.currentConversation, + ); + + const isBlack = useContactStore((state) => state.blackList).some( + (black) => currentConversation?.userID === black.userID, + ); + const isFriend = useContactStore((state) => state.friendList).some( + (friend) => currentConversation?.userID === friend.userID, + ); + + const { isOverlayOpen, closeOverlay } = useOverlayVisible(ref); + + const updateBlack = async () => { + if (!currentConversation) return; + const execFunc = async () => { + try { + isBlack + ? await IMSDK.removeBlack(currentConversation?.userID) + : await IMSDK.addBlack({ + toUserID: currentConversation?.userID, + }); + } catch (error) { + feedbackToast({ error, msg: t("toast.updateBlackStateFailed") }); + } + }; + if (!isBlack) { + modal.confirm({ + title: t("placeholder.moveBlacklist"), + content: ( +
+
{t("toast.confirmMoveBlacklist")}
+ + {t("placeholder.willFilterThisUserMessage")} + +
+ ), + onOk: execFunc, + }); + } else { + await execFunc(); + } + }; + + const tryUnfriend = () => { + if (!currentConversation) return; + modal.confirm({ + title: t("placeholder.unfriend"), + content: t("toast.confirmUnfriend"), + onOk: async () => { + try { + await IMSDK.deleteFriend(currentConversation.userID); + } catch (error) { + feedbackToast({ error, msg: t("toast.unfriendFailed") }); + } + }, + }); + }; + + const openUserCard = () => { + emit("OPEN_USER_CARD", { userID: currentConversation?.userID }); + }; + + return ( + +
+
+ +
{currentConversation?.showName}
+
+ +
+ + + + +
+ {isFriend && ( +
+ +
+ )} + + ); +}; + +export default memo(forwardRef(SingleSetting)); diff --git a/pc-client/src/pages/chat/queryChat/index.tsx b/pc-client/src/pages/chat/queryChat/index.tsx new file mode 100644 index 0000000..cb7ec00 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/index.tsx @@ -0,0 +1,99 @@ +import { Layout } from "antd"; +import { t } from "i18next"; +import { useUnmount } from "ahooks"; +import { DragEvent, useRef, useState } from "react"; + +import { useConversationStore } from "@/store"; +import { canSendImageTypeList, feedbackToast } from "@/utils/common"; + +import ChatContent from "./ChatContent"; +import ChatFooter from "./ChatFooter"; +import { useFileMessage } from "./ChatFooter/SendActionBar/useFileMessage"; +import ChatHeader from "./ChatHeader"; +import useConversationState from "./useConversationState"; +import { useSendMessage } from "./ChatFooter/useSendMessage"; + +export const QueryChat = () => { + const [dropVisible, setDropVisible] = useState(false); + const dragDepth = useRef(0); + + const updateCurrentConversation = useConversationStore( + (state) => state.updateCurrentConversation, + ); + + const { getImageMessage, getFileMessage } = useFileMessage(); + const { sendMessage } = useSendMessage(); + + useConversationState(); + + useUnmount(() => { + updateCurrentConversation(); + }); + + const onDragEnter = (e: DragEvent) => { + if (!e.dataTransfer.types.includes("Files")) return; + e.preventDefault(); + dragDepth.current += 1; + setDropVisible(true); + }; + + const onDragOver = (e: DragEvent) => { + if (!e.dataTransfer.types.includes("Files")) return; + e.preventDefault(); + }; + + const onDragLeave = (e: DragEvent) => { + if (!e.dataTransfer.types.includes("Files")) return; + dragDepth.current -= 1; + if (dragDepth.current <= 0) { + dragDepth.current = 0; + setDropVisible(false); + } + }; + + const onDrop = async (e: DragEvent) => { + if (!e.dataTransfer.types.includes("Files")) return; + e.preventDefault(); + dragDepth.current = 0; + setDropVisible(false); + + const files = Array.from(e.dataTransfer.files); + for (const file of files) { + const ext = file.name.split(".").pop()?.toLowerCase() ?? ""; + const isImage = + file.type.startsWith("image/") || canSendImageTypeList.includes(ext); + try { + const message = isImage + ? await getImageMessage(file) + : await getFileMessage(file); + sendMessage({ message }); + } catch (error) { + feedbackToast({ error }); + } + } + }; + + return ( + + +
+ +
+ + {dropVisible && ( +
+
+ {t("placeholder.dropToSend")} +
+
+ )} +
+ ); +}; diff --git a/pc-client/src/pages/chat/queryChat/useConversationState.ts b/pc-client/src/pages/chat/queryChat/useConversationState.ts new file mode 100644 index 0000000..9535698 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/useConversationState.ts @@ -0,0 +1,51 @@ +import { useLatest, useThrottleFn, useUpdateEffect } from "ahooks"; +import { useEffect } from "react"; + +import { IMSDK } from "@/layout/MainContentWrap"; +import { useConversationStore, useUserStore } from "@/store"; + +export default function useConversationState() { + const syncState = useUserStore((state) => state.syncState); + const latestSyncState = useLatest(syncState); + const currentConversation = useConversationStore( + (state) => state.currentConversation, + ); + const latestCurrentConversation = useLatest(currentConversation); + + useUpdateEffect(() => { + if (syncState !== "loading") { + checkConversationState(); + } + }, [syncState]); + + useUpdateEffect(() => { + throttleCheckConversationState(); + }, [currentConversation?.unreadCount]); + + useEffect(() => { + checkConversationState(); + }, [currentConversation?.conversationID]); + + const checkConversationState = () => { + if ( + !latestCurrentConversation.current || + latestSyncState.current === "loading" + ) + return; + + if (latestCurrentConversation.current.unreadCount > 0) { + IMSDK.markConversationMessageAsRead( + latestCurrentConversation.current.conversationID, + ); + } + }; + + const { run: throttleCheckConversationState } = useThrottleFn( + checkConversationState, + { wait: 2000, leading: false }, + ); + + return { + currentConversation, + }; +} diff --git a/pc-client/src/pages/chat/queryChat/useHistoryMessageList.tsx b/pc-client/src/pages/chat/queryChat/useHistoryMessageList.tsx new file mode 100644 index 0000000..ff11ea7 --- /dev/null +++ b/pc-client/src/pages/chat/queryChat/useHistoryMessageList.tsx @@ -0,0 +1,120 @@ +import { MessageItem, ViewType } from "@openim/wasm-client-sdk"; +import { useLatest, useRequest } from "ahooks"; +import { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; + +import { IMSDK } from "@/layout/MainContentWrap"; +import emitter, { emit } from "@/utils/events"; + +const START_INDEX = 10000; +const SPLIT_COUNT = 20; + +export function useHistoryMessageList() { + const { conversationID } = useParams(); + const [loadState, setLoadState] = useState({ + initLoading: true, + hasMoreOld: true, + messageList: [] as MessageItem[], + firstItemIndex: START_INDEX, + }); + const latestLoadState = useLatest(loadState); + + useEffect(() => { + loadHistoryMessages(); + return () => { + setLoadState(() => ({ + initLoading: true, + hasMoreOld: true, + messageList: [] as MessageItem[], + firstItemIndex: START_INDEX, + })); + }; + }, [conversationID]); + + useEffect(() => { + const pushNewMessage = (message: MessageItem) => { + if ( + latestLoadState.current.messageList.find( + (item) => item.clientMsgID === message.clientMsgID, + ) + ) { + return; + } + setLoadState((preState) => ({ + ...preState, + messageList: [...preState.messageList, message], + })); + }; + const updateOneMessage = (message: MessageItem) => { + setLoadState((preState) => { + const tmpList = [...preState.messageList]; + const idx = tmpList.findIndex((msg) => msg.clientMsgID === message.clientMsgID); + if (idx < 0) { + return preState; + } + + tmpList[idx] = { ...tmpList[idx], ...message }; + return { + ...preState, + messageList: tmpList, + }; + }); + }; + emitter.on("PUSH_NEW_MSG", pushNewMessage); + emitter.on("UPDATE_ONE_MSG", updateOneMessage); + return () => { + emitter.off("PUSH_NEW_MSG", pushNewMessage); + emitter.off("UPDATE_ONE_MSG", updateOneMessage); + }; + }, []); + + const loadHistoryMessages = () => getMoreOldMessages(false).catch(() => undefined); + + const { + loading: moreOldLoading, + runAsync: getMoreOldMessages, + error: loadError, + } = useRequest( + async (loadMore = true) => { + const reqConversationID = conversationID; + const { data } = await IMSDK.getAdvancedHistoryMessageList({ + count: SPLIT_COUNT, + startClientMsgID: loadMore + ? latestLoadState.current?.messageList[0]?.clientMsgID ?? "" + : "", + conversationID: conversationID ?? "", + viewType: ViewType.History, + }); + if (conversationID !== reqConversationID) return; + setTimeout(() => + setLoadState((preState) => ({ + ...preState, + initLoading: false, + hasMoreOld: !data.isEnd, + messageList: [...data.messageList, ...(loadMore ? preState.messageList : [])], + firstItemIndex: preState.firstItemIndex - data.messageList.length, + })), + ); + }, + { + manual: true, + onError: () => { + setLoadState((preState) => ({ ...preState, initLoading: false })); + }, + }, + ); + + return { + SPLIT_COUNT, + loadState, + latestLoadState, + conversationID, + moreOldLoading, + getMoreOldMessages, + loadError: Boolean(loadError) && loadState.messageList.length === 0, + }; +} + +export const pushNewMessage = (message: MessageItem) => emit("PUSH_NEW_MSG", message); +export const updateOneMessage = (message: MessageItem) => + emit("UPDATE_ONE_MSG", message); diff --git a/pc-client/src/pages/common/ChooseModal/ChooseBox/CheckItem.tsx b/pc-client/src/pages/common/ChooseModal/ChooseBox/CheckItem.tsx new file mode 100644 index 0000000..ef9d5bc --- /dev/null +++ b/pc-client/src/pages/common/ChooseModal/ChooseBox/CheckItem.tsx @@ -0,0 +1,72 @@ +import { CloseOutlined, RightOutlined } from "@ant-design/icons"; +import { SessionType } from "@openim/wasm-client-sdk"; +import { + ConversationItem, + FriendUserItem, + GroupItem, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import { Checkbox } from "antd"; +import clsx from "clsx"; +import { FC, memo } from "react"; + +import OIMAvatar from "@/components/OIMAvatar"; + +interface ICheckItemProps { + data: CheckListItem; + isChecked?: boolean; + showCheck?: boolean; + disabled?: boolean; + itemClick?: (data: CheckListItem) => void; + cancelClick?: (data: CheckListItem) => void; +} + +export type CheckListItem = Partial< + FriendUserItem & ConversationItem & GroupItem & { disabled?: boolean } +>; + +const CheckItem: FC = (props) => { + const { data, isChecked, showCheck, disabled, itemClick, cancelClick } = props; + const showName = data.remark || data.nickname || data.groupName || data.showName; + const isDisabled = disabled ?? data.disabled; + return ( +
!isDisabled && itemClick?.(data)} + > +
+ {showCheck && ( + + )} + +
{showName}
+
+ {showCheck ? ( + + ) : ( + { + e.stopPropagation(); + cancelClick?.(data); + }} + /> + )} +
+ ); +}; + +export default memo(CheckItem); diff --git a/pc-client/src/pages/common/ChooseModal/ChooseBox/MenuItem.tsx b/pc-client/src/pages/common/ChooseModal/ChooseBox/MenuItem.tsx new file mode 100644 index 0000000..f827d6b --- /dev/null +++ b/pc-client/src/pages/common/ChooseModal/ChooseBox/MenuItem.tsx @@ -0,0 +1,25 @@ +import { RightOutlined } from "@ant-design/icons"; + +import { ChooseMenuItem } from "."; + +const MenuItem = ({ + menu, + menuClick, +}: { + menu: ChooseMenuItem; + menuClick: (idx: number) => void; +}) => ( +
menuClick(menu.idx)} + > +
+ +
{menu.title}
+
+ +
+); + +export default MenuItem; diff --git a/pc-client/src/pages/common/ChooseModal/ChooseBox/index.tsx b/pc-client/src/pages/common/ChooseModal/ChooseBox/index.tsx new file mode 100644 index 0000000..99a7ead --- /dev/null +++ b/pc-client/src/pages/common/ChooseModal/ChooseBox/index.tsx @@ -0,0 +1,336 @@ +import { SearchOutlined } from "@ant-design/icons"; +import { SessionType } from "@openim/wasm-client-sdk"; +import { GroupMemberItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import { useDebounceFn, useLatest } from "ahooks"; +import { Breadcrumb, Input, Spin } from "antd"; +import { BreadcrumbItemType } from "antd/es/breadcrumb/Breadcrumb"; +import clsx from "clsx"; +import i18n, { t } from "i18next"; +import { + ChangeEvent, + FC, + forwardRef, + ForwardRefRenderFunction, + memo, + useCallback, + useEffect, + useImperativeHandle, + useRef, + useState, +} from "react"; +import { Virtuoso } from "react-virtuoso"; + +import friend from "@/assets/images/chooseModal/friend.png"; +import group from "@/assets/images/chooseModal/group.png"; +import recently from "@/assets/images/chooseModal/recently.png"; +import { useCurrentMemberRole } from "@/hooks/useCurrentMemberRole"; +import useGroupMembers from "@/hooks/useGroupMembers"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { useConversationStore } from "@/store"; +import { useContactStore } from "@/store/contact"; +import { feedbackToast } from "@/utils/common"; + +import CheckItem, { CheckListItem } from "./CheckItem"; +import MenuItem from "./MenuItem"; + +const menuList = [ + { + idx: 0, + title: t("placeholder.myFriend"), + icon: friend, + }, +]; + +i18n.on("languageChanged", () => { + menuList[0].title = t("placeholder.myFriend"); +}); + +export type ChooseMenuItem = (typeof menuList)[0]; + +interface IChooseBoxProps { + className?: string; + isCheckInGroup?: boolean; + showGroupMember?: boolean; + chooseOneOnly?: boolean; + checkMemberRole?: boolean; +} + +export interface ChooseBoxHandle { + getCheckedList: () => CheckListItem[]; + updatePrevCheckList: (data: CheckListItem[]) => void; + resetState: () => void; +} + +const ChooseBox: ForwardRefRenderFunction = ( + props, + ref, +) => { + const { className, isCheckInGroup, showGroupMember, chooseOneOnly, checkMemberRole } = + props; + + const [checkedList, setCheckedList] = useState([]); + const latestCheckedList = useLatest(checkedList); + + const checkClick = useCallback( + (data: CheckListItem) => { + const idx = latestCheckedList.current.findIndex( + (item) => + (item.userID && item.userID === data.userID) || + (item.groupID && item.groupID === data.groupID && !showGroupMember), + ); + if (idx > -1) { + setCheckedList((state) => { + const newState = [...state]; + newState.splice(idx, 1); + return newState; + }); + } else { + if (chooseOneOnly && latestCheckedList.current.length > 0) { + feedbackToast({ + msg: t("toast.beyondSelectionLimit"), + error: t("toast.beyondSelectionLimit"), + }); + return; + } + + setCheckedList((state) => [...state, data]); + } + }, + [chooseOneOnly], + ); + + const isChecked = useCallback( + (data: CheckListItem) => + checkedList.some( + (item) => + (item.userID && item.userID === data.userID) || + (item.groupID && item.groupID === data.groupID && !showGroupMember), + ), + [checkedList.length, showGroupMember], + ); + + const resetState = () => { + setCheckedList([]); + }; + + const updatePrevCheckList = (data: CheckListItem[]) => { + setCheckedList([...data]); + }; + + useImperativeHandle(ref, () => ({ + getCheckedList: () => checkedList, + resetState, + updatePrevCheckList, + })); + + return ( +
+
+
+ + {showGroupMember ? ( + + ) : ( + + )} +
+
+
+ {t("placeholder.selected")} + {` ${checkedList.length} `} +
+
+ {checkedList.map((item) => ( + + ))} +
+
+
+ ); +}; + +export default memo(forwardRef(ChooseBox)); + +interface ICommonLeftProps { + isCheckInGroup: boolean; + checkClick: (data: CheckListItem) => void; + isChecked: (data: CheckListItem) => boolean; +} + +const CommonLeft: FC = ({ + isCheckInGroup, + checkClick, + isChecked, +}) => { + const [breadcrumb, setBreadcrumb] = useState([]); + const [checkList, setCheckList] = useState([]); + + const breadcrumbClick = (e: React.MouseEvent) => { + e.preventDefault(); + setBreadcrumb([]); + }; + + const checkInGroup = async (list: CheckListItem[]) => { + const currentGroupID = useConversationStore.getState().currentConversation?.groupID; + if (!isCheckInGroup || !currentGroupID) { + return list; + } + const tmpList = JSON.parse(JSON.stringify(list)) as CheckListItem[]; + const userIDList = tmpList + .filter((item) => Boolean(item.userID)) + .map((item) => item.userID!); + try { + const { data } = await IMSDK.getUsersInGroup({ + groupID: currentGroupID, + userIDList, + }); + tmpList.map((item) => { + item.disabled = data.includes(item.userID!); + }); + } catch (error) { + console.error(error); + } + return tmpList; + }; + + const menuClick = useCallback(async (idx: number) => { + const pushItem = { + title: "", + className: "text-xs text-[var(--primary)]", + }; + switch (idx) { + case 0: + setCheckList(await checkInGroup(useContactStore.getState().friendList)); + pushItem.title = t("placeholder.myFriend"); + break; + case 1: + setCheckList(await checkInGroup(useContactStore.getState().groupList)); + pushItem.title = t("placeholder.myGroup"); + break; + default: + break; + } + setBreadcrumb((state) => [...state, pushItem]); + }, []); + + if (breadcrumb.length < 1) { + return ( +
+ {menuList.map((menu) => ( + + ))} +
+ ); + } + + return ( +
+ +
+ ( + + )} + /> +
+
+ ); +}; + +const ForwardCommonLeft = memo(CommonLeft); + +interface IGroupMemberListProps { + checkMemberRole?: boolean; + checkClick: (data: CheckListItem) => void; + isChecked: (data: CheckListItem) => boolean; +} + +const GroupMemberList: FC = ({ + checkMemberRole, + checkClick, + isChecked, +}) => { + const { currentRolevel, currentMemberInGroup } = useCurrentMemberRole(); + const { fetchState, getMemberData, resetState } = useGroupMembers(); + + useEffect(() => { + if (currentMemberInGroup?.groupID) { + getMemberData(true); + } + return () => { + resetState(); + }; + }, [currentMemberInGroup?.groupID]); + + const endReached = () => { + if (fetchState.loading || !fetchState.hasMore) { + return; + } + getMemberData(); + }; + + const isDisabled = (member: GroupMemberItem) => { + if (member.userID === currentMemberInGroup?.userID) return true; + if (!checkMemberRole) return false; + return member.roleLevel >= currentRolevel; + }; + + return ( + + ( + + )} + /> + + ); +}; + +const ForwardMemberList = memo(GroupMemberList); diff --git a/pc-client/src/pages/common/ChooseModal/index.tsx b/pc-client/src/pages/common/ChooseModal/index.tsx new file mode 100644 index 0000000..67a4a5b --- /dev/null +++ b/pc-client/src/pages/common/ChooseModal/index.tsx @@ -0,0 +1,309 @@ +import { CloseOutlined } from "@ant-design/icons"; +import { GroupType, SessionType } from "@openim/wasm-client-sdk"; +import { Button, Input, Modal, Upload } from "antd"; +import clsx from "clsx"; +import i18n, { t } from "i18next"; +import { + FC, + forwardRef, + ForwardRefRenderFunction, + memo, + useEffect, + useRef, + useState, +} from "react"; + +import { message } from "@/AntdGlobalComp"; +import OIMAvatar from "@/components/OIMAvatar"; +import { useConversationToggle } from "@/hooks/useConversationToggle"; +import { OverlayVisibleHandle, useOverlayVisible } from "@/hooks/useOverlayVisible"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { FileWithPath } from "@/pages/chat/queryChat/ChatFooter/SendActionBar/useFileMessage"; +import { feedbackToast } from "@/utils/common"; +import { emit } from "@/utils/events"; +import { uploadFile } from "@/utils/imCommon"; + +import ChooseBox, { ChooseBoxHandle } from "./ChooseBox"; +import { CheckListItem } from "./ChooseBox/CheckItem"; + +export type ChooseModalType = + | "CRATE_GROUP" + | "INVITE_TO_GROUP" + | "KICK_FORM_GROUP" + | "TRANSFER_IN_GROUP" + | "SELECT_USER"; + +export interface SelectUserExtraData { + notConversation: boolean; + list: CheckListItem[]; +} + +export interface ChooseModalState { + type: ChooseModalType; + extraData?: unknown; +} + +interface IChooseModalProps { + state: ChooseModalState; +} + +const titleMap = { + CRATE_GROUP: t("placeholder.createGroup"), + INVITE_TO_GROUP: t("placeholder.invitation"), + KICK_FORM_GROUP: t("placeholder.kickMember"), + TRANSFER_IN_GROUP: t("placeholder.transferGroup"), + SELECT_USER: t("placeholder.selectUser"), +}; + +i18n.on("languageChanged", () => { + titleMap.CRATE_GROUP = t("placeholder.createGroup"); + titleMap.INVITE_TO_GROUP = t("placeholder.invitation"); + titleMap.KICK_FORM_GROUP = t("placeholder.kickMember"); + titleMap.TRANSFER_IN_GROUP = t("placeholder.transferGroup"); + titleMap.SELECT_USER = t("placeholder.selectUser"); +}); + +const onlyOneTypes = ["TRANSFER_IN_GROUP"]; +const onlyMemberTypes = ["KICK_FORM_GROUP", "TRANSFER_IN_GROUP"]; + +const ChooseModal: ForwardRefRenderFunction = ( + { state: { type, extraData } }, + ref, +) => { + const { isOverlayOpen, closeOverlay } = useOverlayVisible(ref); + + return ( + + + + ); +}; + +export default memo(forwardRef(ChooseModal)); + +type ChooseContactProps = { + isOverlayOpen: boolean; + type: ChooseModalType; + extraData?: unknown; + closeOverlay: () => void; +}; + +export const ChooseContact: FC = ({ + isOverlayOpen, + type, + extraData, + closeOverlay, +}) => { + const chooseBoxRef = useRef(null); + const [loading, setLoading] = useState(false); + const [groupBaseInfo, setGroupBaseInfo] = useState({ + groupName: "", + groupAvatar: "", + }); + + const { toSpecifiedConversation } = useConversationToggle(); + + useEffect(() => { + if (isOverlayOpen && type === "CRATE_GROUP" && extraData) { + setTimeout( + () => chooseBoxRef.current?.updatePrevCheckList(extraData as CheckListItem[]), + 100, + ); + } + if (isOverlayOpen && type === "SELECT_USER" && extraData) { + setTimeout( + () => + chooseBoxRef.current?.updatePrevCheckList( + (extraData as SelectUserExtraData).list, + ), + 100, + ); + } + if (!isOverlayOpen) resetState(); + }, [isOverlayOpen]); + + const confirmChoose = async () => { + const choosedList = chooseBoxRef.current?.getCheckedList() ?? []; + if (!choosedList?.length && type !== "SELECT_USER") + return message.warning(t("toast.selectLeastOne")); + + if (!groupBaseInfo.groupName.trim() && type === "CRATE_GROUP") + return message.warning(t("toast.inputGroupName")); + + setLoading(true); + try { + switch (type) { + case "CRATE_GROUP": + if (choosedList.length === 1) { + toSpecifiedConversation({ + sourceID: choosedList[0].userID!, + sessionType: SessionType.Single, + }); + break; + } + await IMSDK.createGroup({ + groupInfo: { + groupType: GroupType.WorkingGroup, + groupName: groupBaseInfo.groupName, + faceURL: groupBaseInfo.groupAvatar, + }, + memberUserIDs: choosedList.map((item) => item.userID!), + adminUserIDs: [], + }); + break; + case "INVITE_TO_GROUP": + await IMSDK.inviteUserToGroup({ + groupID: extraData as string, + userIDList: choosedList.map((item) => item.userID!), + reason: "", + }); + break; + case "KICK_FORM_GROUP": + await IMSDK.kickGroupMember({ + groupID: extraData as string, + userIDList: choosedList.map((item) => item.userID!), + reason: "", + }); + break; + case "TRANSFER_IN_GROUP": + await IMSDK.transferGroupOwner({ + groupID: extraData as string, + newOwnerUserID: choosedList[0].userID!, + }); + break; + case "SELECT_USER": + emit("SELECT_USER", { + notConversation: (extraData as SelectUserExtraData).notConversation, + choosedList, + }); + break; + default: + break; + } + } catch (error) { + feedbackToast({ error }); + } + setLoading(false); + closeOverlay(); + }; + + const resetState = () => { + chooseBoxRef.current?.resetState(); + setGroupBaseInfo({ + groupName: "", + groupAvatar: "", + }); + }; + + const customUpload = async ({ file }: { file: FileWithPath }) => { + try { + const { + data: { url }, + } = await uploadFile(file); + setGroupBaseInfo((prev) => ({ ...prev, groupAvatar: url })); + } catch (error) { + feedbackToast({ error: t("toast.updateAvatarFailed") }); + } + }; + + const isCheckInGroup = type === "INVITE_TO_GROUP"; + + return ( + <> +
+
{titleMap[type]}
+ +
+ {type === "CRATE_GROUP" ? ( +
+
+
{t("placeholder.groupName")}
+ + setGroupBaseInfo((state) => ({ ...state, groupName: e.target.value })) + } + /> +
+
+
+ {t("placeholder.groupAvatar")} +
+
+ + + + {t("placeholder.clickToModify")} + + +
+
+
+
+ {t("placeholder.groupMember")} +
+ +
+
+ ) : ( + + )} +
+ + +
+ + ); +}; diff --git a/pc-client/src/pages/common/GroupCardModal/index.tsx b/pc-client/src/pages/common/GroupCardModal/index.tsx new file mode 100644 index 0000000..f63b574 --- /dev/null +++ b/pc-client/src/pages/common/GroupCardModal/index.tsx @@ -0,0 +1,190 @@ +import { LeftOutlined } from "@ant-design/icons"; +import { GroupJoinSource, SessionType } from "@openim/wasm-client-sdk"; +import { GroupItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import { useRequest } from "ahooks"; +import { Button, Input } from "antd"; +import dayjs from "dayjs"; +import { t } from "i18next"; +import { forwardRef, ForwardRefRenderFunction, memo, useEffect, useState } from "react"; + +import clock from "@/assets/images/common/clock.png"; +import member_etc from "@/assets/images/common/member_etc.png"; +import DraggableModalWrap from "@/components/DraggableModalWrap"; +import OIMAvatar from "@/components/OIMAvatar"; +import { useConversationToggle } from "@/hooks/useConversationToggle"; +import useGroupMembers from "@/hooks/useGroupMembers"; +import { OverlayVisibleHandle, useOverlayVisible } from "@/hooks/useOverlayVisible"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { feedbackToast } from "@/utils/common"; + +interface IGroupCardModalProps { + groupData?: GroupItem & { inGroup?: boolean }; +} + +const GroupCardModal: ForwardRefRenderFunction< + OverlayVisibleHandle, + IGroupCardModalProps +> = ({ groupData }, ref) => { + const [reqMsg, setReqMsg] = useState(""); + const [isSendRequest, setIsSendRequest] = useState(false); + + const { fetchState, getMemberData, resetState } = useGroupMembers({ + groupID: groupData?.groupID, + }); + + const { toSpecifiedConversation } = useConversationToggle(); + const { isOverlayOpen, closeOverlay } = useOverlayVisible(ref); + + const { runAsync, loading } = useRequest(IMSDK.joinGroup, { + manual: true, + }); + + useEffect(() => { + if (isOverlayOpen) { + getMemberData(true); + } + }, [isOverlayOpen]); + + const createTimeStr = dayjs(groupData?.createTime ?? 0).format("YYYY/M/D"); + + const sliceNum = groupData?.memberCount === 8 ? 8 : 7; + const renderList = fetchState.groupMemberList.slice(0, sliceNum); + + const joinOrSendMessage = () => { + if (groupData?.inGroup) { + toSpecifiedConversation({ + sourceID: groupData.groupID, + sessionType: SessionType.WorkingGroup, + }); + closeOverlay(); + return; + } + + setIsSendRequest(true); + }; + + const sendApplication = async () => { + try { + await runAsync({ + groupID: groupData!.groupID, + reqMsg, + joinSource: GroupJoinSource.Search, + }); + feedbackToast({ msg: t("toast.sendJoinGroupRequestSuccess") }); + setIsSendRequest(false); + } catch (error) { + feedbackToast({ error, msg: t("toast.sendApplicationFailed") }); + } + }; + + return ( + +
+ {isSendRequest && ( +
setIsSendRequest(false)} + > + +
{t("placeholder.groupVerification")}
+
+ )} +
+ +
+
+ {groupData?.groupName} +
+
+
{`ID:${groupData?.groupID}`}
+
+ +
{createTimeStr}
+
+
+
+
+ {isSendRequest ? ( +
+
+ {t("application.information")} +
+
+ setReqMsg(e.target.value)} + className="bg-[var(--chat-bubble)] hover:bg-[var(--chat-bubble)]" + /> +
+
+ +
+
+ ) : ( +
+
{`${t("placeholder.groupMember")}:${ + groupData?.memberCount + }`}
+
+ {renderList.map((item) => ( + + ))} + {renderList.length === 7 && } +
+
+ +
+
+ )} +
+
+ ); +}; + +export default memo(forwardRef(GroupCardModal)); diff --git a/pc-client/src/pages/common/RtcCallModal/Counter.tsx b/pc-client/src/pages/common/RtcCallModal/Counter.tsx new file mode 100644 index 0000000..3d0d0e4 --- /dev/null +++ b/pc-client/src/pages/common/RtcCallModal/Counter.tsx @@ -0,0 +1,54 @@ +import { + forwardRef, + ForwardRefRenderFunction, + memo, + useEffect, + useImperativeHandle, + useRef, + useState, +} from "react"; + +import { secondsToMS } from "@/utils/common"; + +export type CounterHandle = { + getTimeStr: () => string; +}; +const Counter: ForwardRefRenderFunction< + CounterHandle, + { + isConnected: boolean; + className?: string; + } +> = ({ isConnected, className }, ref) => { + const [count, setCount] = useState(0); + const timer = useRef(null); + + useEffect(() => { + if (isConnected) { + countStart(); + } + return () => { + if (timer.current) { + clearInterval(timer.current); + } + }; + }, [isConnected]); + + const countStart = () => { + timer.current = setInterval(() => { + setCount((prev) => prev + 1); + }, 1000); + }; + + useImperativeHandle(ref, () => ({ + getTimeStr: () => secondsToMS(count), + })); + + return ( +
+
{secondsToMS(count)}
+
+ ); +}; + +export const ForwardCounter = memo(forwardRef(Counter)); diff --git a/pc-client/src/pages/common/RtcCallModal/RtcControl.tsx b/pc-client/src/pages/common/RtcCallModal/RtcControl.tsx new file mode 100644 index 0000000..c0feeb8 --- /dev/null +++ b/pc-client/src/pages/common/RtcCallModal/RtcControl.tsx @@ -0,0 +1,216 @@ +import { + TrackToggle, + useLocalParticipant, + useRoomContext, +} from "@livekit/components-react"; +import { CbEvents, MessageType } from "@openim/wasm-client-sdk"; +import { + MessageItem, + RtcInvite, + WSEvent, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import clsx from "clsx"; +import { t } from "i18next"; +import { RemoteParticipant, RoomEvent, Track } from "livekit-client"; +import { useEffect, useRef } from "react"; + +import { getRtcConnectData } from "@/api/imApi"; +import rtc_accept from "@/assets/images/rtc/rtc_accept.png"; +import rtc_camera from "@/assets/images/rtc/rtc_camera.png"; +import rtc_camera_off from "@/assets/images/rtc/rtc_camera_off.png"; +import rtc_hungup from "@/assets/images/rtc/rtc_hungup.png"; +import rtc_mic from "@/assets/images/rtc/rtc_mic.png"; +import rtc_mic_off from "@/assets/images/rtc/rtc_mic_off.png"; +import { CustomType } from "@/constants"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { useUserStore } from "@/store"; +import { feedbackToast } from "@/utils/common"; + +import { CounterHandle, ForwardCounter } from "./Counter"; +import { AuthData } from "./data"; + +interface IRtcControlProps { + isWaiting: boolean; + isRecv: boolean; + isConnected: boolean; + invitation: RtcInvite; + connectRtc: (data?: AuthData) => void; + closeOverlay: () => void; + sendCustomSignal: (recvID: string, customType: CustomType) => Promise; +} +export const RtcControl = ({ + isWaiting, + isRecv, + isConnected, + invitation, + connectRtc, + closeOverlay, + sendCustomSignal, +}: IRtcControlProps) => { + const room = useRoomContext(); + const localParticipantState = useLocalParticipant(); + const counterRef = useRef(null); + + const recvID = isRecv ? invitation.inviterUserID : invitation.inviteeUserIDList[0]; + const isVideoCall = invitation.mediaType === "video"; + + useEffect(() => { + const acceptHandler = async ({ roomID }: RtcInvite) => { + if (invitation.roomID !== roomID) return; + const { data } = await getRtcConnectData( + roomID, + useUserStore.getState().selfInfo.userID, + ); + connectRtc(data); + }; + const rejectHandler = ({ roomID }: RtcInvite) => { + if (invitation.roomID !== roomID) return; + closeOverlay(); + }; + const hangupHandler = ({ roomID }: RtcInvite) => { + if (invitation.roomID !== roomID) return; + room.disconnect(); + closeOverlay(); + }; + const cancelHandler = ({ roomID }: RtcInvite) => { + if (invitation.roomID !== roomID) return; + if (!isWaiting) return; + closeOverlay(); + }; + const participantDisconnectedHandler = (remoteParticipant: RemoteParticipant) => { + const identity = remoteParticipant.identity; + if ( + identity === invitation.inviterUserID || + identity === invitation.inviteeUserIDList[0] + ) { + room.disconnect(); + } + }; + + const newMessageHandler = ({ data }: WSEvent) => { + data.map((message) => { + if (message.contentType === MessageType.CustomMessage) { + const customData = JSON.parse(message.customElem!.data) as { + data: RtcInvite; + customType: CustomType; + }; + if (customData.customType === CustomType.CallingAccept) { + acceptHandler(customData.data); + } + if (customData.customType === CustomType.CallingReject) { + rejectHandler(customData.data); + } + if (customData.customType === CustomType.CallingCancel) { + cancelHandler(customData.data); + } + if (customData.customType === CustomType.CallingHungup) { + hangupHandler(customData.data); + } + } + }); + }; + + IMSDK.on(CbEvents.OnRecvNewMessages, newMessageHandler); + room.on(RoomEvent.ParticipantDisconnected, participantDisconnectedHandler); + return () => { + IMSDK.off(CbEvents.OnRecvNewMessages, newMessageHandler); + room.off(RoomEvent.ParticipantDisconnected, participantDisconnectedHandler); + }; + }, [room, invitation.roomID, isWaiting]); + + const hungup = () => { + if (isWaiting) { + const customType = isRecv ? CustomType.CallingReject : CustomType.CallingCancel; + sendCustomSignal(recvID, customType); + closeOverlay(); + return; + } + sendCustomSignal(recvID, CustomType.CallingHungup); + room.disconnect(); + }; + + const acceptInvitation = async () => { + try { + await sendCustomSignal(recvID, CustomType.CallingAccept); + const { data } = await getRtcConnectData( + invitation.roomID, + useUserStore.getState().selfInfo.userID, + ); + connectRtc(data); + } catch (error) { + feedbackToast({ msg: t("toast.byInviteUserFailed"), error }); + closeOverlay(); + } + }; + + return ( +
+ {!isWaiting && ( + + )} + {!isWaiting && ( + + + {t("placeholder.microphone")} + + )} +
+ + + {isWaiting ? t("cancel") : t("hangUp")} + +
+ {isRecv && isWaiting && ( +
+ + + {t("answer")} + +
+ )} + {!isWaiting && isVideoCall && ( + + + {t("placeholder.camera")} + + )} +
+ ); +}; diff --git a/pc-client/src/pages/common/RtcCallModal/RtcLayout.tsx b/pc-client/src/pages/common/RtcCallModal/RtcLayout.tsx new file mode 100644 index 0000000..28bef0f --- /dev/null +++ b/pc-client/src/pages/common/RtcCallModal/RtcLayout.tsx @@ -0,0 +1,150 @@ +import { + RoomAudioRenderer, + TrackLoop, + TrackRefContext, + useConnectionState, + useTracks, + VideoTrack, +} from "@livekit/components-react"; +import { PublicUserItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import { Spin } from "antd"; +import clsx from "clsx"; +import { + ConnectionState, + LocalParticipant, + Participant, + ParticipantEvent, + Track, +} from "livekit-client"; +import { useEffect, useState } from "react"; + +import OIMAvatar from "@/components/OIMAvatar"; +import { CustomType } from "@/constants"; + +import { AuthData, InviteData } from "./data"; +import { RtcControl } from "./RtcControl"; + +const localVideoClasses = + "absolute right-3 top-3 !w-[100px] !h-[150px] rounded-md z-10"; +const remoteVideoClasses = "absolute top-0 z-0"; + +interface IRtcLayoutProps { + connect: boolean; + isConnected: boolean; + isRecv: boolean; + inviteData?: InviteData; + closeOverlay: () => void; + sendCustomSignal: (recvID: string, customType: CustomType) => Promise; + connectRtc: (data?: AuthData) => void; +} +export const RtcLayout = ({ + connect, + isConnected, + isRecv, + inviteData, + connectRtc, + sendCustomSignal, + closeOverlay, +}: IRtcLayoutProps) => { + const isVideoCall = inviteData?.invitation?.mediaType === "video"; + const tracks = useTracks([Track.Source.Camera]); + const remoteParticipant = tracks.find((track) => !isLocal(track.participant)); + const isWaiting = !connect && !isConnected; + const [isRemoteVideoMuted, setIsRemoteVideoMuted] = useState(false); + + const connectState = useConnectionState(); + + useEffect(() => { + if (!remoteParticipant?.participant.identity) return; + const trackMuteUpdate = () => { + setIsRemoteVideoMuted(!remoteParticipant?.participant.isCameraEnabled); + }; + remoteParticipant?.participant.on(ParticipantEvent.TrackMuted, trackMuteUpdate); + remoteParticipant?.participant.on(ParticipantEvent.TrackUnmuted, trackMuteUpdate); + trackMuteUpdate(); + }, [remoteParticipant?.participant.identity]); + + const renderContent = () => { + if (!isWaiting && isVideoCall && !isRemoteVideoMuted) return null; + + return ( + + ); + }; + + return ( + +
+
+ {renderContent()} + +
+ {isConnected && ( + + + {(track) => + track && ( + + ) + } + + + )} +
+ +
+ ); +}; + +interface ISingleProfileProps { + isWaiting: boolean; + userInfo?: PublicUserItem; +} +const SingleProfile = ({ isWaiting, userInfo }: ISingleProfileProps) => { + return ( +
+ +
+ {userInfo?.nickname} +
+
+ ); +}; + +const isLocal = (p: Participant) => { + return p instanceof LocalParticipant; +}; diff --git a/pc-client/src/pages/common/RtcCallModal/data.ts b/pc-client/src/pages/common/RtcCallModal/data.ts new file mode 100644 index 0000000..8197943 --- /dev/null +++ b/pc-client/src/pages/common/RtcCallModal/data.ts @@ -0,0 +1,30 @@ +import { + GroupItem, + GroupMemberItem, + PublicUserItem, + RtcInvite, +} from "@openim/wasm-client-sdk/lib/types/entity"; + +export interface InviteData { + invitation?: RtcInvite; + participant?: ParticipantInfo; + isJoin?: boolean; +} + +export interface ParticipantInfo { + userInfo: PublicUserItem; + groupMemberInfo?: GroupMemberItem; + groupInfo?: GroupItem; +} + +export interface RtcInviteResults { + liveURL: string; + roomID: string; + token: string; + busyLineUserIDList?: string[]; +} + +export interface AuthData { + serverUrl: string; + token: string; +} diff --git a/pc-client/src/pages/common/RtcCallModal/index.tsx b/pc-client/src/pages/common/RtcCallModal/index.tsx new file mode 100644 index 0000000..3de5e3b --- /dev/null +++ b/pc-client/src/pages/common/RtcCallModal/index.tsx @@ -0,0 +1,169 @@ +import "@livekit/components-styles"; + +import { LiveKitRoom } from "@livekit/components-react"; +import { t } from "i18next"; +import { + forwardRef, + ForwardRefRenderFunction, + useCallback, + useEffect, + useRef, + useState, +} from "react"; + +import DraggableModalWrap from "@/components/DraggableModalWrap"; +import { CustomType } from "@/constants"; +import { OverlayVisibleHandle, useOverlayVisible } from "@/hooks/useOverlayVisible"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { useUserStore } from "@/store"; +import { feedbackToast } from "@/utils/common"; + +import { AuthData, InviteData } from "./data"; +import { RtcLayout } from "./RtcLayout"; + +interface IRtcCallModalProps { + inviteData: InviteData; +} + +const RtcCallModal: ForwardRefRenderFunction< + OverlayVisibleHandle, + IRtcCallModalProps +> = ({ inviteData }, ref) => { + const { invitation } = inviteData; + const [connect, setConnect] = useState(false); + const [isConnected, setIsConnected] = useState(false); + const [authData, setAuthData] = useState({ + serverUrl: "", + token: "", + }); + const selfID = useUserStore((state) => state.selfInfo.userID); + const { isOverlayOpen, closeOverlay } = useOverlayVisible(ref); + const timer = useRef(); + + const isRecv = selfID !== invitation?.inviterUserID; + + useEffect(() => { + if (!isOverlayOpen) return; + tryInvite(); + }, [isOverlayOpen, isRecv]); + + const checkTimeout = () => { + if (timer.current) clearTimer(); + timer.current = setTimeout(() => { + clearTimer(); + + if (!invitation) return; + + sendCustomSignal(invitation?.inviteeUserIDList[0], CustomType.CallingCancel); + closeOverlay(); + }, (invitation?.timeout ?? 30) * 1000); + }; + + const clearTimer = useCallback(() => clearTimeout(timer.current), []); + + const closeOverlayAndClearTimer = useCallback(() => { + clearTimer(); + closeOverlay(); + }, []); + + const sendCustomSignal = useCallback( + async (recvID: string, customType: CustomType) => { + const data = { + customType, + data: { + ...invitation, + }, + }; + const { data: message } = await IMSDK.createCustomMessage({ + data: JSON.stringify(data), + extension: "", + description: "", + }); + await IMSDK.sendMessage({ + recvID, + message, + groupID: "", + isOnlineOnly: true, + }); + }, + [invitation?.roomID], + ); + + const tryInvite = async () => { + if (!isRecv) { + try { + await sendCustomSignal( + invitation.inviteeUserIDList[0], + CustomType.CallingInvite, + ); + checkTimeout(); + } catch (error) { + feedbackToast({ msg: t("toast.inviteUserFailed"), error }); + closeOverlay(); + } + } + }; + + const connectRtc = useCallback((data?: AuthData) => { + if (data) { + setAuthData(data); + } + clearTimer(); + setTimeout(() => setConnect(true)); + }, []); + + return ( + +
+ {isOverlayOpen && ( + setIsConnected(true)} + onDisconnected={() => { + closeOverlayAndClearTimer(); + setIsConnected(false); + setConnect(false); + }} + > + + + )} +
+
+ ); +}; + +export default forwardRef(RtcCallModal); diff --git a/pc-client/src/pages/common/UserCardModal/EditSelfInfo.tsx b/pc-client/src/pages/common/UserCardModal/EditSelfInfo.tsx new file mode 100644 index 0000000..119d56a --- /dev/null +++ b/pc-client/src/pages/common/UserCardModal/EditSelfInfo.tsx @@ -0,0 +1,137 @@ +import { Button, DatePicker, Form, Input, Modal, Select } from "antd"; +import dayjs, { Dayjs } from "dayjs"; +import { t } from "i18next"; +import { forwardRef, ForwardRefRenderFunction, memo } from "react"; +import { useMutation } from "react-query"; + +import { errorHandle } from "@/api/errorHandle"; +import { BusinessUserInfo, updateBusinessUserInfo } from "@/api/login"; +import { OverlayVisibleHandle, useOverlayVisible } from "@/hooks/useOverlayVisible"; +import { useUserStore } from "@/store"; + +const EditSelfInfo: ForwardRefRenderFunction< + OverlayVisibleHandle, + { refreshSelfInfo: () => void } +> = ({ refreshSelfInfo }, ref) => { + const [form] = Form.useForm(); + const selfInfo = useUserStore((state) => state.selfInfo); + const updateSelfInfo = useUserStore((state) => state.updateSelfInfo); + + const { isOverlayOpen, closeOverlay } = useOverlayVisible(ref); + + const { isLoading, mutate } = useMutation(updateBusinessUserInfo, { + onError: errorHandle, + }); + + const onFinish = (value: BusinessUserInfo & { birth: Dayjs }) => { + const options = { + nickname: value.nickname, + email: value.email, + gender: value.gender, + birth: value.birth.unix() * 1000, + }; + mutate(options, { + onSuccess: () => { + updateSelfInfo(options); + refreshSelfInfo(); + closeOverlay(); + }, + }); + }; + + return ( + +
+
+ {t("placeholder.editInfo")} +
+ {isOverlayOpen && ( +
+ + + + + + + + + + + + + + + + current && current > dayjs().endOf("day")} + /> + + + +
+ + +
+
+
+ )} +
+
+ ); +}; + +export default memo(forwardRef(EditSelfInfo)); diff --git a/pc-client/src/pages/common/UserCardModal/SendRequest.tsx b/pc-client/src/pages/common/UserCardModal/SendRequest.tsx new file mode 100644 index 0000000..13db253 --- /dev/null +++ b/pc-client/src/pages/common/UserCardModal/SendRequest.tsx @@ -0,0 +1,99 @@ +import { LeftOutlined } from "@ant-design/icons"; +import { useRequest } from "ahooks"; +import { Button, Input } from "antd"; +import { t } from "i18next"; +import { useState } from "react"; + +import OIMAvatar from "@/components/OIMAvatar"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { feedbackToast } from "@/utils/common"; + +import { CardInfo } from "."; + +const SendRequest = ({ + cardInfo, + backToCard, +}: { + cardInfo: CardInfo; + backToCard: () => void; +}) => { + const [reqMsg, setReqMsg] = useState(""); + const { runAsync, loading } = useRequest(IMSDK.addFriend, { + manual: true, + }); + + const sendApplication = async () => { + try { + await runAsync({ + toUserID: cardInfo.userID!, + reqMsg, + }); + feedbackToast({ msg: t("toast.sendFreiendRequestSuccess") }); + } catch (error) { + feedbackToast({ error, msg: t("toast.sendApplicationFailed") }); + } + backToCard(); + }; + + return ( +
+
+
+ +
{t("placeholder.friendVerification")}
+
+
+
+
+ +
+
+ {cardInfo?.nickname} +
+
+ {cardInfo?.userID} +
+
+
+
+
+ {t("application.information")} +
+
+ setReqMsg(e.target.value)} + className="bg-[var(--chat-bubble)] hover:bg-[var(--chat-bubble)]" + /> +
+
+
+ +
+
+
+ ); +}; + +export default SendRequest; diff --git a/pc-client/src/pages/common/UserCardModal/index.tsx b/pc-client/src/pages/common/UserCardModal/index.tsx new file mode 100644 index 0000000..b2b96ee --- /dev/null +++ b/pc-client/src/pages/common/UserCardModal/index.tsx @@ -0,0 +1,369 @@ +import { CbEvents } from "@openim/wasm-client-sdk"; +import { SessionType } from "@openim/wasm-client-sdk"; +import { + FriendUserItem, + GroupMemberItem, + WSEvent, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import { useLatest } from "ahooks"; +import { Button, Divider, Spin } from "antd"; +import dayjs from "dayjs"; +import { t } from "i18next"; +import { + FC, + forwardRef, + ForwardRefRenderFunction, + memo, + useCallback, + useEffect, + useRef, + useState, +} from "react"; +import { useQuery } from "react-query"; +import { useCopyToClipboard } from "react-use"; + +import { BusinessUserInfo, getBusinessUserInfo } from "@/api/login"; +import DraggableModalWrap from "@/components/DraggableModalWrap"; +import EditableContent from "@/components/EditableContent"; +import OIMAvatar from "@/components/OIMAvatar"; +import { useConversationToggle } from "@/hooks/useConversationToggle"; +import { OverlayVisibleHandle, useOverlayVisible } from "@/hooks/useOverlayVisible"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { useContactStore, useUserStore } from "@/store"; +import { feedbackToast } from "@/utils/common"; + +import EditSelfInfo from "./EditSelfInfo"; +import SendRequest from "./SendRequest"; + +interface IUserCardModalProps { + userID?: string; + groupID?: string; + isSelf?: boolean; + notAdd?: boolean; + cardInfo?: CardInfo; +} + +export type CardInfo = Partial; + +const getGender = (gender: number) => { + if (!gender) return "-"; + return gender === 1 ? t("placeholder.man") : t("placeholder.female"); +}; + +const UserCardModal: ForwardRefRenderFunction< + OverlayVisibleHandle, + IUserCardModalProps +> = (props, ref) => { + const { userID, isSelf, notAdd } = props; + + const editInfoRef = useRef(null); + const [cardInfo, setCardInfo] = useState(); + const [isSendRequest, setIsSendRequest] = useState(false); + const [userFields, setUserFields] = useState([]); + + const selfInfo = useUserStore((state) => state.selfInfo); + const isFriendUser = useContactStore( + (state) => state.friendList.findIndex((item) => item.userID === userID) !== -1, + ); + + const { isOverlayOpen, closeOverlay } = useOverlayVisible(ref); + const { toSpecifiedConversation } = useConversationToggle(); + const [_, copyToClipboard] = useCopyToClipboard(); + + const getCardInfo = async (): Promise<{ + cardInfo: CardInfo; + memberInfo?: GroupMemberItem | null; + }> => { + if (isSelf) { + return { + cardInfo: selfInfo, + }; + } + let userInfo: CardInfo | null = null; + const friendInfo = useContactStore + .getState() + .friendList.find((item) => item.userID === userID); + if (friendInfo) { + userInfo = { ...friendInfo }; + } else { + const { data } = await IMSDK.getUsersInfo([userID!]); + userInfo = { ...(data[0] ?? {}) }; + } + + try { + const { + data: { users }, + } = await getBusinessUserInfo([userID!]); + userInfo = { ...userInfo, ...users[0] }; + } catch (error) { + console.error("get business user info failed", userID, error); + } + return { + cardInfo: userInfo, + }; + }; + + const refreshData = (data?: { cardInfo: CardInfo | null }) => { + if (!data) { + return; + } + const { cardInfo } = data; + + setCardInfo(cardInfo!); + setUserInfoRow(cardInfo!); + }; + + const { + data: fullCardInfo, + isLoading, + refetch, + } = useQuery(["userInfo", userID], getCardInfo, { + enabled: isOverlayOpen && Boolean(userID), + onSuccess: refreshData, + }); + + const latestFullCardInfo = useLatest(fullCardInfo); + + useEffect(() => { + if (!isOverlayOpen) return; + const friendAddedHandler = ({ data }: WSEvent) => { + if (data.userID === userID) { + refetch(); + } + }; + IMSDK.on(CbEvents.OnFriendAdded, friendAddedHandler); + refreshData( + props.cardInfo ? { cardInfo: props.cardInfo } : latestFullCardInfo.current, + ); + return () => { + IMSDK.off(CbEvents.OnFriendAdded, friendAddedHandler); + }; + }, [isOverlayOpen, props.cardInfo]); + + const refreshSelfInfo = useCallback(() => { + const latestInfo = useUserStore.getState().selfInfo; + setCardInfo(latestInfo); + setUserInfoRow(latestInfo); + }, [isSelf]); + + const updateCardRemark = (remark: string) => { + setUserInfoRow({ ...cardInfo!, remark }); + }; + const setUserInfoRow = (info: CardInfo) => { + let tmpFields = [] as FieldRow[]; + tmpFields.push({ + title: t("placeholder.nickName"), + value: info.nickname || "", + }); + const isFriend = info?.remark !== undefined; + + if (isFriend) { + tmpFields.push({ + title: t("placeholder.remark"), + value: info.remark || "-", + editable: true, + }); + } + if (isFriend || isSelf) { + tmpFields = [ + ...tmpFields, + ...[ + { + title: t("placeholder.gender"), + value: getGender(info.gender!), + }, + { + title: t("placeholder.birth"), + value: info.birth ? dayjs(info.birth).format("YYYY/M/D") : "-", + }, + { + title: t("placeholder.phoneNumber"), + value: info.phoneNumber || "-", + }, + { + title: t("placeholder.email"), + value: info.email || "-", + }, + ], + ]; + } + setUserFields(tmpFields); + }; + + const backToCard = () => { + setIsSendRequest(false); + }; + + const trySendRequest = () => { + setIsSendRequest(true); + }; + + const resetState = () => { + setCardInfo(undefined); + setUserFields([]); + setIsSendRequest(false); + }; + + const showAddFriend = !isFriendUser && !isSelf && !notAdd; + + return ( + + + {isSendRequest ? ( + + ) : ( +
+
+
+
+ +
+
+
+ {cardInfo?.nickname} +
+
+
+
{ + copyToClipboard(cardInfo?.userID ?? ""); + feedbackToast({ msg: t("toast.copySuccess") }); + }} + > + {cardInfo?.userID} +
+
+
+
+
+ +
+
+
+ {showAddFriend && ( + + )} + {isSelf && ( + + )} + {!isSelf && ( + + )} +
+
+ )} + + + + ); +}; + +export default memo(forwardRef(UserCardModal)); + +interface IUserCardDataGroupProps { + title: string; + userID?: string; + divider?: boolean; + fieldRows: FieldRow[]; + updateCardRemark?: (remark: string) => void; +} + +type FieldRow = { + title: string; + value: string; + editable?: boolean; +}; + +const UserCardDataGroup: FC = ({ + title, + userID, + divider, + fieldRows, + updateCardRemark, +}) => { + const tryUpdateRemark = async (remark: string) => { + try { + await IMSDK.updateFriends({ + friendUserIDs: [userID!], + remark, + }); + updateCardRemark?.(remark); + } catch (error) { + feedbackToast({ error }); + } + }; + return ( +
+
{title}
+ {fieldRows.map((fieldRow, idx) => ( +
+
{fieldRow.title}
+ {fieldRow.editable ? ( + + ) : ( +
{fieldRow.value}
+ )} +
+ ))} + + {divider && } +
+ ); +}; diff --git a/pc-client/src/pages/contact/ContactSider.tsx b/pc-client/src/pages/contact/ContactSider.tsx new file mode 100644 index 0000000..55b9461 --- /dev/null +++ b/pc-client/src/pages/contact/ContactSider.tsx @@ -0,0 +1,117 @@ +import { Badge } from "antd"; +import clsx from "clsx"; +import i18n, { t } from "i18next"; +import { useEffect, useState } from "react"; +import { useNavigate } from "react-router-dom"; + +import group_notifications from "@/assets/images/contact/group_notifications.png"; +import my_friends from "@/assets/images/contact/my_friends.png"; +import my_groups from "@/assets/images/contact/my_groups.png"; +import new_friends from "@/assets/images/contact/new_friends.png"; +import FlexibleSider from "@/components/FlexibleSider"; +import { useContactStore } from "@/store"; + +const Links = [ + { + label: t("placeholder.newFriends"), + icon: new_friends, + path: "/contact/newFriends", + }, + { + label: t("placeholder.groupNotification"), + icon: group_notifications, + path: "/contact/groupNotifications", + }, + { + label: t("placeholder.myFriend"), + icon: my_friends, + path: "/contact", + }, + { + label: t("placeholder.myGroup"), + icon: my_groups, + path: "/contact/myGroups", + }, +]; + +i18n.on("languageChanged", () => { + Links[0].label = t("placeholder.newFriends"); + Links[1].label = t("placeholder.groupNotification"); + Links[2].label = t("placeholder.myFriend"); + Links[3].label = t("placeholder.myGroup"); +}); + +const ContactSider = () => { + const [selectIndex, setSelectIndex] = useState(2); + const unHandleFriendApplicationCount = useContactStore( + (state) => state.unHandleFriendApplicationCount, + ); + const unHandleGroupApplicationCount = useContactStore( + (state) => state.unHandleGroupApplicationCount, + ); + const navigate = useNavigate(); + + useEffect(() => { + if (location.hash.includes("/contact/newFriends")) { + setSelectIndex(0); + } + if (location.hash.includes("/contact/groupNotifications")) { + setSelectIndex(1); + } + if (location.hash.includes("/contact/myGroups")) { + setSelectIndex(3); + } + }, []); + + const getBadge = (index: number) => { + if (index === 0) { + return unHandleFriendApplicationCount; + } + if (index === 1) { + return unHandleGroupApplicationCount; + } + return 0; + }; + + return ( + +
+
{t("placeholder.contact")}
+
+
+
    + {Links.map((item, index) => { + return ( +
  • { + setSelectIndex(index); + navigate(String(item.path)); + }} + > + + {item.label} + +
    {item.label}
    +
  • + ); + })} +
+
+
+ ); +}; +export default ContactSider; diff --git a/pc-client/src/pages/contact/groupNotifications/index.tsx b/pc-client/src/pages/contact/groupNotifications/index.tsx new file mode 100644 index 0000000..a2f5008 --- /dev/null +++ b/pc-client/src/pages/contact/groupNotifications/index.tsx @@ -0,0 +1,116 @@ +import { ApplicationHandleResult } from "@openim/wasm-client-sdk"; +import { GroupApplicationItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import { useCallback } from "react"; +import { useTranslation } from "react-i18next"; +import { Virtuoso } from "react-virtuoso"; + +import ApplicationItem, { AccessFunction } from "@/components/ApplicationItem"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { useUserStore } from "@/store"; +import { useContactStore } from "@/store/contact"; +import { feedbackToast } from "@/utils/common"; + +export const GroupNotifications = () => { + const { t } = useTranslation(); + const currentUserID = useUserStore((state) => state.selfInfo.userID); + + const recvGroupApplicationList = useContactStore( + (state) => state.recvGroupApplicationList, + ); + const sendGroupApplicationList = useContactStore( + (state) => state.sendGroupApplicationList, + ); + const updateRecvGroupApplication = useContactStore( + (state) => state.updateRecvGroupApplication, + ); + const updateSendGroupApplication = useContactStore( + (state) => state.updateSendGroupApplication, + ); + + const groupApplicationList = sortArray( + recvGroupApplicationList.concat(sendGroupApplicationList), + ); + + const onAccept = useCallback( + async (application: GroupApplicationItem, isRecv: boolean) => { + try { + await IMSDK.acceptGroupApplication({ + groupID: application.groupID, + fromUserID: application.userID, + handleMsg: "", + }); + const newApplication = { + ...application, + handleResult: ApplicationHandleResult.Agree, + }; + if (isRecv) { + updateRecvGroupApplication(newApplication); + } else { + updateSendGroupApplication(newApplication); + } + } catch (error) { + feedbackToast({ error }); + } + }, + [], + ); + + const onReject = useCallback( + async (application: GroupApplicationItem, isRecv: boolean) => { + try { + await IMSDK.refuseGroupApplication({ + groupID: application.groupID, + fromUserID: application.userID, + handleMsg: "", + }); + const newApplication = { + ...application, + handleResult: ApplicationHandleResult.Reject, + }; + if (isRecv) { + updateRecvGroupApplication(newApplication); + } else { + updateSendGroupApplication(newApplication); + } + } catch (error) { + feedbackToast({ error }); + } + }, + [], + ); + + return ( +
+

+ {t("placeholder.groupNotification")} +

+
+ ( + + )} + /> +
+
+ ); +}; + +const sortArray = (list: GroupApplicationItem[]) => { + list.sort((a, b) => { + if (a.handleResult === 0 && b.handleResult !== 0) { + return -1; + } else if (b.handleResult === 0 && a.handleResult !== 0) { + return 1; + } + return b.reqTime - a.reqTime; + }); + return list; +}; diff --git a/pc-client/src/pages/contact/index.tsx b/pc-client/src/pages/contact/index.tsx new file mode 100644 index 0000000..3630279 --- /dev/null +++ b/pc-client/src/pages/contact/index.tsx @@ -0,0 +1,13 @@ +import { Layout } from "antd"; +import { Outlet } from "react-router-dom"; + +import ContactSider from "@/pages/contact/ContactSider"; + +export const Contact = () => { + return ( + + + + + ); +}; diff --git a/pc-client/src/pages/contact/myFriends/AlphabetIndex.tsx b/pc-client/src/pages/contact/myFriends/AlphabetIndex.tsx new file mode 100644 index 0000000..5019bca --- /dev/null +++ b/pc-client/src/pages/contact/myFriends/AlphabetIndex.tsx @@ -0,0 +1,51 @@ +import clsx from "clsx"; +import { + forwardRef, + ForwardRefRenderFunction, + memo, + useImperativeHandle, + useState, +} from "react"; + +type IAlphabetIndexProps = { + indexList: string[]; + scrollToLetter: (idx: number) => void; +}; + +const AlphabetIndex: ForwardRefRenderFunction< + { updateCurrentLetter: (letter: string) => void }, + IAlphabetIndexProps +> = ({ indexList, scrollToLetter }, ref) => { + const [currentAlphabet, setCurrentAlphabet] = useState(""); + + const jumpToLetter = (idx: number, letter: string) => { + scrollToLetter(idx); + setCurrentAlphabet(letter); + }; + + useImperativeHandle( + ref, + () => ({ + updateCurrentLetter: (letter: string) => setCurrentAlphabet(letter), + }), + [], + ); + + return ( +
+ {indexList.map((letter, idx) => ( + jumpToLetter(idx, letter)} + > + {letter} + + ))} +
+ ); +}; + +export default memo(forwardRef(AlphabetIndex)); diff --git a/pc-client/src/pages/contact/myFriends/FriendListItem.tsx b/pc-client/src/pages/contact/myFriends/FriendListItem.tsx new file mode 100644 index 0000000..b43597e --- /dev/null +++ b/pc-client/src/pages/contact/myFriends/FriendListItem.tsx @@ -0,0 +1,23 @@ +import { FriendUserItem } from "@openim/wasm-client-sdk/lib/types/entity"; + +import OIMAvatar from "@/components/OIMAvatar"; + +const FriendListItem = ({ + friend, + showUserCard, +}: { + friend: FriendUserItem; + showUserCard: (userID: string) => void; +}) => { + return ( +
showUserCard(friend.userID)} + > + +
{friend.remark || friend.nickname}
+
+ ); +}; + +export default FriendListItem; diff --git a/pc-client/src/pages/contact/myFriends/index.tsx b/pc-client/src/pages/contact/myFriends/index.tsx new file mode 100644 index 0000000..fe9a9e4 --- /dev/null +++ b/pc-client/src/pages/contact/myFriends/index.tsx @@ -0,0 +1,115 @@ +import { useRequest } from "ahooks"; +import { Empty, Spin } from "antd"; +import { useCallback, useEffect, useRef } from "react"; +import { useTranslation } from "react-i18next"; +import { GroupedVirtuoso, GroupedVirtuosoHandle } from "react-virtuoso"; + +import { useContactStore } from "@/store"; +import { formatContactsByWorker } from "@/utils/contactsFormat"; +import { emit } from "@/utils/events"; + +import AlphabetIndex from "./AlphabetIndex"; +import FriendListItem from "./FriendListItem"; + +export const MyFriends = () => { + const { t } = useTranslation(); + const friendList = useContactStore((state) => state.friendList); + const virtuoso = useRef(null); + const alphabetRef = useRef<{ updateCurrentLetter: (letter: string) => void }>(null); + + const { data: sectionData, cancel } = useRequest( + () => formatContactsByWorker(friendList), + { + refreshDeps: [friendList], + }, + ); + + useEffect(() => { + return () => { + cancel(); + }; + }, []); + + const scrollToLetter = useCallback( + (idx: number) => { + const prevNum = sectionData?.groupCounts.slice(0, idx).reduce((a, b) => a + b, 0); + console.log(prevNum); + + virtuoso.current?.scrollToIndex({ + index: prevNum ?? 0, + // behavior: "smooth", + }); + }, + [sectionData?.groupCounts], + ); + + const showUserCard = useCallback((userID: string) => { + emit("OPEN_USER_CARD", { + userID, + }); + }, []); + + const determineCurrentGroup = (startIndex: number) => { + if (!sectionData) return; + + let currentItemIndex = 0; + + for ( + let groupIndex = 0; + groupIndex < sectionData.groupCounts.length; + groupIndex++ + ) { + const groupItemCount = sectionData.groupCounts[groupIndex]; + + if (startIndex < currentItemIndex + groupItemCount) { + alphabetRef.current?.updateCurrentLetter(sectionData.indexList[groupIndex]); + break; + } + + currentItemIndex += groupItemCount; + } + }; + + return ( +
+
{t("placeholder.myFriend")}
+ {!sectionData ? ( + + ) : !sectionData.groupCounts.length ? ( + + ) : ( +
+ + + ( +
+
+ {sectionData.indexList[index]} +
+
+
+ )} + itemContent={(index) => { + return ( + + ); + }} + rangeChanged={({ startIndex }) => determineCurrentGroup(startIndex)} + className="no-scrollbar h-full overflow-x-hidden" + /> +
+ )} +
+ ); +}; diff --git a/pc-client/src/pages/contact/myGroups/GroupListItem.tsx b/pc-client/src/pages/contact/myGroups/GroupListItem.tsx new file mode 100644 index 0000000..3881292 --- /dev/null +++ b/pc-client/src/pages/contact/myGroups/GroupListItem.tsx @@ -0,0 +1,26 @@ +import { GroupItem } from "@openim/wasm-client-sdk/lib/types/entity"; + +import OIMAvatar from "@/components/OIMAvatar"; + +const GroupListItem = ({ + source, + showGroupCard, +}: { + source: GroupItem; + showGroupCard: (group: GroupItem) => void; +}) => { + return ( +
showGroupCard(source)} + > + +
+

{source.groupName}

+

{source.memberCount}

+
+
+ ); +}; + +export default GroupListItem; diff --git a/pc-client/src/pages/contact/myGroups/index.tsx b/pc-client/src/pages/contact/myGroups/index.tsx new file mode 100644 index 0000000..40aa07c --- /dev/null +++ b/pc-client/src/pages/contact/myGroups/index.tsx @@ -0,0 +1,77 @@ +import { GroupItem } from "@openim/wasm-client-sdk/lib/types/entity"; +import { Select } from "antd"; +import { useCallback, useState } from "react"; +import { useTranslation } from "react-i18next"; +import { Virtuoso } from "react-virtuoso"; + +import { useContactStore, useUserStore } from "@/store"; +import { emit } from "@/utils/events"; + +import GroupListItem from "./GroupListItem"; + +export enum GroupTypeEnum { + JoinedGroup, + CreatedGroup, +} + +export const MyGroups = () => { + const { t } = useTranslation(); + const [selectGroup, setSelectGroup] = useState(GroupTypeEnum.CreatedGroup); + + const joinedGroupList = useContactStore((state) => state.groupList); + const { userID } = useUserStore((state) => state.selfInfo); + + const handleChange = (value: string) => { + setSelectGroup(Number(value)); + }; + + const filterGroup = joinedGroupList.filter((group) => { + if (selectGroup === GroupTypeEnum.JoinedGroup) { + return group.creatorUserID !== userID; + } else if (selectGroup === GroupTypeEnum.CreatedGroup) { + return group.creatorUserID === userID; + } + return false; + }); + + const showGroupCard = useCallback((group: GroupItem) => { + emit("OPEN_GROUP_CARD", group); + }, []); + + return ( +
+
+

{t("placeholder.myGroup")}

+ + + + + + + + + + + + + ); +}; + +export default LoginForm; diff --git a/pc-client/src/pages/login/index.module.scss b/pc-client/src/pages/login/index.module.scss new file mode 100644 index 0000000..dce3103 --- /dev/null +++ b/pc-client/src/pages/login/index.module.scss @@ -0,0 +1,18 @@ +.login { + :global { + .ant-form-item-label { + padding: 0; + } + } +} + +.login-method-tab { + :global { + .ant-tabs-nav { + margin: 24px 0 12px 0; + } + .ant-tabs-tab { + padding: 6px 0; + } + } +} diff --git a/pc-client/src/pages/login/index.tsx b/pc-client/src/pages/login/index.tsx new file mode 100644 index 0000000..2c5b4c6 --- /dev/null +++ b/pc-client/src/pages/login/index.tsx @@ -0,0 +1,55 @@ +import { t } from "i18next"; +import { useCopyToClipboard } from "react-use"; + +import login_bg from "@/assets/images/login/login_bg.png"; +import WindowControlBar from "@/components/WindowControlBar"; +import { APP_NAME, APP_VERSION, SDK_VERSION } from "@/config"; +import { feedbackToast } from "@/utils/common"; + +import styles from "./index.module.scss"; +import LoginForm from "./LoginForm"; + +export const Login = () => { + const [_, copyToClipboard] = useCopyToClipboard(); + + const handleCopy = () => { + copyToClipboard(`${`${APP_NAME} ${APP_VERSION}`}/${SDK_VERSION}`); + feedbackToast({ msg: t("toast.copySuccess") }); + }; + + return ( +
+
+ +
+
+ +
+ +
+
+
+
{`${APP_NAME} ${APP_VERSION}`}
+
{SDK_VERSION}
+
+
+ ); +}; + +const LeftBar = () => { + return ( +
+
+
{t("placeholder.title")}
+ {t("placeholder.subTitle")} + login_bg +
+
+ ); +}; diff --git a/pc-client/src/processShim.ts b/pc-client/src/processShim.ts new file mode 100644 index 0000000..243c7ee --- /dev/null +++ b/pc-client/src/processShim.ts @@ -0,0 +1,9 @@ +// 部分依赖(如 react-draggable)在模块加载时会读取 process.env, +// 而浏览器环境下 OpenIM SDK 注入的 process 对象可能没有 env,导致白屏。 +// 这里在最前面补齐,保证渲染进程(web 预览)也能正常运行。 +const w = window as unknown as { process?: { env?: Record } }; +if (typeof w.process !== "undefined" && !w.process.env) { + w.process.env = {}; +} + +export {}; diff --git a/pc-client/src/routes/ContactRoutes.ts b/pc-client/src/routes/ContactRoutes.ts new file mode 100644 index 0000000..6a3a71a --- /dev/null +++ b/pc-client/src/routes/ContactRoutes.ts @@ -0,0 +1,32 @@ +const contactRoutes = [ + { + path: "groupNotifications", + async lazy() { + const { GroupNotifications } = await import("@/pages/contact/groupNotifications"); + return { Component: GroupNotifications }; + }, + }, + { + index: true, + async lazy() { + const { MyFriends } = await import("@/pages/contact/myFriends"); + return { Component: MyFriends }; + }, + }, + { + path: "myGroups", + async lazy() { + const { MyGroups } = await import("@/pages/contact/myGroups"); + return { Component: MyGroups }; + }, + }, + { + path: "newFriends", + async lazy() { + const { NewFriends } = await import("@/pages/contact/newFriends"); + return { Component: NewFriends }; + }, + }, +]; + +export default contactRoutes; diff --git a/pc-client/src/routes/GlobalErrorElement.tsx b/pc-client/src/routes/GlobalErrorElement.tsx new file mode 100644 index 0000000..2e8107b --- /dev/null +++ b/pc-client/src/routes/GlobalErrorElement.tsx @@ -0,0 +1,30 @@ +import { Button, Result } from "antd"; +import { t } from "i18next"; +import { useRouteError } from "react-router-dom"; + +const GlobalErrorElement = () => { + const error = useRouteError(); + + const reload = () => { + window.location.reload(); + }; + + console.error("GlobalErrorElement"); + console.error(error); + + return ( +
+ + {t("placeholder.recover")} + + } + /> +
+ ); +}; + +export default GlobalErrorElement; diff --git a/pc-client/src/routes/index.tsx b/pc-client/src/routes/index.tsx new file mode 100644 index 0000000..d6a402e --- /dev/null +++ b/pc-client/src/routes/index.tsx @@ -0,0 +1,59 @@ +import { createHashRouter } from "react-router-dom"; + +import { MainContentLayout } from "@/layout/MainContentLayout"; +import { MainContentWrap } from "@/layout/MainContentWrap"; +import { EmptyChat } from "@/pages/chat/EmptyChat"; +import { QueryChat } from "@/pages/chat/queryChat"; + +import contactRoutes from "./ContactRoutes"; +import GlobalErrorElement from "./GlobalErrorElement"; + +const router = createHashRouter([ + { + path: "/", + element: , + errorElement: , + children: [ + { + path: "/", + element: , + children: [ + { + path: "/chat", + async lazy() { + const { Chat } = await import("@/pages/chat"); + return { Component: Chat }; + }, + children: [ + { + index: true, + element: , + }, + { + path: ":conversationID", + element: , + }, + ], + }, + { + path: "contact", + async lazy() { + const { Contact } = await import("@/pages/contact"); + return { Component: Contact }; + }, + children: contactRoutes, + }, + ], + }, + { + path: "login", + async lazy() { + const { Login } = await import("@/pages/login"); + return { Component: Login }; + }, + }, + ], + }, +]); + +export default router; diff --git a/pc-client/src/store/contact.ts b/pc-client/src/store/contact.ts new file mode 100644 index 0000000..0f6ce51 --- /dev/null +++ b/pc-client/src/store/contact.ts @@ -0,0 +1,252 @@ +import { ApplicationHandleResult } from "@openim/wasm-client-sdk"; +import { + BlackUserItem, + FriendApplicationItem, + FriendUserItem, + GroupApplicationItem, + GroupItem, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import { t } from "i18next"; +import { create } from "zustand"; + +import { IMSDK } from "@/layout/MainContentWrap"; +import { feedbackToast } from "@/utils/common"; + +import { ContactStore } from "./type"; + +export const useContactStore = create()((set, get) => ({ + friendList: [], + blackList: [], + groupList: [], + recvFriendApplicationList: [], + sendFriendApplicationList: [], + recvGroupApplicationList: [], + sendGroupApplicationList: [], + unHandleFriendApplicationCount: 0, + unHandleGroupApplicationCount: 0, + getFriendListByReq: async () => { + try { + let offset = 0; + let tmpList = [] as FriendUserItem[]; + let initialFetch = true; + // eslint-disable-next-line + while (true) { + const count = initialFetch ? 10000 : 1000; + const { data } = await IMSDK.getFriendListPage({ + offset, + count, + filterBlack: true, + }); + tmpList = [...tmpList, ...data]; + offset += count; + if (data.length < count) break; + initialFetch = false; + } + set(() => ({ + friendList: [...tmpList], + })); + } catch (error) { + feedbackToast({ error, msg: t("toast.getFriendListFailed") }); + } + }, + setFriendList: (list: FriendUserItem[]) => { + set(() => ({ friendList: list })); + }, + updateFriend: (friend: FriendUserItem, remove?: boolean) => { + const tmpList = [...get().friendList]; + const idx = tmpList.findIndex((f) => f.userID === friend.userID); + if (idx < 0) { + return; + } + if (remove) { + tmpList.splice(idx, 1); + } else { + tmpList[idx] = { ...friend }; + } + set(() => ({ friendList: tmpList })); + }, + pushNewFriend: (friend: FriendUserItem) => { + set((state) => ({ friendList: [...state.friendList, friend] })); + }, + getBlackListByReq: async () => { + try { + const { data } = await IMSDK.getBlackList(); + set(() => ({ blackList: data })); + } catch (error) { + feedbackToast({ error, msg: t("toast.getBlackListFailed") }); + } + }, + updateBlack: (black: BlackUserItem, remove?: boolean) => { + const tmpList = [...get().blackList]; + const idx = tmpList.findIndex((b) => b.userID === black.userID); + if (idx < 0) { + return; + } + if (remove) { + tmpList.splice(idx, 1); + } else { + tmpList[idx] = { ...black }; + } + set(() => ({ blackList: tmpList })); + }, + pushNewBlack: (black: BlackUserItem) => { + const isFriend = get().friendList.find((f) => f.userID === black.userID); + set((state) => ({ + blackList: [...state.blackList, black], + friendList: !isFriend + ? state.friendList + : state.friendList.filter((f) => f.userID !== black.userID), + })); + }, + getGroupListByReq: async () => { + try { + let offset = 0; + let tmpList = [] as GroupItem[]; + // eslint-disable-next-line + while (true) { + const { data } = await IMSDK.getJoinedGroupListPage({ offset, count: 1000 }); + tmpList = [...tmpList, ...data]; + offset += 1000; + if (data.length < 1000) break; + } + + // const { data } = await IMSDK.getJoinedGroupList(); + set(() => ({ groupList: tmpList })); + } catch (error) { + feedbackToast({ error, msg: t("toast.getGroupListFailed") }); + } + }, + setGroupList: (list: GroupItem[]) => { + set(() => ({ groupList: list })); + }, + updateGroup: (group: GroupItem, remove?: boolean) => { + const tmpList = [...get().groupList]; + const idx = tmpList.findIndex((g) => g.groupID === group.groupID); + if (idx < 0) { + return; + } + if (remove) { + tmpList.splice(idx, 1); + } else { + tmpList[idx] = { ...group }; + } + set(() => ({ groupList: tmpList })); + }, + pushNewGroup: (group: GroupItem) => { + set((state) => ({ groupList: [...state.groupList, group] })); + }, + getRecvFriendApplicationListByReq: async () => { + try { + const { data } = await IMSDK.getFriendApplicationListAsRecipient(); + set(() => ({ recvFriendApplicationList: data })); + } catch (error) { + console.error(error); + } + }, + updateRecvFriendApplication: async (application: FriendApplicationItem) => { + let tmpList = [...get().recvFriendApplicationList]; + let isHandleResultUpdate = false; + const idx = tmpList.findIndex((a) => a.fromUserID === application.fromUserID); + if (idx < 0) { + tmpList = [...tmpList, application]; + } else { + isHandleResultUpdate = true; + tmpList[idx] = { ...application }; + } + if (idx < 0 || isHandleResultUpdate) { + const unHandleFriendApplicationCount = tmpList.filter( + (application) => + application.handleResult === 0, + ).length; + set(() => ({ + recvFriendApplicationList: tmpList, + unHandleFriendApplicationCount, + })); + return; + } + set(() => ({ recvFriendApplicationList: tmpList })); + }, + getSendFriendApplicationListByReq: async () => { + try { + const { data } = await IMSDK.getFriendApplicationListAsApplicant(); + set(() => ({ sendFriendApplicationList: data })); + } catch (error) { + console.error(error); + } + }, + updateSendFriendApplication: (application: FriendApplicationItem) => { + let tmpList = [...get().sendFriendApplicationList]; + const idx = tmpList.findIndex((a) => a.toUserID === application.toUserID); + if (idx < 0) { + tmpList = [...tmpList, application]; + } else { + tmpList[idx] = { ...application }; + } + set(() => ({ sendFriendApplicationList: tmpList })); + }, + getRecvGroupApplicationListByReq: async () => { + try { + const { data } = await IMSDK.getGroupApplicationListAsRecipient(); + set(() => ({ recvGroupApplicationList: data })); + } catch (error) { + console.error(error); + } + }, + updateRecvGroupApplication: async (application: GroupApplicationItem) => { + let tmpList = [...get().recvGroupApplicationList]; + let isHandleResultUpdate = false; + const idx = tmpList.findIndex((a) => a.userID === application.userID); + if (idx < 0) { + tmpList = [...tmpList, application]; + } else { + isHandleResultUpdate = true; + tmpList[idx] = { ...application }; + } + if (idx < 0 || application.handleResult === ApplicationHandleResult.Unprocessed) { + const unHandleGroupApplicationCount = tmpList.filter( + (application) => + application.handleResult === 0 + ).length; + set(() => ({ recvGroupApplicationList: tmpList, unHandleGroupApplicationCount })); + return; + } + set(() => ({ recvGroupApplicationList: tmpList })); + }, + getSendGroupApplicationListByReq: async () => { + try { + const { data } = await IMSDK.getGroupApplicationListAsApplicant(); + set(() => ({ sendGroupApplicationList: data })); + } catch (error) { + console.error(error); + } + }, + updateSendGroupApplication: (application: GroupApplicationItem) => { + let tmpList = [...get().sendGroupApplicationList]; + const idx = tmpList.findIndex((a) => a.groupID === application.groupID); + if (idx < 0) { + tmpList = [...tmpList, application]; + } else { + tmpList[idx] = { ...application }; + } + set(() => ({ sendGroupApplicationList: tmpList })); + }, + updateUnHandleFriendApplicationCount: (num: number) => { + set(() => ({ unHandleFriendApplicationCount: num })); + }, + updateUnHandleGroupApplicationCount: (num: number) => { + set(() => ({ unHandleGroupApplicationCount: num })); + }, + clearContactStore: () => { + set(() => ({ + friendList: [], + blackList: [], + groupList: [], + recvFriendApplicationList: [], + sendFriendApplicationList: [], + recvGroupApplicationList: [], + sendGroupApplicationList: [], + unHandleFriendApplicationCount: 0, + unHandleGroupApplicationCount: 0, + })); + }, +})); diff --git a/pc-client/src/store/conversation.ts b/pc-client/src/store/conversation.ts new file mode 100644 index 0000000..2d9021f --- /dev/null +++ b/pc-client/src/store/conversation.ts @@ -0,0 +1,159 @@ +import { + ConversationItem, + GroupItem, + GroupMemberItem, + MessageItem, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import { t } from "i18next"; +import { create } from "zustand"; + +import { IMSDK } from "@/layout/MainContentWrap"; +import { feedbackToast } from "@/utils/common"; +import { conversationSort, isGroupSession } from "@/utils/imCommon"; + +import { ConversationListUpdateType, ConversationStore } from "./type"; +import { useUserStore } from "./user"; + +const CONVERSATION_SPLIT_COUNT = 500; + +export const useConversationStore = create()((set, get) => ({ + conversationList: [], + currentConversation: undefined, + unReadCount: 0, + currentGroupInfo: undefined, + currentMemberInGroup: undefined, + getConversationListByReq: async (isOffset?: boolean) => { + let tmpConversationList = [] as ConversationItem[]; + try { + const { data } = await IMSDK.getConversationListSplit({ + offset: isOffset ? get().conversationList.length : 0, + count: CONVERSATION_SPLIT_COUNT, + }); + tmpConversationList = data; + } catch (error) { + feedbackToast({ error, msg: t("toast.getConversationFailed") }); + return true; + } + set((state) => ({ + conversationList: [ + ...(isOffset ? state.conversationList : []), + ...tmpConversationList, + ], + })); + return tmpConversationList.length === CONVERSATION_SPLIT_COUNT; + }, + updateConversationList: ( + list: ConversationItem[], + type: ConversationListUpdateType, + ) => { + const idx = list.findIndex( + (c) => c.conversationID === get().currentConversation?.conversationID, + ); + if (idx > -1) get().updateCurrentConversation(list[idx]); + + if (type === "filter") { + set((state) => ({ + conversationList: conversationSort( + [...list, ...state.conversationList], + state.conversationList, + ), + })); + return; + } + let filterArr: ConversationItem[] = []; + const chids = list.map((ch) => ch.conversationID); + filterArr = get().conversationList.filter( + (tc) => !chids.includes(tc.conversationID), + ); + + set(() => ({ conversationList: conversationSort([...list, ...filterArr]) })); + }, + updateCurrentConversation: async ( + conversation?: ConversationItem, + isJump?: boolean, + ) => { + if (!conversation) { + set(() => ({ + currentConversation: undefined, + quoteMessage: undefined, + currentGroupInfo: undefined, + currentMemberInGroup: undefined, + })); + return; + } + const prevConversation = get().currentConversation; + + const toggleNewConversation = + conversation.conversationID !== prevConversation?.conversationID; + if (toggleNewConversation && isGroupSession(conversation.conversationType)) { + get().getCurrentGroupInfoByReq(conversation.groupID); + await get().getCurrentMemberInGroupByReq(conversation.groupID); + } + set(() => ({ currentConversation: { ...conversation } })); + }, + getUnReadCountByReq: async () => { + try { + const { data } = await IMSDK.getTotalUnreadMsgCount(); + set(() => ({ unReadCount: data })); + return data; + } catch (error) { + console.error(error); + return 0; + } + }, + updateUnReadCount: (count: number) => { + set(() => ({ unReadCount: count })); + }, + getCurrentGroupInfoByReq: async (groupID: string) => { + let groupInfo: GroupItem; + try { + const { data } = await IMSDK.getSpecifiedGroupsInfo([groupID]); + groupInfo = data[0]; + } catch (error) { + feedbackToast({ error, msg: t("toast.getGroupInfoFailed") }); + return; + } + set(() => ({ currentGroupInfo: { ...groupInfo } })); + }, + updateCurrentGroupInfo: (groupInfo: GroupItem) => { + set(() => ({ currentGroupInfo: { ...groupInfo } })); + }, + getCurrentMemberInGroupByReq: async (groupID: string) => { + let memberInfo: GroupMemberItem; + const selfID = useUserStore.getState().selfInfo.userID; + try { + const { data } = await IMSDK.getSpecifiedGroupMembersInfo({ + groupID, + userIDList: [selfID], + }); + memberInfo = data[0]; + } catch (error) { + set(() => ({ currentMemberInGroup: undefined })); + feedbackToast({ error, msg: t("toast.getGroupMemberFailed") }); + return; + } + set(() => ({ currentMemberInGroup: memberInfo ? { ...memberInfo } : undefined })); + }, + setCurrentMemberInGroup: (memberInfo?: GroupMemberItem) => { + set(() => ({ currentMemberInGroup: memberInfo })); + }, + tryUpdateCurrentMemberInGroup: (member: GroupMemberItem) => { + const currentMemberInGroup = get().currentMemberInGroup; + if ( + member.groupID === currentMemberInGroup?.groupID && + member.userID === currentMemberInGroup?.userID + ) { + set(() => ({ currentMemberInGroup: { ...member } })); + } + }, + clearConversationStore: () => { + set(() => ({ + conversationList: [], + currentConversation: undefined, + unReadCount: 0, + currentGroupInfo: undefined, + currentMemberInGroup: undefined, + quoteMessage: undefined, + })); + }, +})); diff --git a/pc-client/src/store/index.ts b/pc-client/src/store/index.ts new file mode 100644 index 0000000..6e54c74 --- /dev/null +++ b/pc-client/src/store/index.ts @@ -0,0 +1,3 @@ +export * from "./contact"; +export * from "./conversation"; +export * from "./user"; diff --git a/pc-client/src/store/type.d.ts b/pc-client/src/store/type.d.ts new file mode 100644 index 0000000..df57530 --- /dev/null +++ b/pc-client/src/store/type.d.ts @@ -0,0 +1,104 @@ +import { + AtTextElem, + BlackUserItem, + ConversationItem, + FriendApplicationItem, + FriendUserItem, + GroupApplicationItem, + GroupItem, + GroupMemberItem, + MessageItem, +} from "@openim/wasm-client-sdk/lib/types/entity"; + +import { BusinessUserInfo } from "@/api/login"; + +export type IMConnectState = "success" | "loading" | "failed"; + +export interface UserStore { + syncState: IMConnectState; + progress: number; + reinstall: boolean; + isLogining: boolean; + connectState: IMConnectState; + selfInfo: BusinessUserInfo; + appSettings: AppSettings; + updateSyncState: (syncState: IMConnectState) => void; + updateProgressState: (progress: number) => void; + updateReinstallState: (reinstall: boolean) => void; + updateIsLogining: (isLogining: boolean) => void; + updateConnectState: (connectState: IMConnectState) => void; + updateSelfInfo: (info: Partial) => void; + getSelfInfoByReq: () => void; + updateAppSettings: (settings: Partial) => void; + userLogout: (force?: boolean) => Promise; +} + +export interface AppSettings { + locale: LocaleString; + closeAction: "miniSize" | "quit"; +} + +export type LocaleString = "zh-CN" | "en-US"; + +export type ConversationListUpdateType = "push" | "filter"; + +export interface ConversationStore { + conversationList: ConversationItem[]; + currentConversation?: ConversationItem; + unReadCount: number; + currentGroupInfo?: GroupItem; + currentMemberInGroup?: GroupMemberItem; + getConversationListByReq: ( + isOffset?: boolean + ) => Promise; + updateConversationList: ( + list: ConversationItem[], + type: ConversationListUpdateType, + ) => void; + updateCurrentConversation: ( + conversation?: ConversationItem, + isJump?: boolean, + ) => Promise; + getUnReadCountByReq: () => Promise; + updateUnReadCount: (count: number) => void; + getCurrentGroupInfoByReq: (groupID: string) => Promise; + updateCurrentGroupInfo: (groupInfo: GroupItem) => void; + getCurrentMemberInGroupByReq: (groupID: string) => Promise; + setCurrentMemberInGroup: (memberInfo?: GroupMemberItem) => void; + tryUpdateCurrentMemberInGroup: (member: GroupMemberItem) => void; + clearConversationStore: () => void; +} + +export interface ContactStore { + friendList: FriendUserItem[]; + blackList: BlackUserItem[]; + groupList: GroupItem[]; + recvFriendApplicationList: FriendApplicationItem[]; + sendFriendApplicationList: FriendApplicationItem[]; + recvGroupApplicationList: GroupApplicationItem[]; + sendGroupApplicationList: GroupApplicationItem[]; + unHandleFriendApplicationCount: number; + unHandleGroupApplicationCount: number; + getFriendListByReq: () => Promise; + setFriendList: (list: FriendUserItem[]) => void; + updateFriend: (friend: FriendUserItem, remove?: boolean) => void; + pushNewFriend: (friend: FriendUserItem) => void; + getBlackListByReq: () => Promise; + updateBlack: (black: BlackUserItem, remove?: boolean) => void; + pushNewBlack: (black: BlackUserItem) => void; + getGroupListByReq: () => Promise; + setGroupList: (list: GroupItem[]) => void; + updateGroup: (group: GroupItem, remove?: boolean) => void; + pushNewGroup: (group: GroupItem) => void; + getRecvFriendApplicationListByReq: () => Promise; + updateRecvFriendApplication: (application: FriendApplicationItem) => Promise; + getSendFriendApplicationListByReq: () => Promise; + updateSendFriendApplication: (application: FriendApplicationItem) => void; + getRecvGroupApplicationListByReq: () => Promise; + updateRecvGroupApplication: (application: GroupApplicationItem) => Promise; + getSendGroupApplicationListByReq: () => Promise; + updateSendGroupApplication: (application: GroupApplicationItem) => void; + updateUnHandleFriendApplicationCount: (num: number) => void; + updateUnHandleGroupApplicationCount: (num: number) => void; + clearContactStore: () => void; +} diff --git a/pc-client/src/store/user.ts b/pc-client/src/store/user.ts new file mode 100644 index 0000000..51f9faa --- /dev/null +++ b/pc-client/src/store/user.ts @@ -0,0 +1,70 @@ +import { t } from "i18next"; +import { create } from "zustand"; + +import { BusinessUserInfo, getBusinessUserInfo } from "@/api/login"; +import { IMSDK } from "@/layout/MainContentWrap"; +import router from "@/routes"; +import { feedbackToast } from "@/utils/common"; +import { clearIMProfile, getLocale, setLocale } from "@/utils/storage"; + +import { useContactStore } from "./contact"; +import { useConversationStore } from "./conversation"; +import { AppSettings, IMConnectState, UserStore } from "./type"; + +export const useUserStore = create()((set, get) => ({ + syncState: "success", + progress: 0, + reinstall: true, + isLogining: false, + connectState: "success", + selfInfo: {} as BusinessUserInfo, + appSettings: { + locale: getLocale(), + closeAction: "miniSize", + }, + updateSyncState: (syncState: IMConnectState) => { + set({ syncState }); + }, + updateProgressState: (progress: number) => { + set({ progress }); + }, + updateReinstallState: (reinstall: boolean) => { + set({ reinstall }); + }, + updateIsLogining: (isLogining: boolean) => { + set({ isLogining }); + }, + updateConnectState: (connectState: IMConnectState) => { + set({ connectState }); + }, + getSelfInfoByReq: () => { + IMSDK.getSelfUserInfo() + .then(({ data }) => { + set(() => ({ selfInfo: data as unknown as BusinessUserInfo })); + getBusinessUserInfo([data.userID]).then(({ data: { users } }) => + set((state) => ({ selfInfo: { ...state.selfInfo, ...users[0] } })), + ); + }) + .catch((error) => { + feedbackToast({ error, msg: t("toast.getSelfInfoFailed") }); + get().userLogout(); + }); + }, + updateSelfInfo: (info: Partial) => { + set((state) => ({ selfInfo: { ...state.selfInfo, ...info } })); + }, + updateAppSettings: (settings: Partial) => { + if (settings.locale) { + setLocale(settings.locale); + } + set((state) => ({ appSettings: { ...state.appSettings, ...settings } })); + }, + userLogout: async (force?: boolean) => { + if (!force) await IMSDK.logout(); + clearIMProfile(); + set({ selfInfo: {} as BusinessUserInfo, progress: 0 }); + useContactStore.getState().clearContactStore(); + useConversationStore.getState().clearConversationStore(); + router.navigate("/login"); + }, +})); diff --git a/pc-client/src/styles/antd.scss b/pc-client/src/styles/antd.scss new file mode 100644 index 0000000..a4c400b --- /dev/null +++ b/pc-client/src/styles/antd.scss @@ -0,0 +1,281 @@ +.ant-avatar-image { + background-color: transparent !important; +} + +.ant-badge { + z-index: 1; +} + +.ant-spin-text { + color: var(--primary); +} + +.ant-empty-description { + color: var(--sub-text) !important; +} + +.ant-app, +.lk-room-container { + height: var(--full-height); + & > .ant-spin-nested-loading { + height: var(--full-height); + .ant-spin-container { + height: var(--full-height); + } + } +} + +.ant-popover .ant-popover-inner { + padding: 0; +} + +.ant-image-mask-info { + color: #fff; +} + +.grid-image { + .ant-image { + position: unset; + } +} + +.message-image { + .ant-image-mask { + border-radius: 6px; + } +} + +.quote-image { + .ant-image-mask { + opacity: 0 !important; + } +} + +.conversation-popover { + .ant-popover-content { + transform: translateY(-36px); + } + + @media only screen and (min-width: 600px) { + .ant-popover-content { + transform: translate(42px, -36px); + } + } +} + +.profile-popover { + .ant-popover-content { + transform: translateX(12px); + } +} + +.chat-drawer { + margin-top: var(--searchbar-height); + + .ant-drawer-content-wrapper { + box-shadow: -7px 0px 7px 1px rgba(30, 116, 222, 0.05); + min-width: 460px; + } + + .ant-drawer-header { + padding: 0 24px; + background-color: #e8eaef; + border: none; + + .ant-drawer-header-title { + height: 64px; + } + + .ant-drawer-close { + position: absolute; + right: 24px; + margin: 0; + } + } + + .ant-drawer-body { + padding: 0; + display: flex; + flex-direction: column; + } + + .anticon-close, + .anticon-right { + color: #8e9ab0; + } +} + +.disabled-upload { + .ant-upload { + cursor: auto; + } +} + +.message-drawer-tab { + height: 100%; + + .ant-tabs-nav { + padding: 0 24px; + margin-top: 12px; + + .ant-tabs-tab { + padding: 4px 0; + } + + .ant-tabs-ink-bar { + height: 3px; + border-radius: 8px; + transform: scaleX(0.6); + } + + &::before { + border: none; + } + } + + .ant-tabs-content-holder { + flex: 1; + + .ant-tabs-content { + height: 100%; + overflow-y: auto; + + .ant-tabs-tabpane { + height: 100%; + } + } + } +} + +.no-padding-modal { + .ant-modal-content { + padding: 0; + border-radius: 6px; + overflow: hidden; + } +} + +.global-search-modal { + .ant-modal-content { + border-radius: 16px; + } + + .message-drawer-tab { + .ant-tabs-nav { + padding: 0 32px; + margin-bottom: 0; + border-bottom: 1px solid var(--gap-text); + } + } + + .ant-tabs-content-holder { + .ant-tabs-content { + padding: 0 12px; + overflow-y: hidden; + } + } +} + +.rtc-single-modal { + .ant-modal-content { + padding: 0; + border-radius: 16px; + overflow: hidden; + } +} + +.bold-label-form { + .ant-form-item-label { + label { + color: var(--base-black); + font-weight: 500; + } + } +} + +.sub-label-form { + .ant-form-item-label { + text-align: start; + label { + color: var(--sub-text); + } + } +} + +.ant-btn-primary { + background-color: var(--primary); + + &:disabled { + opacity: 0.5; + color: #fff; + background-color: var(--primary); + } +} + +.ant-switch { + background-color: rgba(0, 0, 0, 0.25); +} + +.ant-breadcrumb-link { + line-height: 22px; +} + +.no-addon-search { + .ant-input { + border-radius: 6px !important; + } + .ant-input-group-addon { + display: none; + } +} + +.flex-1 > .ant-spin-container { + height: 100%; + width: 100%; +} + +.h-full > .ant-spin-container { + height: 100%; + width: 100%; +} + +.h-full > .ant-spin-container { + height: 100%; +} + +.drop-file-moal { + .ant-modal-confirm-content { + max-width: 100% !important; + } +} + +.ant-skeleton-with-avatar + .ant-skeleton-content + .ant-skeleton-title + + .ant-skeleton-paragraph { + margin-block-start: 12px; +} + +.ant-skeleton-with-avatar .ant-skeleton-content .ant-skeleton-title { + margin-block-start: 0; +} + +.ant-skeleton .ant-skeleton-header .ant-skeleton-avatar { + border-radius: 6px; +} + +.send-action-dropdown { + .ant-dropdown-menu-item { + padding: 4px 6px !important; + width: 120px !important; + + span { + font-size: 12px; + color: var(--sub-text); + } + + .anticon-check { + color: var(--primary); + } + } +} diff --git a/pc-client/src/styles/global.scss b/pc-client/src/styles/global.scss new file mode 100644 index 0000000..345dfe5 --- /dev/null +++ b/pc-client/src/styles/global.scss @@ -0,0 +1,168 @@ +:root { + --full-height: 100%; + --chat-bubble: #ffffff; + --chat-bubble-sender: #cde6ff; + --base-black: #0c1c33; + --primary: #0073d9; + --primary-active: #eaf4ff; + --top-search-bar: #0073d9; + --sub-text: #8e9ab0; + --gap-text: #e8eaef; + --warn-text: #ff381f; + --moment-text: #6085b1; + --searchbar-height: 2.5rem; +} + +@media only screen and (max-width: 600px) { + .no-mobile { + display: none; + } +} + +html { + height: var(--full-height); + + font-family: "Noto Sans SC", "SF Pro SC", "SF Pro Text", "SF Pro Icons", "PingFang SC", + "Helvetica Neue", "Helvetica", "Arial", sans-serif; + + div { + color: var(--base-black); + } +} + +body, +#root { + height: var(--full-height); + overflow: hidden; + user-select: none; +} + +::-webkit-scrollbar { + width: 6px; + background-color: transparent; +} +::-webkit-scrollbar-track { + background: transparent; +} +::-webkit-scrollbar-thumb { + border-radius: 3px; + background: #b7bdcb; + box-shadow: 4px 4px 15px rgba(112, 124, 151, 0.05), + 2px 2px 10px rgba(112, 124, 151, 0.1), 1px 1px 50px rgba(112, 124, 151, 0.15); +} +::-webkit-scrollbar-thumb:hover { + border-radius: 3px; + box-shadow: inset 0 0 6px rgba(0, 0, 0, 0.3); + background-color: rgba(245, 238, 238, 1); +} + +#chat-list { + &::-webkit-scrollbar { + width: 8px; + } +} + +.no-scrollbar { + &::-webkit-scrollbar { + display: none; + } +} + +.emojione { + width: 16px !important; + height: 16px !important; + display: inline-block; +} + +.image-el { + vertical-align: bottom; + display: inline-block; + max-width: 30vw; + max-height: 15vh; + object-fit: contain; + cursor: pointer; +} + +.at-el { + display: inline-block; + color: var(--primary); + width: fit-content; +} + +.link-el { + color: var(--primary); + cursor: pointer; +} + +.member-el { + margin: 0 4px; +} + +.app-drag { + -webkit-app-region: drag; +} + +.app-no-drag { + -webkit-app-region: no-drag; +} + +.text-break { + word-wrap: break-word; + word-break: break-all; + white-space: pre-wrap; +} + +#scrollableDiv { + position: relative; +} + +.growable::before { + content: ""; + flex-grow: 1; +} + +#video_player { + position: unset !important; +} + +.video-img { + position: relative; + display: inline-block; +} + +.video-image-mask:hover { + opacity: 1; +} + +.video-image-mask { + position: absolute; + display: flex; + align-items: center; + justify-content: center; + color: #fff; + background: rgba(0, 0, 0, 0.5); + cursor: pointer; + opacity: 0; + transition: opacity 0.3s; + inset: 0; +} + +.no-scrollbar { + ::-webkit-scrollbar { + width: 0px; + display: none; + } +} + +img { + -webkit-user-drag: none; +} + +.custom-form-item > label { + color: var(--sub-text) !important; + margin-bottom: 4px !important; +} + +.lk-participant-media-video { + object-fit: contain !important; +} diff --git a/pc-client/src/styles/svg.scss b/pc-client/src/styles/svg.scss new file mode 100644 index 0000000..e69de29 diff --git a/pc-client/src/types/common.d.ts b/pc-client/src/types/common.d.ts new file mode 100644 index 0000000..9fd33d1 --- /dev/null +++ b/pc-client/src/types/common.d.ts @@ -0,0 +1,290 @@ +export interface ChildWindowOptions { + /** + * Window's width in pixels. Default is `800`. + */ + width?: number; + /** + * Window's height in pixels. Default is `600`. + */ + height?: number; + /** + * (**required** if y is used) Window's left offset from screen. Default is to + * center the window. + */ + x?: number; + /** + * (**required** if x is used) Window's top offset from screen. Default is to + * center the window. + */ + y?: number; + /** + * The `width` and `height` would be used as web page's size, which means the + * actual window's size will include window frame's size and be slightly larger. + * Default is `false`. + */ + useContentSize?: boolean; + /** + * Show window in the center of the screen. Default is `false`. + */ + center?: boolean; + /** + * Window's minimum width. Default is `0`. + */ + minWidth?: number; + /** + * Window's minimum height. Default is `0`. + */ + minHeight?: number; + /** + * Window's maximum width. Default is no limit. + */ + maxWidth?: number; + /** + * Window's maximum height. Default is no limit. + */ + maxHeight?: number; + /** + * Whether window is resizable. Default is `true`. + */ + resizable?: boolean; + /** + * Whether window is movable. This is not implemented on Linux. Default is `true`. + * + * @platform darwin,win32 + */ + movable?: boolean; + /** + * Whether window is minimizable. This is not implemented on Linux. Default is + * `true`. + * + * @platform darwin,win32 + */ + minimizable?: boolean; + /** + * Whether window is maximizable. This is not implemented on Linux. Default is + * `true`. + * + * @platform darwin,win32 + */ + maximizable?: boolean; + /** + * Whether window is closable. This is not implemented on Linux. Default is `true`. + * + * @platform darwin,win32 + */ + closable?: boolean; + /** + * Whether the window can be focused. Default is `true`. On Windows setting + * `focusable: false` also implies setting `skipTaskbar: true`. On Linux setting + * `focusable: false` makes the window stop interacting with wm, so the window will + * always stay on top in all workspaces. + */ + focusable?: boolean; + /** + * Whether the window should always stay on top of other windows. Default is + * `false`. + */ + alwaysOnTop?: boolean; + /** + * Whether the window should show in fullscreen. When explicitly set to `false` the + * fullscreen button will be hidden or disabled on macOS. Default is `false`. + */ + fullscreen?: boolean; + /** + * Whether the window can be put into fullscreen mode. On macOS, also whether the + * maximize/zoom button should toggle full screen mode or maximize window. Default + * is `true`. + */ + fullscreenable?: boolean; + /** + * Use pre-Lion fullscreen on macOS. Default is `false`. + * + * @platform darwin + */ + simpleFullscreen?: boolean; + /** + * Whether to show the window in taskbar. Default is `false`. + * + * @platform darwin,win32 + */ + skipTaskbar?: boolean; + /** + * Whether window should be hidden when the user toggles into mission control. + * + * @platform darwin + */ + hiddenInMissionControl?: boolean; + /** + * Whether the window is in kiosk mode. Default is `false`. + */ + kiosk?: boolean; + /** + * Default window title. Default is `"Electron"`. If the HTML tag `` is + * defined in the HTML file loaded by `loadURL()`, this property will be ignored. + */ + title?: string; + /** + * Whether window should be shown when created. Default is `true`. + */ + show?: boolean; + /** + * Whether the renderer should be active when `show` is `false` and it has just + * been created. In order for `document.visibilityState` to work correctly on + * first load with `show: false` you should set this to `false`. Setting this to + * `false` will cause the `ready-to-show` event to not fire. Default is `true`. + */ + paintWhenInitiallyHidden?: boolean; + /** + * Specify `false` to create a frameless window. Default is `true`. + */ + frame?: boolean; + /** + * Whether this is a modal window. This only works when the window is a child + * window. Default is `false`. + */ + modal?: boolean; + /** + * Whether clicking an inactive window will also click through to the web contents. + * Default is `false` on macOS. This option is not configurable on other platforms. + * + * @platform darwin + */ + acceptFirstMouse?: boolean; + /** + * Whether to hide cursor when typing. Default is `false`. + */ + disableAutoHideCursor?: boolean; + /** + * Auto hide the menu bar unless the `Alt` key is pressed. Default is `false`. + */ + autoHideMenuBar?: boolean; + /** + * Enable the window to be resized larger than screen. Only relevant for macOS, as + * other OSes allow larger-than-screen windows by default. Default is `false`. + * + * @platform darwin + */ + enableLargerThanScreen?: boolean; + /** + * The window's background color in Hex, RGB, RGBA, HSL, HSLA or named CSS color + * format. Alpha in #AARRGGBB format is supported if `transparent` is set to + * `true`. Default is `#FFF` (white). See win.setBackgroundColor for more + * information. + */ + backgroundColor?: string; + /** + * Whether window should have a shadow. Default is `true`. + */ + hasShadow?: boolean; + /** + * Set the initial opacity of the window, between 0.0 (fully transparent) and 1.0 + * (fully opaque). This is only implemented on Windows and macOS. + * + * @platform darwin,win32 + */ + opacity?: number; + /** + * Forces using dark theme for the window, only works on some GTK+3 desktop + * environments. Default is `false`. + */ + darkTheme?: boolean; + /** + * Makes the window transparent. Default is `false`. On Windows, does not work + * unless the window is frameless. + */ + transparent?: boolean; + /** + * The type of window, default is normal window. See more about this below. + */ + type?: string; + /** + * Specify how the material appearance should reflect window activity state on + * macOS. Must be used with the `vibrancy` property. Possible values are: + * + * @platform darwin + */ + visualEffectState?: "followWindow" | "active" | "inactive"; + /** + * The style of window title bar. Default is `default`. Possible values are: + * + * @platform darwin,win32 + */ + titleBarStyle?: "default" | "hidden" | "hiddenInset" | "customButtonsOnHover"; + /** + * Set a custom position for the traffic light buttons in frameless windows. + * + * @platform darwin + */ + trafficLightPosition?: Point; + /** + * Whether frameless window should have rounded corners on macOS. Default is + * `true`. Setting this property to `false` will prevent the window from being + * fullscreenable. + * + * @platform darwin + */ + roundedCorners?: boolean; + /** + * Shows the title in the title bar in full screen mode on macOS for `hiddenInset` + * titleBarStyle. Default is `false`. + * + * @deprecated + * @platform darwin + */ + fullscreenWindowTitle?: boolean; + /** + * Use `WS_THICKFRAME` style for frameless windows on Windows, which adds standard + * window frame. Setting it to `false` will remove window shadow and window + * animations. Default is `true`. + */ + thickFrame?: boolean; + /** + * Add a type of vibrancy effect to the window, only on macOS. Can be + * `appearance-based`, `light`, `dark`, `titlebar`, `selection`, `menu`, `popover`, + * `sidebar`, `medium-light`, `ultra-dark`, `header`, `sheet`, `window`, `hud`, + * `fullscreen-ui`, `tooltip`, `content`, `under-window`, or `under-page`. Please + * note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` + * are deprecated and have been removed in macOS Catalina (10.15). + * + * @platform darwin + */ + vibrancy?: + | "appearance-based" + | "light" + | "dark" + | "titlebar" + | "selection" + | "menu" + | "popover" + | "sidebar" + | "medium-light" + | "ultra-dark" + | "header" + | "sheet" + | "window" + | "hud" + | "fullscreen-ui" + | "tooltip" + | "content" + | "under-window" + | "under-page"; + /** + * Controls the behavior on macOS when option-clicking the green stoplight button + * on the toolbar or by clicking the Window > Zoom menu item. If `true`, the window + * will grow to the preferred width of the web page when zoomed, `false` will cause + * it to zoom to the width of the screen. This will also affect the behavior when + * calling `maximize()` directly. Default is `false`. + * + * @platform darwin + */ + zoomToPageWidth?: boolean; + /** + * Tab group name, allows opening the window as a native tab. Windows with the same + * tabbing identifier will be grouped together. This also adds a native new tab + * button to your window's tab bar and allows your `app` and window to receive the + * `new-window-for-tab` event. + * + * @platform darwin + */ + tabbingIdentifier?: string; +} diff --git a/pc-client/src/types/globalExpose.d.ts b/pc-client/src/types/globalExpose.d.ts new file mode 100644 index 0000000..b76e7b0 --- /dev/null +++ b/pc-client/src/types/globalExpose.d.ts @@ -0,0 +1,32 @@ +import { Platform } from "@openim/wasm-client-sdk"; + +export type DataPath = "public" | "emojiData" | "sdkResources" | "logsPath"; + +export interface IElectronAPI { + getDataPath: (key: DataPath) => string; + getVersion: () => string; + getPlatform: () => Platform; + getSystemVersion: () => string; + subscribe: (channel: string, callback: (...args: any[]) => void) => () => void; + subscribeOnce: (channel: string, callback: (...args: any[]) => void) => void; + unsubscribeAll: (channel: string) => void; + ipcInvoke: <T = unknown>(channel: string, ...arg: any) => Promise<T>; + ipcSendSync: <T = unknown>(channel: string, ...arg: any) => T; + saveFileToDisk: (params: { file: File; sync?: boolean }) => Promise<string>; + getFileByPath: (filePath: string) => Promise<File | null>; +} + +declare global { + interface Window { + electronAPI?: IElectronAPI; + userClick: (userID?: string, groupID?: string) => void; + editRevoke: (clientMsgID: string) => void; + screenshotPreview: (results: string) => void; + } +} + +declare module "i18next" { + interface TFunction { + (key: string, options?: object): string; + } +} diff --git a/pc-client/src/utils/avatar.ts b/pc-client/src/utils/avatar.ts new file mode 100644 index 0000000..6190fc9 --- /dev/null +++ b/pc-client/src/utils/avatar.ts @@ -0,0 +1,30 @@ +export const avatarList = [ + { + src: new URL("@/assets/avatar/ic_avatar_01.png", import.meta.url).href, + name: "ic_avatar_01", + }, + { + src: new URL("@/assets/avatar/ic_avatar_02.png", import.meta.url).href, + name: "ic_avatar_02", + }, + { + src: new URL("@/assets/avatar/ic_avatar_03.png", import.meta.url).href, + name: "ic_avatar_03", + }, + { + src: new URL("@/assets/avatar/ic_avatar_04.png", import.meta.url).href, + name: "ic_avatar_04", + }, + { + src: new URL("@/assets/avatar/ic_avatar_05.png", import.meta.url).href, + name: "ic_avatar_05", + }, + { + src: new URL("@/assets/avatar/ic_avatar_06.png", import.meta.url).href, + name: "ic_avatar_06", + }, +]; + +export const getDefaultAvatar = (name: string) => { + return avatarList.find((avator) => avator.name === name)?.src; +}; diff --git a/pc-client/src/utils/common.ts b/pc-client/src/utils/common.ts new file mode 100644 index 0000000..f20440d --- /dev/null +++ b/pc-client/src/utils/common.ts @@ -0,0 +1,163 @@ +import { t } from "i18next"; + +import { message } from "../AntdGlobalComp"; + +type FeedbackToastParams = { + msg?: string | null; + error?: unknown; + duration?: number; + onClose?: () => void; +}; + +interface FeedbackError extends Error { + errMsg?: string; + errDlt?: string; +} +export const feedbackToast = (config?: FeedbackToastParams) => { + const { msg, error, duration, onClose } = config ?? {}; + let content = ""; + if (error) { + content = + (error as FeedbackError)?.message ?? + (error as FeedbackError)?.errDlt ?? + t("toast.accessFailed"); + } + message.open({ + type: error ? "error" : "success", + content: msg ?? content ?? t("toast.accessSuccess"), + duration, + onClose, + }); + if (error) { + console.error(msg, error); + } +}; + +export const canSendImageTypeList = ["png", "jpg", "jpeg", "gif", "bmp", "webp"]; + +export const bytesToSize = (bytes: number) => { + if (bytes === 0) return "0 B"; + const k = 1024, + sizes = ["B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"], + i = Math.floor(Math.log(bytes) / Math.log(k)); + + const size = bytes / Math.pow(k, i); + return `${size % 1 === 0 ? size : size.toFixed(2)} ${sizes[i]}`; +}; + +export const secondsToTime = (seconds: number) => { + let minutes = 0; // min + let hours = 0; // hour + let days = 0; // day + if (seconds > 60) { + minutes = parseInt((seconds / 60) as unknown as string); + seconds = parseInt((seconds % 60) as unknown as string); + if (minutes > 60) { + hours = parseInt((minutes / 60) as unknown as string); + minutes = parseInt((minutes % 60) as unknown as string); + if (hours > 24) { + days = parseInt((hours / 24) as unknown as string); + hours = parseInt((hours % 24) as unknown as string); + } + } + } + let result = ""; + if (seconds > 0) { + result = t("date.second", { num: parseInt(seconds as unknown as string) }); + } + if (minutes > 0) { + result = t("date.minute", { num: parseInt(minutes as unknown as string) }) + result; + } + if (hours > 0) { + result = t("date.hour", { num: parseInt(hours as unknown as string) }) + result; + } + if (days > 0) { + result = t("date.day", { num: parseInt(days as unknown as string) }) + result; + } + return result; +}; + +export const secondsToMS = (duration: number) => { + let minutes = Math.floor(duration / 60) % 60; + let seconds = (duration % 60).toString(); + minutes = minutes.toString().padStart(2, "0") as unknown as number; + seconds = seconds.length === 1 ? "0" + seconds : seconds; + return `${minutes}:${seconds}`; +}; + +export const filterEmptyValue = (obj: Record<string, unknown>) => { + for (const key in obj) { + if (obj[key] === "") { + delete obj[key]; + } + } +}; + +export const checkIsSafari = () => + /^((?!chrome|android).)*safari/i.test(navigator.userAgent) && + /iPad|iPhone|iPod/.test(navigator.userAgent); + +export const downloadFile = async (originUrl: string) => { + const linkNode = document.createElement("a"); + linkNode.style.display = "none"; + const idx = originUrl.lastIndexOf("/"); + linkNode.download = originUrl.slice(idx + 1); + linkNode.href = originUrl; + document.body.appendChild(linkNode); + linkNode.click(); + document.body.removeChild(linkNode); +}; + +export const base64toFile = (base64Str: string) => { + var arr = base64Str.split(","), + fileType = arr[0].match(/:(.*?);/)![1], + bstr = atob(arr[1]), + n = bstr.length, + u8arr = new Uint8Array(n); + + while (n--) { + u8arr[n] = bstr.charCodeAt(n); + } + + return new File([u8arr], `screenshot${Date.now()}.png`, { + type: fileType, + }); +}; + +export const fileToBase64 = (file: File): Promise<string> => + new Promise((resolve) => { + const reader = new FileReader(); + reader.onload = function (evt) { + const base64 = evt.target?.result; + resolve(base64 as string); + }; + reader.readAsDataURL(file); + }); + +export const formatBr = (str: string) => str.replace(/\n/g, "<br>"); + +export const getFileType = (name: string) => { + const idx = name.lastIndexOf("."); + return name.slice(idx + 1); +}; + +export const generateAvatar = (str: string, size = 40) => { + str = !str ? t("placeholder.unknown") : str.split("")[0]; + let colors = ["#0072E3"]; + let cvs = document.createElement("canvas"); + cvs.setAttribute("width", size as unknown as string); + cvs.setAttribute("height", size as unknown as string); + let ctx = cvs.getContext("2d"); + ctx!.fillStyle = colors[Math.floor(Math.random() * colors.length)]; + ctx!.fillRect(0, 0, size, size); + ctx!.fillStyle = "rgb(255,255,255)"; + ctx!.font = size * 0.4 + "px Arial"; + ctx!.textBaseline = "middle"; + ctx!.textAlign = "center"; + ctx!.fillText(str, size / 2, size / 2); + return cvs.toDataURL("image/png", 1); +}; + +export async function sleep(duration: number): Promise<void> { + return new Promise((resolve) => setTimeout(resolve, duration)); +} diff --git a/pc-client/src/utils/contactsFormat.ts b/pc-client/src/utils/contactsFormat.ts new file mode 100644 index 0000000..33ed478 --- /dev/null +++ b/pc-client/src/utils/contactsFormat.ts @@ -0,0 +1,548 @@ +import { FriendUserItem } from "@openim/wasm-client-sdk/lib/types/entity"; + +const workerFunction = () => { + const PinYin = { + a: "\u554a\u963f\u9515", + ai: "\u57c3\u6328\u54ce\u5509\u54c0\u7691\u764c\u853c\u77ee\u827e\u788d\u7231\u9698\u8bf6\u6371\u55f3\u55cc\u5ad2\u7477\u66a7\u7839\u953f\u972d", + an: "\u978d\u6c28\u5b89\u4ffa\u6309\u6697\u5cb8\u80fa\u6848\u8c19\u57ef\u63de\u72b4\u5eb5\u6849\u94f5\u9e4c\u9878\u9eef", + ang: "\u80ae\u6602\u76ce", + ao: "\u51f9\u6556\u71ac\u7ff1\u8884\u50b2\u5965\u61ca\u6fb3\u5773\u62d7\u55f7\u5662\u5c99\u5ed2\u9068\u5aaa\u9a9c\u8071\u87af\u93ca\u9ccc\u93d6", + ba: "\u82ad\u634c\u6252\u53ed\u5427\u7b06\u516b\u75a4\u5df4\u62d4\u8dcb\u9776\u628a\u8019\u575d\u9738\u7f62\u7238\u8307\u83dd\u8406\u636d\u5c9c\u705e\u6777\u94af\u7c91\u9c85\u9b43", + bai: "\u767d\u67cf\u767e\u6446\u4f70\u8d25\u62dc\u7a17\u859c\u63b0\u97b4", + ban: "\u6591\u73ed\u642c\u6273\u822c\u9881\u677f\u7248\u626e\u62cc\u4f34\u74e3\u534a\u529e\u7eca\u962a\u5742\u8c73\u94a3\u7622\u764d\u8228", + bang: "\u90a6\u5e2e\u6886\u699c\u8180\u7ed1\u68d2\u78c5\u868c\u9551\u508d\u8c24\u84a1\u8783", + bao: "\u82de\u80de\u5305\u8912\u96f9\u4fdd\u5821\u9971\u5b9d\u62b1\u62a5\u66b4\u8c79\u9c8d\u7206\u52f9\u8446\u5b80\u5b62\u7172\u9e28\u8913\u8db5\u9f85", + bo: "\u5265\u8584\u73bb\u83e0\u64ad\u62e8\u94b5\u6ce2\u535a\u52c3\u640f\u94c2\u7b94\u4f2f\u5e1b\u8236\u8116\u818a\u6e24\u6cca\u9a73\u4eb3\u8543\u5575\u997d\u6a97\u64d8\u7934\u94b9\u9e41\u7c38\u8ddb", + bei: "\u676f\u7891\u60b2\u5351\u5317\u8f88\u80cc\u8d1d\u94a1\u500d\u72c8\u5907\u60eb\u7119\u88ab\u5b5b\u9642\u90b6\u57e4\u84d3\u5457\u602b\u6096\u789a\u9e4e\u8919\u943e", + ben: "\u5954\u82ef\u672c\u7b28\u755a\u574c\u951b", + beng: "\u5d29\u7ef7\u752d\u6cf5\u8e66\u8ff8\u552a\u5623\u750f", + bi: "\u903c\u9f3b\u6bd4\u9119\u7b14\u5f7c\u78a7\u84d6\u853d\u6bd5\u6bd9\u6bd6\u5e01\u5e87\u75f9\u95ed\u655d\u5f0a\u5fc5\u8f9f\u58c1\u81c2\u907f\u965b\u5315\u4ef3\u4ffe\u8298\u835c\u8378\u5421\u54d4\u72f4\u5eb3\u610e\u6ed7\u6fde\u5f3c\u59a3\u5a62\u5b16\u74a7\u8d32\u7540\u94cb\u79d5\u88e8\u7b5a\u7b85\u7be6\u822d\u895e\u8df8\u9ac0", + bian: "\u97ad\u8fb9\u7f16\u8d2c\u6241\u4fbf\u53d8\u535e\u8fa8\u8fa9\u8fab\u904d\u533e\u5f01\u82c4\u5fed\u6c74\u7f0f\u7178\u782d\u78a5\u7a39\u7a86\u8759\u7b3e\u9cca", + biao: "\u6807\u5f6a\u8198\u8868\u5a4a\u9aa0\u98d1\u98d9\u98da\u706c\u9556\u9573\u762d\u88f1\u9cd4", + bie: "\u9cd6\u618b\u522b\u762a\u8e69\u9cd8", + bin: "\u5f6c\u658c\u6fd2\u6ee8\u5bbe\u6448\u50a7\u6d5c\u7f24\u73a2\u6ba1\u8191\u9554\u9acc\u9b13", + bing: "\u5175\u51b0\u67c4\u4e19\u79c9\u997c\u70b3\u75c5\u5e76\u7980\u90b4\u6452\u7ee0\u678b\u69df\u71f9", + bu: "\u6355\u535c\u54fa\u8865\u57e0\u4e0d\u5e03\u6b65\u7c3f\u90e8\u6016\u62ca\u535f\u900b\u74ff\u6661\u949a\u91ad", + ca: "\u64e6\u5693\u7924", + cai: "\u731c\u88c1\u6750\u624d\u8d22\u776c\u8e29\u91c7\u5f69\u83dc\u8521", + can: "\u9910\u53c2\u8695\u6b8b\u60ed\u60e8\u707f\u9a96\u74a8\u7cb2\u9eea", + cang: "\u82cd\u8231\u4ed3\u6ca7\u85cf\u4f27", + cao: "\u64cd\u7cd9\u69fd\u66f9\u8349\u8279\u5608\u6f15\u87ac\u825a", + ce: "\u5395\u7b56\u4fa7\u518c\u6d4b\u5202\u5e3b\u607b", + ceng: "\u5c42\u8e6d\u564c", + cha: "\u63d2\u53c9\u832c\u8336\u67e5\u78b4\u643d\u5bdf\u5c94\u5dee\u8be7\u7339\u9987\u6c4a\u59f9\u6748\u6942\u69ce\u6aab\u9497\u9538\u9572\u8869", + chai: "\u62c6\u67f4\u8c7a\u4faa\u8308\u7625\u867f\u9f87", + chan: "\u6400\u63ba\u8749\u998b\u8c17\u7f20\u94f2\u4ea7\u9610\u98a4\u5181\u8c04\u8c36\u8487\u5edb\u5fcf\u6f7a\u6fb6\u5b71\u7fbc\u5a75\u5b17\u9aa3\u89c7\u7985\u9561\u88e3\u87fe\u8e94", + chang: + "\u660c\u7316\u573a\u5c1d\u5e38\u957f\u507f\u80a0\u5382\u655e\u7545\u5531\u5021\u4f25\u9b2f\u82cc\u83d6\u5f9c\u6005\u60dd\u960a\u5a3c\u5ae6\u6636\u6c05\u9cb3", + chao: "\u8d85\u6284\u949e\u671d\u5632\u6f6e\u5de2\u5435\u7092\u600a\u7ec9\u6641\u8016", + che: "\u8f66\u626f\u64a4\u63a3\u5f7b\u6f88\u577c\u5c6e\u7817", + chen: "\u90f4\u81e3\u8fb0\u5c18\u6668\u5ff1\u6c89\u9648\u8d81\u886c\u79f0\u8c0c\u62bb\u55d4\u5bb8\u741b\u6987\u809c\u80c2\u789c\u9f80", + cheng: + "\u6491\u57ce\u6a59\u6210\u5448\u4e58\u7a0b\u60e9\u6f84\u8bda\u627f\u901e\u9a8b\u79e4\u57d5\u5d4a\u5fb5\u6d48\u67a8\u67fd\u6a18\u665f\u584d\u77a0\u94d6\u88ce\u86cf\u9172", + chi: "\u5403\u75f4\u6301\u5319\u6c60\u8fdf\u5f1b\u9a70\u803b\u9f7f\u4f88\u5c3a\u8d64\u7fc5\u65a5\u70bd\u50ba\u5880\u82aa\u830c\u640b\u53f1\u54e7\u557b\u55e4\u5f73\u996c\u6cb2\u5ab8\u6555\u80dd\u7719\u7735\u9e31\u761b\u892b\u86a9\u87ad\u7b1e\u7bea\u8c49\u8e05\u8e1f\u9b51", + chong: "\u5145\u51b2\u866b\u5d07\u5ba0\u833a\u5fe1\u61a7\u94f3\u825f", + chou: "\u62bd\u916c\u7574\u8e0c\u7a20\u6101\u7b79\u4ec7\u7ef8\u7785\u4e11\u4fe6\u5733\u5e31\u60c6\u6eb4\u59af\u7633\u96e0\u9c8b", + chu: "\u81ed\u521d\u51fa\u6a71\u53a8\u8e87\u9504\u96cf\u6ec1\u9664\u695a\u7840\u50a8\u77d7\u6410\u89e6\u5904\u4e8d\u520d\u61b7\u7ecc\u6775\u696e\u6a17\u870d\u8e70\u9edc", + chuan: + "\u63e3\u5ddd\u7a7f\u693d\u4f20\u8239\u5598\u4e32\u63be\u821b\u60f4\u9044\u5ddb\u6c1a\u948f\u9569\u8221", + chuang: "\u75ae\u7a97\u5e62\u5e8a\u95ef\u521b\u6006", + chui: "\u5439\u708a\u6376\u9524\u5782\u9672\u68f0\u69cc", + chun: "\u6625\u693f\u9187\u5507\u6df3\u7eaf\u8822\u4fc3\u83bc\u6c8c\u80ab\u6710\u9e51\u877d", + chuo: "\u6233\u7ef0\u851f\u8fb6\u8f8d\u955e\u8e14\u9f8a", + ci: "\u75b5\u8328\u78c1\u96cc\u8f9e\u6148\u74f7\u8bcd\u6b64\u523a\u8d50\u6b21\u8360\u5472\u5d6f\u9e5a\u8785\u7ccd\u8d91", + cong: "\u806a\u8471\u56f1\u5306\u4ece\u4e1b\u506c\u82c1\u6dd9\u9aa2\u742e\u7481\u679e", + cu: "\u51d1\u7c97\u918b\u7c07\u731d\u6b82\u8e59", + cuan: "\u8e7f\u7be1\u7a9c\u6c46\u64ba\u6615\u7228", + cui: "\u6467\u5d14\u50ac\u8106\u7601\u7cb9\u6dec\u7fe0\u8403\u60b4\u7480\u69b1\u96b9", + cun: "\u6751\u5b58\u5bf8\u78cb\u5fd6\u76b4", + cuo: "\u64ae\u6413\u63aa\u632b\u9519\u539d\u811e\u9509\u77ec\u75e4\u9e7e\u8e49\u8e9c", + da: "\u642d\u8fbe\u7b54\u7629\u6253\u5927\u8037\u54d2\u55d2\u601b\u59b2\u75b8\u8921\u7b2a\u977c\u9791", + dai: "\u5446\u6b79\u50a3\u6234\u5e26\u6b86\u4ee3\u8d37\u888b\u5f85\u902e\u6020\u57ed\u7519\u5454\u5cb1\u8fe8\u902f\u9a80\u7ed0\u73b3\u9edb", + dan: "\u803d\u62c5\u4e39\u5355\u90f8\u63b8\u80c6\u65e6\u6c2e\u4f46\u60ee\u6de1\u8bde\u5f39\u86cb\u4ebb\u510b\u5369\u840f\u5556\u6fb9\u6a90\u6b9a\u8d55\u7708\u7605\u8043\u7baa", + dang: "\u5f53\u6321\u515a\u8361\u6863\u8c20\u51fc\u83ea\u5b95\u7800\u94db\u88c6", + dao: "\u5200\u6363\u8e48\u5012\u5c9b\u7977\u5bfc\u5230\u7a3b\u60bc\u9053\u76d7\u53e8\u5541\u5fc9\u6d2e\u6c18\u7118\u5fd1\u7e9b", + de: "\u5fb7\u5f97\u7684\u951d", + deng: "\u8e6c\u706f\u767b\u7b49\u77aa\u51f3\u9093\u5654\u5d9d\u6225\u78f4\u956b\u7c26", + di: "\u5824\u4f4e\u6ef4\u8fea\u654c\u7b1b\u72c4\u6da4\u5ae1\u62b5\u5e95\u5730\u8482\u7b2c\u5e1d\u5f1f\u9012\u7f14\u6c10\u7c74\u8bcb\u8c1b\u90b8\u577b\u839c\u837b\u5600\u5a23\u67e2\u68e3\u89cc\u7825\u78b2\u7747\u955d\u7f9d\u9ab6", + dian: "\u98a0\u6382\u6ec7\u7898\u70b9\u5178\u975b\u57ab\u7535\u4f43\u7538\u5e97\u60e6\u5960\u6dc0\u6bbf\u4e36\u963d\u576b\u57dd\u5dc5\u73b7\u765c\u766b\u7c1f\u8e2e", + diao: "\u7889\u53fc\u96d5\u51cb\u5201\u6389\u540a\u9493\u8c03\u8f7a\u94de\u8729\u7c9c\u8c82", + die: "\u8dcc\u7239\u789f\u8776\u8fed\u8c0d\u53e0\u4f5a\u57a4\u581e\u63f2\u558b\u6e2b\u8f76\u7252\u74de\u8936\u800b\u8e40\u9cbd\u9cce", + ding: "\u4e01\u76ef\u53ee\u9489\u9876\u9f0e\u952d\u5b9a\u8ba2\u4e22\u4ec3\u5576\u738e\u815a\u7887\u753a\u94e4\u7594\u8035\u914a", + dong: "\u4e1c\u51ac\u8463\u61c2\u52a8\u680b\u4f97\u606b\u51bb\u6d1e\u578c\u549a\u5cbd\u5cd2\u5902\u6c21\u80e8\u80f4\u7850\u9e2b", + dou: "\u515c\u6296\u6597\u9661\u8c46\u9017\u75d8\u8538\u94ad\u7aa6\u7aac\u86aa\u7bfc\u9161", + du: "\u90fd\u7763\u6bd2\u728a\u72ec\u8bfb\u5835\u7779\u8d4c\u675c\u9540\u809a\u5ea6\u6e21\u5992\u828f\u561f\u6e0e\u691f\u6a50\u724d\u8839\u7b03\u9ad1\u9ee9", + duan: "\u7aef\u77ed\u953b\u6bb5\u65ad\u7f0e\u5f56\u6934\u7145\u7c16", + dui: "\u5806\u5151\u961f\u5bf9\u603c\u619d\u7893", + dun: "\u58a9\u5428\u8e72\u6566\u987f\u56e4\u949d\u76fe\u9041\u7096\u7818\u7905\u76f9\u9566\u8db8", + duo: "\u6387\u54c6\u591a\u593a\u579b\u8eb2\u6735\u8dfa\u8235\u5241\u60f0\u5815\u5484\u54da\u7f0d\u67c1\u94ce\u88f0\u8e31", + e: "\u86fe\u5ce8\u9e45\u4fc4\u989d\u8bb9\u5a25\u6076\u5384\u627c\u904f\u9102\u997f\u5669\u8c14\u57a9\u57ad\u82ca\u83aa\u843c\u5443\u6115\u5c59\u5a40\u8f6d\u66f7\u816d\u786a\u9507\u9537\u9e57\u989a\u9cc4", + en: "\u6069\u84bd\u6441\u5514\u55ef", + er: "\u800c\u513f\u8033\u5c14\u9975\u6d31\u4e8c\u8d30\u8fe9\u73e5\u94d2\u9e38\u9c95", + fa: "\u53d1\u7f5a\u7b4f\u4f10\u4e4f\u9600\u6cd5\u73d0\u57a1\u781d", + fan: "\u85e9\u5e06\u756a\u7ffb\u6a0a\u77fe\u9492\u7e41\u51e1\u70e6\u53cd\u8fd4\u8303\u8d29\u72af\u996d\u6cdb\u8629\u5e61\u72ad\u68b5\u6535\u71d4\u7548\u8e6f", + fang: "\u574a\u82b3\u65b9\u80aa\u623f\u9632\u59a8\u4eff\u8bbf\u7eba\u653e\u531a\u90a1\u5f77\u94ab\u822b\u9c82", + fei: "\u83f2\u975e\u5561\u98de\u80a5\u532a\u8bfd\u5420\u80ba\u5e9f\u6cb8\u8d39\u82be\u72d2\u60b1\u6ddd\u5983\u7ecb\u7eef\u69a7\u8153\u6590\u6249\u7953\u7829\u9544\u75f1\u871a\u7bda\u7fe1\u970f\u9cb1", + fen: "\u82ac\u915a\u5429\u6c1b\u5206\u7eb7\u575f\u711a\u6c7e\u7c89\u594b\u4efd\u5fff\u6124\u7caa\u507e\u7035\u68fc\u610d\u9cbc\u9f22", + feng: "\u4e30\u5c01\u67ab\u8702\u5cf0\u950b\u98ce\u75af\u70fd\u9022\u51af\u7f1d\u8bbd\u5949\u51e4\u4ff8\u9146\u8451\u6ca3\u781c", + fu: "\u4f5b\u5426\u592b\u6577\u80a4\u5b75\u6276\u62c2\u8f90\u5e45\u6c1f\u7b26\u4f0f\u4fd8\u670d\u6d6e\u6daa\u798f\u88b1\u5f17\u752b\u629a\u8f85\u4fef\u91dc\u65a7\u812f\u8151\u5e9c\u8150\u8d74\u526f\u8986\u8d4b\u590d\u5085\u4ed8\u961c\u7236\u8179\u8d1f\u5bcc\u8ba3\u9644\u5987\u7f1a\u5490\u5310\u51eb\u90db\u8299\u82fb\u832f\u83a9\u83d4\u544b\u5e5e\u6ecf\u8274\u5b5a\u9a78\u7ec2\u6874\u8d59\u9efb\u9efc\u7f58\u7a03\u99a5\u864d\u86a8\u8709\u8760\u876e\u9eb8\u8dba\u8dd7\u9cc6", + ga: "\u5676\u560e\u86e4\u5c2c\u5477\u5c15\u5c1c\u65ee\u9486", + gai: "\u8be5\u6539\u6982\u9499\u76d6\u6e89\u4e10\u9654\u5793\u6224\u8d45\u80f2", + gan: "\u5e72\u7518\u6746\u67d1\u7aff\u809d\u8d76\u611f\u79c6\u6562\u8d63\u5769\u82f7\u5c34\u64c0\u6cd4\u6de6\u6f89\u7ec0\u6a44\u65f0\u77f8\u75b3\u9150", + gang: "\u5188\u521a\u94a2\u7f38\u809b\u7eb2\u5c97\u6e2f\u6206\u7f61\u9883\u7b7b", + gong: "\u6760\u5de5\u653b\u529f\u606d\u9f9a\u4f9b\u8eac\u516c\u5bab\u5f13\u5de9\u6c5e\u62f1\u8d21\u5171\u857b\u5efe\u54a3\u73d9\u80b1\u86a3\u86e9\u89e5", + gao: "\u7bd9\u768b\u9ad8\u818f\u7f94\u7cd5\u641e\u9550\u7a3f\u544a\u777e\u8bf0\u90dc\u84bf\u85c1\u7f1f\u69d4\u69c1\u6772\u9506", + ge: "\u54e5\u6b4c\u6401\u6208\u9e3d\u80f3\u7599\u5272\u9769\u845b\u683c\u9601\u9694\u94ec\u4e2a\u5404\u9b32\u4ee1\u54ff\u5865\u55dd\u7ea5\u643f\u8188\u784c\u94ea\u9549\u88bc\u988c\u867c\u8238\u9abc\u9ac2", + gei: "\u7ed9", + gen: "\u6839\u8ddf\u4e98\u831b\u54cf\u826e", + geng: "\u8015\u66f4\u5e9a\u7fb9\u57c2\u803f\u6897\u54fd\u8d53\u9ca0", + gou: "\u94a9\u52fe\u6c9f\u82df\u72d7\u57a2\u6784\u8d2d\u591f\u4f5d\u8bdf\u5ca3\u9058\u5abe\u7f11\u89cf\u5f40\u9e32\u7b31\u7bdd\u97b2", + gu: "\u8f9c\u83c7\u5495\u7b8d\u4f30\u6cbd\u5b64\u59d1\u9f13\u53e4\u86ca\u9aa8\u8c37\u80a1\u6545\u987e\u56fa\u96c7\u560f\u8bc2\u83f0\u54cc\u5d2e\u6c69\u688f\u8f71\u726f\u727f\u80cd\u81cc\u6bc2\u77bd\u7f5f\u94b4\u9522\u74e0\u9e2a\u9e44\u75fc\u86c4\u9164\u89da\u9cb4\u9ab0\u9e58", + gua: "\u522e\u74dc\u5250\u5be1\u6302\u8902\u5366\u8bd6\u5471\u681d\u9e39", + guai: "\u4e56\u62d0\u602a\u54d9", + guan: "\u68fa\u5173\u5b98\u51a0\u89c2\u7ba1\u9986\u7f50\u60ef\u704c\u8d2f\u500c\u839e\u63bc\u6dab\u76e5\u9e73\u9ccf", + guang: "\u5149\u5e7f\u901b\u72b7\u6844\u80f1\u7592", + gui: "\u7470\u89c4\u572d\u7845\u5f52\u9f9f\u95fa\u8f68\u9b3c\u8be1\u7678\u6842\u67dc\u8dea\u8d35\u523d\u5326\u523f\u5e8b\u5b84\u59ab\u6867\u7085\u6677\u7688\u7c0b\u9c91\u9cdc", + gun: "\u8f8a\u6eda\u68cd\u4e28\u886e\u7ef2\u78d9\u9ca7", + guo: "\u9505\u90ed\u56fd\u679c\u88f9\u8fc7\u9998\u8803\u57da\u63b4\u5459\u56d7\u5e3c\u5d1e\u7313\u6901\u8662\u951e\u8052\u872e\u873e\u8748", + ha: "\u54c8", + hai: "\u9ab8\u5b69\u6d77\u6c26\u4ea5\u5bb3\u9a87\u54b4\u55e8\u988f\u91a2", + han: "\u9163\u61a8\u90af\u97e9\u542b\u6db5\u5bd2\u51fd\u558a\u7f55\u7ff0\u64bc\u634d\u65f1\u61be\u608d\u710a\u6c57\u6c49\u9097\u83e1\u6496\u961a\u701a\u6657\u7113\u9894\u86b6\u9f3e", + hen: "\u592f\u75d5\u5f88\u72e0\u6068", + hang: "\u676d\u822a\u6c86\u7ed7\u73e9\u6841", + hao: "\u58d5\u568e\u8c6a\u6beb\u90dd\u597d\u8017\u53f7\u6d69\u8585\u55e5\u5686\u6fe0\u704f\u660a\u7693\u98a2\u869d", + he: "\u5475\u559d\u8377\u83cf\u6838\u79be\u548c\u4f55\u5408\u76d2\u8c89\u9602\u6cb3\u6db8\u8d6b\u8910\u9e64\u8d3a\u8bc3\u52be\u58d1\u85ff\u55d1\u55ec\u9616\u76cd\u86b5\u7fee", + hei: "\u563f\u9ed1", + heng: "\u54fc\u4ea8\u6a2a\u8861\u6052\u8a07\u8605", + hong: "\u8f70\u54c4\u70d8\u8679\u9e3f\u6d2a\u5b8f\u5f18\u7ea2\u9ec9\u8ba7\u836d\u85a8\u95f3\u6cd3", + hou: "\u5589\u4faf\u7334\u543c\u539a\u5019\u540e\u5820\u5f8c\u9005\u760a\u7bcc\u7cc7\u9c8e\u9aba", + hu: "\u547c\u4e4e\u5ffd\u745a\u58f6\u846b\u80e1\u8774\u72d0\u7cca\u6e56\u5f27\u864e\u552c\u62a4\u4e92\u6caa\u6237\u51b1\u553f\u56eb\u5cb5\u7322\u6019\u60da\u6d52\u6ef9\u7425\u69f2\u8f77\u89f3\u70c0\u7173\u623d\u6248\u795c\u9e55\u9e71\u7b0f\u9190\u659b", + hua: "\u82b1\u54d7\u534e\u733e\u6ed1\u753b\u5212\u5316\u8bdd\u5290\u6d4d\u9a85\u6866\u94e7\u7a1e", + huai: "\u69d0\u5f8a\u6000\u6dee\u574f\u8fd8\u8e1d", + huan: "\u6b22\u73af\u6853\u7f13\u6362\u60a3\u5524\u75ea\u8c62\u7115\u6da3\u5ba6\u5e7b\u90c7\u5942\u57b8\u64d0\u571c\u6d39\u6d63\u6f36\u5bf0\u902d\u7f33\u953e\u9ca9\u9b1f", + huang: + "\u8352\u614c\u9ec4\u78fa\u8757\u7c27\u7687\u51f0\u60f6\u714c\u6643\u5e4c\u604d\u8c0e\u968d\u5fa8\u6e5f\u6f62\u9051\u749c\u8093\u7640\u87e5\u7bc1\u9cc7", + hui: "\u7070\u6325\u8f89\u5fbd\u6062\u86d4\u56de\u6bc1\u6094\u6167\u5349\u60e0\u6666\u8d3f\u79fd\u4f1a\u70e9\u6c47\u8bb3\u8bf2\u7ed8\u8bd9\u8334\u835f\u8559\u54d5\u5599\u96b3\u6d04\u5f57\u7f0b\u73f2\u6656\u605a\u867a\u87ea\u9ebe", + hun: "\u8364\u660f\u5a5a\u9b42\u6d51\u6df7\u8be8\u9984\u960d\u6eb7\u7f17", + huo: "\u8c41\u6d3b\u4f19\u706b\u83b7\u6216\u60d1\u970d\u8d27\u7978\u6509\u56af\u5925\u94ac\u952a\u956c\u8020\u8816", + ji: "\u51fb\u573e\u57fa\u673a\u7578\u7a3d\u79ef\u7b95\u808c\u9965\u8ff9\u6fc0\u8ba5\u9e21\u59ec\u7ee9\u7f09\u5409\u6781\u68d8\u8f91\u7c4d\u96c6\u53ca\u6025\u75be\u6c72\u5373\u5ac9\u7ea7\u6324\u51e0\u810a\u5df1\u84df\u6280\u5180\u5b63\u4f0e\u796d\u5242\u60b8\u6d4e\u5bc4\u5bc2\u8ba1\u8bb0\u65e2\u5fcc\u9645\u5993\u7ee7\u7eaa\u5c45\u4e0c\u4e69\u525e\u4f76\u4f74\u8114\u58bc\u82a8\u82b0\u8401\u84ba\u857a\u638e\u53fd\u54ad\u54dc\u5527\u5c8c\u5d74\u6d0e\u5f50\u5c50\u9aa5\u757f\u7391\u696b\u6b9b\u621f\u6222\u8d4d\u89ca\u7284\u9f51\u77f6\u7f81\u5d47\u7a37\u7620\u7635\u866e\u7b08\u7b04\u66a8\u8dfb\u8dfd\u9701\u9c9a\u9cab\u9afb\u9e82", + jia: "\u5609\u67b7\u5939\u4f73\u5bb6\u52a0\u835a\u988a\u8d3e\u7532\u94be\u5047\u7a3c\u4ef7\u67b6\u9a7e\u5ac1\u4f3d\u90cf\u62ee\u5cac\u6d43\u8fe6\u73c8\u621b\u80db\u605d\u94d7\u9553\u75c2\u86f1\u7b33\u8888\u8dcf", + jian: "\u6b7c\u76d1\u575a\u5c16\u7b3a\u95f4\u714e\u517c\u80a9\u8270\u5978\u7f04\u8327\u68c0\u67ec\u78b1\u7877\u62e3\u6361\u7b80\u4fed\u526a\u51cf\u8350\u69db\u9274\u8df5\u8d31\u89c1\u952e\u7bad\u4ef6\u5065\u8230\u5251\u996f\u6e10\u6e85\u6da7\u5efa\u50ed\u8c0f\u8c2b\u83c5\u84b9\u641b\u56dd\u6e54\u8e47\u8b07\u7f23\u67a7\u67d9\u6957\u620b\u622c\u726e\u728d\u6bfd\u8171\u7751\u950f\u9e63\u88e5\u7b15\u7bb4\u7fe6\u8dbc\u8e3a\u9ca3\u97af", + jiang: + "\u50f5\u59dc\u5c06\u6d46\u6c5f\u7586\u848b\u6868\u5956\u8bb2\u5320\u9171\u964d\u8333\u6d1a\u7edb\u7f30\u729f\u7913\u8029\u7ce8\u8c47", + jiao: "\u8549\u6912\u7901\u7126\u80f6\u4ea4\u90ca\u6d47\u9a84\u5a07\u56bc\u6405\u94f0\u77eb\u4fa5\u811a\u72e1\u89d2\u997a\u7f34\u7ede\u527f\u6559\u9175\u8f7f\u8f83\u53eb\u4f7c\u50ec\u832d\u6322\u564d\u5ce4\u5fbc\u59e3\u7e9f\u656b\u768e\u9e6a\u86df\u91ae\u8de4\u9c9b", + jie: "\u7a96\u63ed\u63a5\u7686\u79f8\u8857\u9636\u622a\u52ab\u8282\u6854\u6770\u6377\u776b\u7aed\u6d01\u7ed3\u89e3\u59d0\u6212\u85c9\u82a5\u754c\u501f\u4ecb\u75a5\u8beb\u5c4a\u5048\u8ba6\u8bd8\u5588\u55df\u736c\u5a55\u5b51\u6840\u7352\u78a3\u9534\u7596\u88b7\u9889\u86a7\u7faf\u9c92\u9ab1\u9aeb", + jin: "\u5dfe\u7b4b\u65a4\u91d1\u4eca\u6d25\u895f\u7d27\u9526\u4ec5\u8c28\u8fdb\u9773\u664b\u7981\u8fd1\u70ec\u6d78\u5c3d\u537a\u8369\u5807\u5664\u9991\u5ed1\u5997\u7f19\u747e\u69ff\u8d46\u89d0\u9485\u9513\u887f\u77dc", + jing: "\u52b2\u8346\u5162\u830e\u775b\u6676\u9cb8\u4eac\u60ca\u7cbe\u7cb3\u7ecf\u4e95\u8b66\u666f\u9888\u9759\u5883\u656c\u955c\u5f84\u75c9\u9756\u7adf\u7ade\u51c0\u522d\u5106\u9631\u83c1\u734d\u61ac\u6cfe\u8ff3\u5f2a\u5a67\u80bc\u80eb\u8148\u65cc", + jiong: "\u70af\u7a98\u5182\u8fe5\u6243", + jiu: "\u63ea\u7a76\u7ea0\u7396\u97ed\u4e45\u7078\u4e5d\u9152\u53a9\u6551\u65e7\u81fc\u8205\u548e\u5c31\u759a\u50e6\u557e\u9604\u67e9\u6855\u9e6b\u8d73\u9b0f", + ju: "\u97a0\u62d8\u72d9\u75bd\u9a79\u83ca\u5c40\u5480\u77e9\u4e3e\u6cae\u805a\u62d2\u636e\u5de8\u5177\u8ddd\u8e1e\u952f\u4ff1\u53e5\u60e7\u70ac\u5267\u5028\u8bb5\u82e3\u82f4\u8392\u63ac\u907d\u5c66\u741a\u67b8\u6910\u6998\u6989\u6a58\u728b\u98d3\u949c\u9514\u7aad\u88fe\u8d84\u91b5\u8e3d\u9f83\u96ce\u97ab", + juan: "\u6350\u9e43\u5a1f\u5026\u7737\u5377\u7ee2\u9104\u72f7\u6d93\u684a\u8832\u9529\u954c\u96bd", + jue: "\u6485\u652b\u6289\u6398\u5014\u7235\u89c9\u51b3\u8bc0\u7edd\u53a5\u5282\u8c32\u77cd\u8568\u5658\u5d1b\u7357\u5b53\u73cf\u6877\u6a5b\u721d\u9562\u8e76\u89d6", + jun: "\u5747\u83cc\u94a7\u519b\u541b\u5cfb\u4fca\u7ae3\u6d5a\u90e1\u9a8f\u6343\u72fb\u76b2\u7b60\u9e87", + ka: "\u5580\u5496\u5361\u4f67\u5494\u80e9", + ke: "\u54af\u5777\u82db\u67ef\u68f5\u78d5\u9897\u79d1\u58f3\u54b3\u53ef\u6e34\u514b\u523b\u5ba2\u8bfe\u5ca2\u606a\u6e98\u9a92\u7f02\u73c2\u8f72\u6c2a\u778c\u94b6\u75b4\u7aa0\u874c\u9ac1", + kai: "\u5f00\u63e9\u6977\u51ef\u6168\u5240\u57b2\u8488\u5ffe\u607a\u94e0\u950e", + kan: "\u520a\u582a\u52d8\u574e\u780d\u770b\u4f83\u51f5\u83b0\u83b6\u6221\u9f9b\u77b0", + kang: "\u5eb7\u6177\u7ce0\u625b\u6297\u4ea2\u7095\u5751\u4f09\u95f6\u94aa", + kao: "\u8003\u62f7\u70e4\u9760\u5c3b\u6832\u7292\u94d0", + ken: "\u80af\u5543\u57a6\u6073\u57a0\u88c9\u9880", + keng: "\u542d\u5fd0\u94ff", + kong: "\u7a7a\u6050\u5b54\u63a7\u5025\u5d06\u7b9c", + kou: "\u62a0\u53e3\u6263\u5bc7\u82a4\u853b\u53e9\u770d\u7b58", + ku: "\u67af\u54ed\u7a9f\u82e6\u9177\u5e93\u88e4\u5233\u5800\u55be\u7ed4\u9ab7", + kua: "\u5938\u57ae\u630e\u8de8\u80ef\u4f89", + kuai: "\u5757\u7b77\u4fa9\u5feb\u84af\u90d0\u8489\u72ef\u810d", + kuan: "\u5bbd\u6b3e\u9acb", + kuang: + "\u5321\u7b50\u72c2\u6846\u77ff\u7736\u65f7\u51b5\u8bd3\u8bf3\u909d\u5739\u593c\u54d0\u7ea9\u8d36", + kui: "\u4e8f\u76d4\u5cbf\u7aa5\u8475\u594e\u9b41\u5080\u9988\u6127\u6e83\u9997\u532e\u5914\u9697\u63c6\u55b9\u559f\u609d\u6126\u9615\u9035\u668c\u777d\u8069\u8770\u7bd1\u81fe\u8dec", + kun: "\u5764\u6606\u6346\u56f0\u6083\u9603\u7428\u951f\u918c\u9cb2\u9ae1", + kuo: "\u62ec\u6269\u5ed3\u9614\u86de", + la: "\u5783\u62c9\u5587\u8721\u814a\u8fa3\u5566\u524c\u647a\u908b\u65ef\u782c\u760c", + lai: "\u83b1\u6765\u8d56\u5d03\u5f95\u6d9e\u6fd1\u8d49\u7750\u94fc\u765e\u7c41", + lan: "\u84dd\u5a6a\u680f\u62e6\u7bee\u9611\u5170\u6f9c\u8c30\u63fd\u89c8\u61d2\u7f06\u70c2\u6ee5\u5549\u5c9a\u61d4\u6f24\u6984\u6593\u7f71\u9567\u8934", + lang: "\u7405\u6994\u72fc\u5eca\u90ce\u6717\u6d6a\u83a8\u8497\u5577\u9606\u9512\u7a02\u8782", + lao: "\u635e\u52b3\u7262\u8001\u4f6c\u59e5\u916a\u70d9\u6d9d\u5520\u5d02\u6833\u94d1\u94f9\u75e8\u91aa", + le: "\u52d2\u4e50\u808b\u4ec2\u53fb\u561e\u6cd0\u9cd3", + lei: "\u96f7\u956d\u857e\u78ca\u7d2f\u5121\u5792\u64c2\u7c7b\u6cea\u7fb8\u8bd4\u837d\u54a7\u6f2f\u5ad8\u7f27\u6a91\u8012\u9179", + ling: "\u68f1\u51b7\u62ce\u73b2\u83f1\u96f6\u9f84\u94c3\u4f36\u7f9a\u51cc\u7075\u9675\u5cad\u9886\u53e6\u4ee4\u9143\u5844\u82d3\u5464\u56f9\u6ce0\u7eeb\u67c3\u68c2\u74f4\u8046\u86c9\u7fce\u9cae", + leng: "\u695e\u6123", + li: "\u5398\u68a8\u7281\u9ece\u7bf1\u72f8\u79bb\u6f13\u7406\u674e\u91cc\u9ca4\u793c\u8389\u8354\u540f\u6817\u4e3d\u5389\u52b1\u783e\u5386\u5229\u5088\u4f8b\u4fd0\u75e2\u7acb\u7c92\u6ca5\u96b6\u529b\u7483\u54e9\u4fea\u4fda\u90e6\u575c\u82c8\u8385\u84e0\u85dc\u6369\u5456\u5533\u55b1\u7301\u6ea7\u6fa7\u9026\u5a0c\u5ae0\u9a8a\u7f21\u73de\u67a5\u680e\u8f79\u623e\u783a\u8a48\u7f79\u9502\u9e42\u75a0\u75ac\u86ce\u870a\u8821\u7b20\u7be5\u7c9d\u91b4\u8dde\u96f3\u9ca1\u9ce2\u9ee7", + lian: "\u4fe9\u8054\u83b2\u8fde\u9570\u5ec9\u601c\u6d9f\u5e18\u655b\u8138\u94fe\u604b\u70bc\u7ec3\u631b\u8539\u5941\u6f4b\u6fc2\u5a08\u740f\u695d\u6b93\u81c1\u81a6\u88e2\u880a\u9ca2", + liang: + "\u7cae\u51c9\u6881\u7cb1\u826f\u4e24\u8f86\u91cf\u667e\u4eae\u8c05\u589a\u690b\u8e09\u9753\u9b49", + liao: "\u64a9\u804a\u50da\u7597\u71ce\u5be5\u8fbd\u6f66\u4e86\u6482\u9563\u5ed6\u6599\u84fc\u5c25\u5639\u7360\u5bee\u7f2d\u948c\u9e69\u8022", + lie: "\u5217\u88c2\u70c8\u52a3\u730e\u51bd\u57d2\u6d0c\u8d94\u8e90\u9b23", + lin: "\u7433\u6797\u78f7\u9716\u4e34\u90bb\u9cde\u6dcb\u51db\u8d41\u541d\u853a\u5d99\u5eea\u9074\u6aa9\u8f9a\u77b5\u7cbc\u8e8f\u9e9f", + liu: "\u6e9c\u7409\u69b4\u786b\u998f\u7559\u5218\u7624\u6d41\u67f3\u516d\u62a1\u507b\u848c\u6cd6\u6d4f\u905b\u9a9d\u7efa\u65d2\u7198\u950d\u954f\u9e68\u938f", + long: "\u9f99\u804b\u5499\u7b3c\u7abf\u9686\u5784\u62e2\u9647\u5f04\u5785\u830f\u6cf7\u73d1\u680a\u80e7\u783b\u7643", + lou: "\u697c\u5a04\u6402\u7bd3\u6f0f\u964b\u55bd\u5d5d\u9542\u7618\u8027\u877c\u9ac5", + lu: "\u82a6\u5362\u9885\u5e90\u7089\u63b3\u5364\u864f\u9c81\u9e93\u788c\u9732\u8def\u8d42\u9e7f\u6f5e\u7984\u5f55\u9646\u622e\u5786\u6445\u64b8\u565c\u6cf8\u6e0c\u6f09\u7490\u680c\u6a79\u8f73\u8f82\u8f98\u6c07\u80ea\u9565\u9e2c\u9e6d\u7c0f\u823b\u9c88", + lv: "\u9a74\u5415\u94dd\u4fa3\u65c5\u5c65\u5c61\u7f15\u8651\u6c2f\u5f8b\u7387\u6ee4\u7eff\u634b\u95fe\u6988\u8182\u7a06\u891b", + luan: "\u5ce6\u5b6a\u6ee6\u5375\u4e71\u683e\u9e3e\u92ae", + lue: "\u63a0\u7565\u950a", + lun: "\u8f6e\u4f26\u4ed1\u6ca6\u7eb6\u8bba\u56f5", + luo: "\u841d\u87ba\u7f57\u903b\u9523\u7ba9\u9aa1\u88f8\u843d\u6d1b\u9a86\u7edc\u502e\u8366\u645e\u7321\u6cfa\u6924\u8136\u9559\u7630\u96d2", + ma: "\u5988\u9ebb\u739b\u7801\u8682\u9a6c\u9a82\u561b\u5417\u551b\u72b8\u5b37\u6769\u9ebd", + mai: "\u57cb\u4e70\u9ea6\u5356\u8fc8\u8109\u52a2\u836c\u54aa\u973e", + man: "\u7792\u9992\u86ee\u6ee1\u8513\u66fc\u6162\u6f2b\u8c29\u5881\u5e54\u7f26\u71b3\u9558\u989f\u87a8\u9cd7\u9794", + mang: "\u8292\u832b\u76f2\u5fd9\u83bd\u9099\u6f2d\u6726\u786d\u87d2", + meng: "\u6c13\u840c\u8499\u6aac\u76df\u9530\u731b\u68a6\u5b5f\u52d0\u750d\u77a2\u61f5\u791e\u867b\u8722\u8813\u824b\u8268\u9efe", + miao: "\u732b\u82d7\u63cf\u7784\u85d0\u79d2\u6e3a\u5e99\u5999\u55b5\u9088\u7f08\u7f2a\u676a\u6dfc\u7707\u9e4b\u8731", + mao: "\u8305\u951a\u6bdb\u77db\u94c6\u536f\u8302\u5192\u5e3d\u8c8c\u8d38\u4f94\u88a4\u52d6\u8306\u5cc1\u7441\u6634\u7266\u8004\u65c4\u61cb\u7780\u86d1\u8765\u87ca\u9ae6", + me: "\u4e48", + mei: "\u73ab\u679a\u6885\u9176\u9709\u7164\u6ca1\u7709\u5a92\u9541\u6bcf\u7f8e\u6627\u5bd0\u59b9\u5a9a\u5776\u8393\u5d4b\u7338\u6d7c\u6e44\u6963\u9545\u9e5b\u8882\u9b45", + men: "\u95e8\u95f7\u4eec\u626a\u739f\u7116\u61d1\u9494", + mi: "\u772f\u919a\u9761\u7cdc\u8ff7\u8c1c\u5f25\u7c73\u79d8\u89c5\u6ccc\u871c\u5bc6\u5e42\u8288\u5196\u8c27\u863c\u5627\u7315\u736f\u6c68\u5b93\u5f2d\u8112\u6549\u7cf8\u7e3b\u9e8b", + mian: "\u68c9\u7720\u7ef5\u5195\u514d\u52c9\u5a29\u7f05\u9762\u6c94\u6e4e\u817c\u7704", + mie: "\u8511\u706d\u54a9\u881b\u7bfe", + min: "\u6c11\u62bf\u76bf\u654f\u60af\u95fd\u82e0\u5cb7\u95f5\u6cef\u73c9", + ming: "\u660e\u879f\u9e23\u94ed\u540d\u547d\u51a5\u8317\u6e9f\u669d\u7791\u9169", + miu: "\u8c2c", + mo: "\u6478\u6479\u8611\u6a21\u819c\u78e8\u6469\u9b54\u62b9\u672b\u83ab\u58a8\u9ed8\u6cab\u6f20\u5bde\u964c\u8c1f\u8309\u84e6\u998d\u5aeb\u9546\u79e3\u763c\u8031\u87c6\u8c8a\u8c98", + mou: "\u8c0b\u725f\u67d0\u53b6\u54de\u5a7a\u7738\u936a", + mu: "\u62c7\u7261\u4ea9\u59c6\u6bcd\u5893\u66ae\u5e55\u52df\u6155\u6728\u76ee\u7766\u7267\u7a46\u4eeb\u82dc\u5452\u6c90\u6bea\u94bc", + na: "\u62ff\u54ea\u5450\u94a0\u90a3\u5a1c\u7eb3\u5185\u637a\u80ad\u954e\u8872\u7bac", + nai: "\u6c16\u4e43\u5976\u8010\u5948\u9f10\u827f\u8418\u67f0", + nan: "\u5357\u7537\u96be\u56ca\u5583\u56e1\u6960\u8169\u877b\u8d67", + nao: "\u6320\u8111\u607c\u95f9\u5b6c\u57b4\u7331\u7459\u7847\u94d9\u86f2", + ne: "\u6dd6\u5462\u8bb7", + nei: "\u9981", + nen: "\u5ae9\u80fd\u6798\u6041", + ni: "\u59ae\u9713\u502a\u6ce5\u5c3c\u62df\u4f60\u533f\u817b\u9006\u6eba\u4f32\u576d\u730a\u6029\u6ee0\u6635\u65ce\u7962\u615d\u7768\u94cc\u9cb5", + nian: "\u852b\u62c8\u5e74\u78be\u64b5\u637b\u5ff5\u5eff\u8f87\u9ecf\u9c87\u9cb6", + niang: "\u5a18\u917f", + niao: "\u9e1f\u5c3f\u8311\u5b32\u8132\u8885", + nie: "\u634f\u8042\u5b7d\u556e\u954a\u954d\u6d85\u4e5c\u9667\u8616\u55eb\u8080\u989e\u81ec\u8e51", + nin: "\u60a8\u67e0", + ning: "\u72de\u51dd\u5b81\u62e7\u6cde\u4f5e\u84e5\u549b\u752f\u804d", + niu: "\u725b\u626d\u94ae\u7ebd\u72c3\u5ff8\u599e\u86b4", + nong: "\u8113\u6d53\u519c\u4fac", + nu: "\u5974\u52aa\u6012\u5476\u5e11\u5f29\u80ec\u5b65\u9a7d", + nv: "\u5973\u6067\u9495\u8844", + nuan: "\u6696", + nuenue: "\u8650", + nue: "\u759f\u8c11", + nuo: "\u632a\u61e6\u7cef\u8bfa\u50a9\u6426\u558f\u9518", + ou: "\u54e6\u6b27\u9e25\u6bb4\u85d5\u5455\u5076\u6ca4\u6004\u74ef\u8026", + pa: "\u556a\u8db4\u722c\u5e15\u6015\u7436\u8469\u7b62", + pai: "\u62cd\u6392\u724c\u5f98\u6e43\u6d3e\u4ff3\u848e", + pan: "\u6500\u6f58\u76d8\u78d0\u76fc\u7554\u5224\u53db\u723f\u6cee\u88a2\u897b\u87e0\u8e52", + pang: "\u4e53\u5e9e\u65c1\u802a\u80d6\u6ec2\u9004", + pao: "\u629b\u5486\u5228\u70ae\u888d\u8dd1\u6ce1\u530f\u72cd\u5e96\u812c\u75b1", + pei: "\u5478\u80da\u57f9\u88f4\u8d54\u966a\u914d\u4f69\u6c9b\u638a\u8f94\u5e14\u6de0\u65c6\u952b\u9185\u9708", + pen: "\u55b7\u76c6\u6e53", + peng: "\u7830\u62a8\u70f9\u6f8e\u5f6d\u84ec\u68da\u787c\u7bf7\u81a8\u670b\u9e4f\u6367\u78b0\u576f\u580b\u562d\u6026\u87db", + pi: "\u7812\u9739\u6279\u62ab\u5288\u7435\u6bd7\u5564\u813e\u75b2\u76ae\u5339\u75de\u50fb\u5c41\u8b6c\u4e15\u9674\u90b3\u90eb\u572e\u9f19\u64d7\u567c\u5e80\u5ab2\u7eb0\u6787\u7513\u7765\u7f74\u94cd\u75e6\u7656\u758b\u868d\u8c94", + pian: "\u7bc7\u504f\u7247\u9a97\u8c1d\u9a88\u728f\u80fc\u890a\u7fe9\u8e41", + piao: "\u98d8\u6f02\u74e2\u7968\u527d\u560c\u5ad6\u7f25\u6b8d\u779f\u87b5", + pie: "\u6487\u77a5\u4e3f\u82e4\u6c15", + pin: "\u62fc\u9891\u8d2b\u54c1\u8058\u62da\u59d8\u5ad4\u6980\u725d\u98a6", + ping: "\u4e52\u576a\u82f9\u840d\u5e73\u51ed\u74f6\u8bc4\u5c4f\u4fdc\u5a09\u67b0\u9c86", + po: "\u5761\u6cfc\u9887\u5a46\u7834\u9b44\u8feb\u7c95\u53f5\u9131\u6ea5\u73c0\u948b\u94b7\u76a4\u7b38", + pou: "\u5256\u88d2\u8e23", + pu: "\u6251\u94fa\u4ec6\u8386\u8461\u83e9\u84b2\u57d4\u6734\u5703\u666e\u6d66\u8c31\u66dd\u7011\u530d\u5657\u6fee\u749e\u6c06\u9564\u9568\u8e7c", + qi: "\u671f\u6b3a\u6816\u621a\u59bb\u4e03\u51c4\u6f06\u67d2\u6c8f\u5176\u68cb\u5947\u6b67\u7566\u5d0e\u8110\u9f50\u65d7\u7948\u7941\u9a91\u8d77\u5c82\u4e5e\u4f01\u542f\u5951\u780c\u5668\u6c14\u8fc4\u5f03\u6c7d\u6ce3\u8bab\u4e9f\u4e93\u573b\u8291\u840b\u847a\u5601\u5c7a\u5c90\u6c54\u6dc7\u9a90\u7eee\u742a\u7426\u675e\u6864\u69ed\u6b39\u797a\u61a9\u789b\u86f4\u871e\u7da6\u7dae\u8dbf\u8e4a\u9ccd\u9e92", + qia: "\u6390\u6070\u6d3d\u845c", + qian: "\u7275\u6266\u948e\u94c5\u5343\u8fc1\u7b7e\u4edf\u8c26\u4e7e\u9ed4\u94b1\u94b3\u524d\u6f5c\u9063\u6d45\u8c34\u5811\u5d4c\u6b20\u6b49\u4f65\u9621\u828a\u82a1\u8368\u63ae\u5c8d\u60ad\u614a\u9a9e\u6434\u8930\u7f31\u6920\u80b7\u6106\u94a4\u8654\u7b9d", + qiang: + "\u67aa\u545b\u8154\u7f8c\u5899\u8537\u5f3a\u62a2\u5af1\u6a2f\u6217\u709d\u9516\u9535\u956a\u8941\u8723\u7f9f\u8deb\u8dc4", + qiao: "\u6a47\u9539\u6572\u6084\u6865\u77a7\u4e54\u4fa8\u5de7\u9798\u64ac\u7fd8\u5ced\u4fcf\u7a8d\u5281\u8bee\u8c2f\u835e\u6100\u6194\u7f32\u6a35\u6bf3\u7857\u8df7\u9792", + qie: "\u5207\u8304\u4e14\u602f\u7a83\u90c4\u553c\u60ec\u59be\u6308\u9532\u7ba7", + qin: "\u94a6\u4fb5\u4eb2\u79e6\u7434\u52e4\u82b9\u64d2\u79bd\u5bdd\u6c81\u82a9\u84c1\u8572\u63ff\u5423\u55ea\u5659\u6eb1\u6a8e\u8793\u887e", + qing: "\u9752\u8f7b\u6c22\u503e\u537f\u6e05\u64ce\u6674\u6c30\u60c5\u9877\u8bf7\u5e86\u5029\u82d8\u570a\u6aa0\u78ec\u873b\u7f44\u7b90\u8b26\u9cad\u9ee5", + qiong: "\u743c\u7a77\u909b\u8315\u7a79\u7b47\u928e", + qiu: "\u79cb\u4e18\u90b1\u7403\u6c42\u56da\u914b\u6cc5\u4fc5\u6c3d\u5def\u827d\u72b0\u6e6b\u9011\u9052\u6978\u8d47\u9e20\u866c\u86af\u8764\u88d8\u7cd7\u9cc5\u9f3d", + qu: "\u8d8b\u533a\u86c6\u66f2\u8eaf\u5c48\u9a71\u6e20\u53d6\u5a36\u9f8b\u8da3\u53bb\u8bce\u52ac\u8556\u8627\u5c96\u8862\u9612\u74a9\u89d1\u6c0d\u795b\u78f2\u766f\u86d0\u883c\u9eb4\u77bf\u9ee2", + quan: "\u5708\u98a7\u6743\u919b\u6cc9\u5168\u75ca\u62f3\u72ac\u5238\u529d\u8be0\u8343\u737e\u609b\u7efb\u8f81\u754e\u94e8\u8737\u7b4c\u9b08", + que: "\u7f3a\u7094\u7638\u5374\u9e4a\u69b7\u786e\u96c0\u9619\u60ab", + qun: "\u88d9\u7fa4\u9021", + ran: "\u7136\u71c3\u5189\u67d3\u82d2\u9aef", + rang: "\u74e4\u58e4\u6518\u56b7\u8ba9\u79b3\u7a70", + rao: "\u9976\u6270\u7ed5\u835b\u5a06\u6861", + ruo: "\u60f9\u82e5\u5f31", + re: "\u70ed\u504c", + ren: "\u58ec\u4ec1\u4eba\u5fcd\u97e7\u4efb\u8ba4\u5203\u598a\u7eab\u4ede\u834f\u845a\u996a\u8f6b\u7a14\u887d", + reng: "\u6254\u4ecd", + ri: "\u65e5", + rong: "\u620e\u8338\u84c9\u8363\u878d\u7194\u6eb6\u5bb9\u7ed2\u5197\u5d58\u72e8\u7f1b\u6995\u877e", + rou: "\u63c9\u67d4\u8089\u7cc5\u8e42\u97a3", + ru: "\u8339\u8815\u5112\u5b7a\u5982\u8fb1\u4e73\u6c5d\u5165\u8925\u84d0\u85b7\u5685\u6d33\u6ebd\u6fe1\u94f7\u8966\u98a5", + ruan: "\u8f6f\u962e\u670a", + rui: "\u854a\u745e\u9510\u82ae\u8564\u777f\u868b", + run: "\u95f0\u6da6", + sa: "\u6492\u6d12\u8428\u5345\u4ee8\u6332\u98d2", + sai: "\u816e\u9cc3\u585e\u8d5b\u567b", + san: "\u4e09\u53c1\u4f1e\u6563\u5f61\u9993\u6c35\u6bf5\u7cc1\u9730", + sang: "\u6851\u55d3\u4e27\u6421\u78c9\u98a1", + sao: "\u6414\u9a9a\u626b\u5ac2\u57fd\u81ca\u7619\u9ccb", + se: "\u745f\u8272\u6da9\u556c\u94e9\u94ef\u7a51", + sen: "\u68ee", + seng: "\u50e7", + sha: "\u838e\u7802\u6740\u5239\u6c99\u7eb1\u50bb\u5565\u715e\u810e\u6b43\u75e7\u88df\u970e\u9ca8", + shai: "\u7b5b\u6652\u917e", + shan: "\u73ca\u82eb\u6749\u5c71\u5220\u717d\u886b\u95ea\u9655\u64c5\u8d61\u81b3\u5584\u6c55\u6247\u7f2e\u5261\u8baa\u912f\u57cf\u829f\u6f78\u59d7\u9a9f\u81bb\u9490\u759d\u87ee\u8222\u8dda\u9cdd", + shang: + "\u5892\u4f24\u5546\u8d4f\u664c\u4e0a\u5c1a\u88f3\u57a7\u7ef1\u6b87\u71b5\u89de", + shao: "\u68a2\u634e\u7a0d\u70e7\u828d\u52fa\u97f6\u5c11\u54e8\u90b5\u7ecd\u52ad\u82d5\u6f72\u86f8\u7b24\u7b72\u8244", + she: "\u5962\u8d4a\u86c7\u820c\u820d\u8d66\u6444\u5c04\u6151\u6d89\u793e\u8bbe\u538d\u4f58\u731e\u7572\u9e9d", + shen: "\u7837\u7533\u547b\u4f38\u8eab\u6df1\u5a20\u7ec5\u795e\u6c88\u5ba1\u5a76\u751a\u80be\u614e\u6e17\u8bdc\u8c02\u5432\u54c2\u6e16\u6939\u77e7\u8703", + sheng: + "\u58f0\u751f\u7525\u7272\u5347\u7ef3\u7701\u76db\u5269\u80dc\u5723\u4e1e\u6e11\u5ab5\u771a\u7b19", + shi: "\u5e08\u5931\u72ee\u65bd\u6e7f\u8bd7\u5c38\u8671\u5341\u77f3\u62fe\u65f6\u4ec0\u98df\u8680\u5b9e\u8bc6\u53f2\u77e2\u4f7f\u5c4e\u9a76\u59cb\u5f0f\u793a\u58eb\u4e16\u67ff\u4e8b\u62ed\u8a93\u901d\u52bf\u662f\u55dc\u566c\u9002\u4ed5\u4f8d\u91ca\u9970\u6c0f\u5e02\u6043\u5ba4\u89c6\u8bd5\u8c25\u57d8\u83b3\u84cd\u5f11\u5511\u9963\u8f7c\u8006\u8d33\u70bb\u793b\u94c8\u94ca\u87ab\u8210\u7b6e\u8c55\u9ca5\u9cba", + shou: "\u6536\u624b\u9996\u5b88\u5bff\u6388\u552e\u53d7\u7626\u517d\u624c\u72e9\u7ef6\u824f", + shu: "\u852c\u67a2\u68b3\u6b8a\u6292\u8f93\u53d4\u8212\u6dd1\u758f\u4e66\u8d4e\u5b70\u719f\u85af\u6691\u66d9\u7f72\u8700\u9ecd\u9f20\u5c5e\u672f\u8ff0\u6811\u675f\u620d\u7ad6\u5885\u5eb6\u6570\u6f31\u6055\u500f\u587e\u83fd\u5fc4\u6cad\u6d91\u6f8d\u59dd\u7ebe\u6bf9\u8167\u6bb3\u956f\u79eb\u9e6c", + shua: "\u5237\u800d\u5530\u6dae", + shuai: "\u6454\u8870\u7529\u5e05\u87c0", + shuan: "\u6813\u62f4\u95e9", + shuang: "\u971c\u53cc\u723d\u5b40", + shui: "\u8c01\u6c34\u7761\u7a0e", + shun: "\u542e\u77ac\u987a\u821c\u6042", + shuo: "\u8bf4\u7855\u6714\u70c1\u84b4\u6420\u55cd\u6fef\u5981\u69ca\u94c4", + si: "\u65af\u6495\u5636\u601d\u79c1\u53f8\u4e1d\u6b7b\u8086\u5bfa\u55e3\u56db\u4f3a\u4f3c\u9972\u5df3\u53ae\u4fdf\u5155\u83e5\u549d\u6c5c\u6cd7\u6f8c\u59d2\u9a77\u7f0c\u7940\u7960\u9536\u9e36\u801c\u86f3\u7b25", + song: "\u677e\u8038\u6002\u9882\u9001\u5b8b\u8bbc\u8bf5\u51c7\u83d8\u5d27\u5d69\u5fea\u609a\u6dde\u7ae6", + sou: "\u641c\u8258\u64de\u55fd\u53df\u55d6\u55fe\u998a\u6eb2\u98d5\u778d\u953c\u878b", + su: "\u82cf\u9165\u4fd7\u7d20\u901f\u7c9f\u50f3\u5851\u6eaf\u5bbf\u8bc9\u8083\u5919\u8c21\u850c\u55c9\u612b\u7c0c\u89eb\u7a23", + suan: "\u9178\u849c\u7b97", + sui: "\u867d\u968b\u968f\u7ee5\u9ad3\u788e\u5c81\u7a57\u9042\u96a7\u795f\u84d1\u51ab\u8c07\u6fc9\u9083\u71e7\u772d\u7762", + sun: "\u5b59\u635f\u7b0b\u836a\u72f2\u98e7\u69ab\u8de3\u96bc", + suo: "\u68ad\u5506\u7f29\u7410\u7d22\u9501\u6240\u5522\u55e6\u5a11\u686b\u7743\u7fa7", + ta: "\u584c\u4ed6\u5b83\u5979\u5854\u736d\u631e\u8e4b\u8e0f\u95fc\u6ebb\u9062\u69bb\u6c93", + tai: "\u80ce\u82d4\u62ac\u53f0\u6cf0\u915e\u592a\u6001\u6c70\u90b0\u85b9\u80bd\u70b1\u949b\u8dc6\u9c90", + tan: "\u574d\u644a\u8d2a\u762b\u6ee9\u575b\u6a80\u75f0\u6f6d\u8c2d\u8c08\u5766\u6bef\u8892\u78b3\u63a2\u53f9\u70ad\u90ef\u8548\u6619\u94bd\u952c\u8983", + tang: "\u6c64\u5858\u642a\u5802\u68e0\u819b\u5510\u7cd6\u50a5\u9967\u6e8f\u746d\u94f4\u9557\u8025\u8797\u87b3\u7fb0\u91a3", + thang: "\u5018\u8eba\u6dcc", + theng: "\u8d9f\u70eb", + tao: "\u638f\u6d9b\u6ed4\u7ee6\u8404\u6843\u9003\u6dd8\u9676\u8ba8\u5957\u6311\u9f17\u5555\u97ec\u9955", + te: "\u7279", + teng: "\u85e4\u817e\u75bc\u8a8a\u6ed5", + ti: "\u68af\u5254\u8e22\u9511\u63d0\u9898\u8e44\u557c\u4f53\u66ff\u568f\u60d5\u6d95\u5243\u5c49\u8351\u608c\u9016\u7ee8\u7f07\u9e48\u88fc\u918d", + tian: "\u5929\u6dfb\u586b\u7530\u751c\u606c\u8214\u8146\u63ad\u5fdd\u9617\u6b84\u754b\u94bf\u86ba", + tiao: "\u6761\u8fe2\u773a\u8df3\u4f7b\u7967\u94eb\u7a95\u9f86\u9ca6", + tie: "\u8d34\u94c1\u5e16\u841c\u992e", + ting: "\u5385\u542c\u70c3\u6c40\u5ef7\u505c\u4ead\u5ead\u633a\u8247\u839b\u8476\u5a77\u6883\u8713\u9706", + tong: "\u901a\u6850\u916e\u77b3\u540c\u94dc\u5f64\u7ae5\u6876\u6345\u7b52\u7edf\u75db\u4f5f\u50ee\u4edd\u833c\u55f5\u6078\u6f7c\u783c", + tou: "\u5077\u6295\u5934\u900f\u4ea0", + tu: "\u51f8\u79c3\u7a81\u56fe\u5f92\u9014\u6d82\u5c60\u571f\u5410\u5154\u580d\u837c\u83df\u948d\u9174", + tuan: "\u6e4d\u56e2\u7583", + tui: "\u63a8\u9893\u817f\u8715\u892a\u9000\u5fd2\u717a", + tun: "\u541e\u5c6f\u81c0\u9968\u66be\u8c5a\u7a80", + tuo: "\u62d6\u6258\u8131\u9e35\u9640\u9a6e\u9a7c\u692d\u59a5\u62d3\u553e\u4e47\u4f57\u5768\u5eb9\u6cb1\u67dd\u7823\u7ba8\u8204\u8dce\u9f0d", + wa: "\u6316\u54c7\u86d9\u6d3c\u5a03\u74e6\u889c\u4f64\u5a32\u817d", + wai: "\u6b6a\u5916", + wan: "\u8c4c\u5f2f\u6e7e\u73a9\u987d\u4e38\u70f7\u5b8c\u7897\u633d\u665a\u7696\u60cb\u5b9b\u5a49\u4e07\u8155\u525c\u8284\u82cb\u83c0\u7ea8\u7efe\u742c\u8118\u7579\u873f\u7ba2", + wang: "\u6c6a\u738b\u4ea1\u6789\u7f51\u5f80\u65fa\u671b\u5fd8\u5984\u7f54\u5c22\u60d8\u8f8b\u9b4d", + wei: "\u5a01\u5dcd\u5fae\u5371\u97e6\u8fdd\u6845\u56f4\u552f\u60df\u4e3a\u6f4d\u7ef4\u82c7\u840e\u59d4\u4f1f\u4f2a\u5c3e\u7eac\u672a\u851a\u5473\u754f\u80c3\u5582\u9b4f\u4f4d\u6e2d\u8c13\u5c09\u6170\u536b\u502d\u504e\u8bff\u9688\u8473\u8587\u5e0f\u5e37\u5d34\u5d6c\u7325\u732c\u95f1\u6ca9\u6d27\u6da0\u9036\u5a13\u73ae\u97ea\u8ece\u709c\u7168\u71a8\u75ff\u8249\u9c94", + wen: "\u761f\u6e29\u868a\u6587\u95fb\u7eb9\u543b\u7a33\u7d0a\u95ee\u520e\u6120\u960c\u6c76\u74ba\u97eb\u6b81\u96ef", + weng: "\u55e1\u7fc1\u74ee\u84ca\u8579", + wo: "\u631d\u8717\u6da1\u7a9d\u6211\u65a1\u5367\u63e1\u6c83\u83b4\u5e44\u6e25\u674c\u809f\u9f8c", + wu: "\u5deb\u545c\u94a8\u4e4c\u6c61\u8bec\u5c4b\u65e0\u829c\u68a7\u543e\u5434\u6bcb\u6b66\u4e94\u6342\u5348\u821e\u4f0d\u4fae\u575e\u620a\u96fe\u6664\u7269\u52ff\u52a1\u609f\u8bef\u5140\u4ef5\u9622\u90ac\u572c\u82b4\u5e91\u6003\u5fe4\u6d6f\u5be4\u8fd5\u59a9\u9a9b\u727e\u7110\u9e49\u9e5c\u8708\u92c8\u9f2f", + xi: "\u6614\u7199\u6790\u897f\u7852\u77fd\u6670\u563b\u5438\u9521\u727a\u7a00\u606f\u5e0c\u6089\u819d\u5915\u60dc\u7184\u70ef\u6eaa\u6c50\u7280\u6a84\u88ad\u5e2d\u4e60\u5ab3\u559c\u94e3\u6d17\u7cfb\u9699\u620f\u7ec6\u50d6\u516e\u96b0\u90d7\u831c\u8478\u84f0\u595a\u550f\u5f99\u9969\u960b\u6d60\u6dc5\u5c63\u5b09\u73ba\u6a28\u66e6\u89cb\u6b37\u71b9\u798a\u79a7\u94b8\u7699\u7a78\u8725\u87cb\u823e\u7fb2\u7c9e\u7fd5\u91af\u9f37", + xia: "\u778e\u867e\u5323\u971e\u8f96\u6687\u5ce1\u4fa0\u72ed\u4e0b\u53a6\u590f\u5413\u6380\u846d\u55c4\u72ce\u9050\u7455\u7856\u7615\u7f45\u9ee0", + xian: "\u9528\u5148\u4ed9\u9c9c\u7ea4\u54b8\u8d24\u8854\u8237\u95f2\u6d8e\u5f26\u5acc\u663e\u9669\u73b0\u732e\u53bf\u817a\u9985\u7fa1\u5baa\u9677\u9650\u7ebf\u51bc\u85d3\u5c98\u7303\u66b9\u5a34\u6c19\u7946\u9e47\u75eb\u86ac\u7b45\u7c7c\u9170\u8df9", + xiang: + "\u76f8\u53a2\u9576\u9999\u7bb1\u8944\u6e58\u4e61\u7fd4\u7965\u8be6\u60f3\u54cd\u4eab\u9879\u5df7\u6a61\u50cf\u5411\u8c61\u8297\u8459\u9977\u5ea0\u9aa7\u7f03\u87d3\u9c9e\u98e8", + xiao: "\u8427\u785d\u9704\u524a\u54ee\u56a3\u9500\u6d88\u5bb5\u6dc6\u6653\u5c0f\u5b5d\u6821\u8096\u5578\u7b11\u6548\u54d3\u54bb\u5d24\u6f47\u900d\u9a81\u7ee1\u67ad\u67b5\u7b71\u7bab\u9b48", + xie: "\u6954\u4e9b\u6b47\u874e\u978b\u534f\u631f\u643a\u90aa\u659c\u80c1\u8c10\u5199\u68b0\u5378\u87f9\u61c8\u6cc4\u6cfb\u8c22\u5c51\u5055\u4eb5\u52f0\u71ee\u85a4\u64b7\u5ee8\u7023\u9082\u7ec1\u7f2c\u69ad\u698d\u6b59\u8e9e", + xin: "\u85aa\u82af\u950c\u6b23\u8f9b\u65b0\u5ffb\u5fc3\u4fe1\u8845\u56df\u99a8\u8398\u6b46\u94fd\u946b", + xing: "\u661f\u8165\u7329\u60fa\u5174\u5211\u578b\u5f62\u90a2\u884c\u9192\u5e78\u674f\u6027\u59d3\u9649\u8347\u8365\u64e4\u60bb\u784e", + xiong: "\u5144\u51f6\u80f8\u5308\u6c79\u96c4\u718a\u828e", + xiu: "\u4f11\u4fee\u7f9e\u673d\u55c5\u9508\u79c0\u8896\u7ee3\u83a0\u5cab\u9990\u5ea5\u9e3a\u8c85\u9af9", + xu: "\u589f\u620c\u9700\u865a\u5618\u987b\u5f90\u8bb8\u84c4\u9157\u53d9\u65ed\u5e8f\u755c\u6064\u7d6e\u5a7f\u7eea\u7eed\u8bb4\u8be9\u5729\u84ff\u6035\u6d2b\u6e86\u987c\u6829\u7166\u7809\u76f1\u80e5\u7cc8\u9191", + xuan: "\u8f69\u55a7\u5ba3\u60ac\u65cb\u7384\u9009\u7663\u7729\u7eda\u5107\u8c16\u8431\u63ce\u9994\u6ceb\u6d35\u6e32\u6f29\u7487\u6966\u6684\u70ab\u714a\u78b9\u94c9\u955f\u75c3", + xue: "\u9774\u859b\u5b66\u7a74\u96ea\u8840\u5671\u6cf6\u9cd5", + xun: "\u52cb\u718f\u5faa\u65ec\u8be2\u5bfb\u9a6f\u5de1\u6b89\u6c5b\u8bad\u8baf\u900a\u8fc5\u5dfd\u57d9\u8340\u85b0\u5ccb\u5f87\u6d54\u66db\u7aa8\u91ba\u9c9f", + ya: "\u538b\u62bc\u9e26\u9e2d\u5440\u4e2b\u82bd\u7259\u869c\u5d16\u8859\u6daf\u96c5\u54d1\u4e9a\u8bb6\u4f22\u63e0\u5416\u5c88\u8fd3\u5a05\u740a\u6860\u6c29\u7811\u775a\u75d6", + yan: "\u7109\u54bd\u9609\u70df\u6df9\u76d0\u4e25\u7814\u8712\u5ca9\u5ef6\u8a00\u989c\u960e\u708e\u6cbf\u5944\u63a9\u773c\u884d\u6f14\u8273\u5830\u71d5\u538c\u781a\u96c1\u5501\u5f66\u7130\u5bb4\u8c1a\u9a8c\u53a3\u9765\u8d5d\u4fe8\u5043\u5156\u8ba0\u8c33\u90fe\u9122\u82ab\u83f8\u5d26\u6079\u95eb\u960f\u6d07\u6e6e\u6edf\u598d\u5ae3\u7430\u664f\u80ed\u814c\u7131\u7f68\u7b75\u917d\u9b47\u990d\u9f39", + yang: "\u6b83\u592e\u9e2f\u79e7\u6768\u626c\u4f6f\u75a1\u7f8a\u6d0b\u9633\u6c27\u4ef0\u75d2\u517b\u6837\u6f3e\u5f89\u600f\u6cf1\u7080\u70ca\u6059\u86d8\u9785", + yao: "\u9080\u8170\u5996\u7476\u6447\u5c27\u9065\u7a91\u8c23\u59da\u54ac\u8200\u836f\u8981\u8000\u592d\u723b\u5406\u5d3e\u5fad\u7039\u5e7a\u73e7\u6773\u66dc\u80b4\u9e5e\u7a88\u7e47\u9cd0", + ye: "\u6930\u564e\u8036\u7237\u91ce\u51b6\u4e5f\u9875\u6396\u4e1a\u53f6\u66f3\u814b\u591c\u6db2\u8c12\u90ba\u63f6\u9980\u6654\u70e8\u94d8", + yi: "\u4e00\u58f9\u533b\u63d6\u94f1\u4f9d\u4f0a\u8863\u9890\u5937\u9057\u79fb\u4eea\u80f0\u7591\u6c82\u5b9c\u59e8\u5f5d\u6905\u8681\u501a\u5df2\u4e59\u77e3\u4ee5\u827a\u6291\u6613\u9091\u5c79\u4ebf\u5f79\u81c6\u9038\u8084\u75ab\u4ea6\u88d4\u610f\u6bc5\u5fc6\u4e49\u76ca\u6ea2\u8be3\u8bae\u8c0a\u8bd1\u5f02\u7ffc\u7fcc\u7ece\u5208\u5293\u4f7e\u8bd2\u572a\u572f\u57f8\u61ff\u82e1\u858f\u5f08\u5955\u6339\u5f0b\u5453\u54a6\u54bf\u566b\u5cc4\u5db7\u7317\u9974\u603f\u6021\u6092\u6f2a\u8fe4\u9a7f\u7f22\u6baa\u8d3b\u65d6\u71a0\u9487\u9552\u9571\u75cd\u7617\u7654\u7fca\u8864\u8734\u8223\u7fbf\u7ff3\u914f\u9edf", + yin: "\u8335\u836b\u56e0\u6bb7\u97f3\u9634\u59fb\u541f\u94f6\u6deb\u5bc5\u996e\u5c39\u5f15\u9690\u5370\u80e4\u911e\u5819\u831a\u5591\u72fa\u5924\u6c24\u94df\u763e\u8693\u972a\u9f88", + ying: "\u82f1\u6a31\u5a74\u9e70\u5e94\u7f28\u83b9\u8424\u8425\u8367\u8747\u8fce\u8d62\u76c8\u5f71\u9896\u786c\u6620\u5b34\u90e2\u8314\u83ba\u8426\u6484\u5624\u81ba\u6ee2\u6f46\u701b\u745b\u748e\u6979\u9e66\u763f\u988d\u7f42", + yo: "\u54df\u5537", + yong: "\u62e5\u4f63\u81c3\u75c8\u5eb8\u96cd\u8e0a\u86f9\u548f\u6cf3\u6d8c\u6c38\u607f\u52c7\u7528\u4fd1\u58c5\u5889\u6175\u9095\u955b\u752c\u9cd9\u9954", + you: "\u5e7d\u4f18\u60a0\u5fe7\u5c24\u7531\u90ae\u94c0\u72b9\u6cb9\u6e38\u9149\u6709\u53cb\u53f3\u4f51\u91c9\u8bf1\u53c8\u5e7c\u5363\u6538\u4f91\u83b8\u5466\u56ff\u5ba5\u67da\u7337\u7256\u94d5\u75a3\u8763\u9c7f\u9edd\u9f2c", + yu: "\u8fc2\u6de4\u4e8e\u76c2\u6986\u865e\u611a\u8206\u4f59\u4fde\u903e\u9c7c\u6109\u6e1d\u6e14\u9685\u4e88\u5a31\u96e8\u4e0e\u5c7f\u79b9\u5b87\u8bed\u7fbd\u7389\u57df\u828b\u90c1\u5401\u9047\u55bb\u5cea\u5fa1\u6108\u6b32\u72f1\u80b2\u8a89\u6d74\u5bd3\u88d5\u9884\u8c6b\u9a6d\u79ba\u6bd3\u4f1b\u4fe3\u8c00\u8c15\u8438\u84e3\u63c4\u5581\u5704\u5709\u5d5b\u72f3\u996b\u5ebe\u9608\u59aa\u59a4\u7ea1\u745c\u6631\u89ce\u8174\u6b24\u65bc\u715c\u71e0\u807f\u94b0\u9e46\u7610\u7600\u7ab3\u8753\u7afd\u8201\u96e9\u9f89", + yuan: "\u9e33\u6e0a\u51a4\u5143\u57a3\u8881\u539f\u63f4\u8f95\u56ed\u5458\u5706\u733f\u6e90\u7f18\u8fdc\u82d1\u613f\u6028\u9662\u586c\u6c85\u5a9b\u7457\u6a7c\u7230\u7722\u9e22\u8788\u9f0b", + yue: "\u66f0\u7ea6\u8d8a\u8dc3\u94a5\u5cb3\u7ca4\u6708\u60a6\u9605\u9fa0\u6a3e\u5216\u94ba", + yun: "\u8018\u4e91\u90e7\u5300\u9668\u5141\u8fd0\u8574\u915d\u6655\u97f5\u5b55\u90d3\u82b8\u72c1\u607d\u7ead\u6b92\u6600\u6c32", + za: "\u531d\u7838\u6742\u62f6\u5482", + zai: "\u683d\u54c9\u707e\u5bb0\u8f7d\u518d\u5728\u54b1\u5d3d\u753e", + zan: "\u6512\u6682\u8d5e\u74d2\u661d\u7c2a\u7ccc\u8db1\u933e", + zang: "\u8d43\u810f\u846c\u5958\u6215\u81e7", + zao: "\u906d\u7cdf\u51ff\u85fb\u67a3\u65e9\u6fa1\u86a4\u8e81\u566a\u9020\u7682\u7076\u71e5\u5523\u7f2b", + ze: "\u8d23\u62e9\u5219\u6cfd\u4ec4\u8d5c\u5567\u8fee\u6603\u7b2e\u7ba6\u8234", + zei: "\u8d3c", + zen: "\u600e\u8c2e", + zeng: "\u589e\u618e\u66fe\u8d60\u7f2f\u7511\u7f7e\u9503", + zha: "\u624e\u55b3\u6e23\u672d\u8f67\u94e1\u95f8\u7728\u6805\u69a8\u548b\u4e4d\u70b8\u8bc8\u63f8\u5412\u54a4\u54f3\u600d\u781f\u75c4\u86b1\u9f44", + zhai: "\u6458\u658b\u5b85\u7a84\u503a\u5be8\u7826", + zhan: "\u77bb\u6be1\u8a79\u7c98\u6cbe\u76cf\u65a9\u8f97\u5d2d\u5c55\u8638\u6808\u5360\u6218\u7ad9\u6e5b\u7efd\u8c35\u640c\u65c3", + zhang: + "\u6a1f\u7ae0\u5f70\u6f33\u5f20\u638c\u6da8\u6756\u4e08\u5e10\u8d26\u4ed7\u80c0\u7634\u969c\u4ec9\u9123\u5e5b\u5d82\u7350\u5adc\u748b\u87d1", + zhao: "\u62db\u662d\u627e\u6cbc\u8d75\u7167\u7f69\u5146\u8087\u53ec\u722a\u8bcf\u68f9\u948a\u7b0a", + zhe: "\u906e\u6298\u54f2\u86f0\u8f99\u8005\u9517\u8517\u8fd9\u6d59\u8c2a\u966c\u67d8\u8f84\u78d4\u9e67\u891a\u8707\u8d6d", + zhen: "\u73cd\u659f\u771f\u7504\u7827\u81fb\u8d1e\u9488\u4fa6\u6795\u75b9\u8bca\u9707\u632f\u9547\u9635\u7f1c\u6862\u699b\u8f78\u8d48\u80d7\u6715\u796f\u755b\u9e29", + zheng: + "\u84b8\u6323\u7741\u5f81\u72f0\u4e89\u6014\u6574\u62ef\u6b63\u653f\u5e27\u75c7\u90d1\u8bc1\u8be4\u5ce5\u94b2\u94ee\u7b5d", + zhi: "\u829d\u679d\u652f\u5431\u8718\u77e5\u80a2\u8102\u6c41\u4e4b\u7ec7\u804c\u76f4\u690d\u6b96\u6267\u503c\u4f84\u5740\u6307\u6b62\u8dbe\u53ea\u65e8\u7eb8\u5fd7\u631a\u63b7\u81f3\u81f4\u7f6e\u5e1c\u5cd9\u5236\u667a\u79e9\u7a1a\u8d28\u7099\u75d4\u6ede\u6cbb\u7a92\u536e\u965f\u90c5\u57f4\u82b7\u646d\u5e19\u5fee\u5f58\u54ab\u9a98\u6809\u67b3\u6800\u684e\u8f75\u8f7e\u6534\u8d3d\u81a3\u7949\u7957\u9ef9\u96c9\u9e37\u75e3\u86ed\u7d77\u916f\u8dd6\u8e2c\u8e2f\u8c78\u89ef", + zhong: + "\u4e2d\u76c5\u5fe0\u949f\u8877\u7ec8\u79cd\u80bf\u91cd\u4ef2\u4f17\u51a2\u953a\u87bd\u8202\u822f\u8e35", + zhou: "\u821f\u5468\u5dde\u6d32\u8bcc\u7ca5\u8f74\u8098\u5e1a\u5492\u76b1\u5b99\u663c\u9aa4\u5544\u7740\u501c\u8bf9\u836e\u9b3b\u7ea3\u80c4\u78a1\u7c40\u8233\u914e\u9cb7", + zhu: "\u73e0\u682a\u86db\u6731\u732a\u8bf8\u8bdb\u9010\u7af9\u70db\u716e\u62c4\u77a9\u5631\u4e3b\u8457\u67f1\u52a9\u86c0\u8d2e\u94f8\u7b51\u4f4f\u6ce8\u795d\u9a7b\u4f2b\u4f8f\u90be\u82ce\u8331\u6d19\u6e1a\u6f74\u9a7a\u677c\u69e0\u6a65\u70b7\u94e2\u75b0\u7603\u86b0\u7afa\u7bb8\u7fe5\u8e85\u9e88", + zhua: "\u6293", + zhuai: "\u62fd", + zhuan: "\u4e13\u7816\u8f6c\u64b0\u8d5a\u7bc6\u629f\u556d\u989b", + zhuang: "\u6869\u5e84\u88c5\u5986\u649e\u58ee\u72b6\u4e2c", + zhui: "\u690e\u9525\u8ffd\u8d58\u5760\u7f00\u8411\u9a93\u7f12", + zhun: "\u8c06\u51c6", + zhuo: "\u6349\u62d9\u5353\u684c\u7422\u8301\u914c\u707c\u6d4a\u502c\u8bfc\u5ef4\u855e\u64e2\u555c\u6d5e\u6dbf\u6753\u712f\u799a\u65ab", + zi: "\u5179\u54a8\u8d44\u59ff\u6ecb\u6dc4\u5b5c\u7d2b\u4ed4\u7c7d\u6ed3\u5b50\u81ea\u6e0d\u5b57\u8c18\u5d6b\u59ca\u5b73\u7f01\u6893\u8f8e\u8d40\u6063\u7726\u9531\u79ed\u8014\u7b2b\u7ca2\u89dc\u8a3e\u9cbb\u9aed", + zong: "\u9b03\u68d5\u8e2a\u5b97\u7efc\u603b\u7eb5\u8159\u7cbd", + zou: "\u90b9\u8d70\u594f\u63cd\u9139\u9cb0", + zu: "\u79df\u8db3\u5352\u65cf\u7956\u8bc5\u963b\u7ec4\u4fce\u83f9\u5550\u5f82\u9a75\u8e74", + zuan: "\u94bb\u7e82\u6525\u7f35", + zui: "\u5634\u9189\u6700\u7f6a", + zun: "\u5c0a\u9075\u6499\u6a3d\u9cdf", + zuo: "\u6628\u5de6\u4f50\u67de\u505a\u4f5c\u5750\u5ea7\u961d\u963c\u80d9\u795a\u9162", + cou: "\u85ae\u6971\u8f8f\u8160", + nang: "\u652e\u54dd\u56d4\u9995\u66e9", + o: "\u5594", + dia: "\u55f2", + chuai: "\u562c\u81aa\u8e39", + cen: "\u5c91\u6d94", + diu: "\u94e5", + nou: "\u8028", + fou: "\u7f36", + bia: "\u9adf", + }; + const formatContacts = (data: FriendUserItem[], key = "nickname") => { + const ucfirst = (l1: string) => { + if (l1.length > 0) { + const first = l1.substr(0, 1).toUpperCase(); + const spare = l1.substr(1, l1.length); + return first + spare; + } + }; + + const arraySearch = (l1: string) => { + for (const name in PinYin) { + // @ts-ignore + if ((PinYin[name] as string).indexOf(l1) !== -1) { + return ucfirst(name); + } + } + return false; + }; + + const codefans = (l1: string) => { + l1 = l1 ?? "unkown"; + const l2 = l1.length; + let I1 = ""; + const reg = new RegExp("[a-zA-Z0-9- ]"); + for (let i = 0; i < l2; i++) { + const val = l1.substr(i, 1); + const name = arraySearch(val); + if (reg.test(val)) { + I1 += val; + } else if (name !== false) { + I1 += name; + } + } + I1 = I1.replace(/ /g, "-"); + while (I1.indexOf("--") > 0) { + I1 = I1.replace("--", "-"); + } + return I1; + }; + + const arr = []; + + for (i = 0; i < data.length; i++) { + // @ts-ignore + const firstName = (data[i].initial = codefans(data[i][key]).substr(0, 1)); + arr.push(firstName.toUpperCase()); + } + + const arrlist = []; + for (i = 0; i < arr.length; i++) { + if (arrlist.indexOf(arr[i]) === -1) { + arrlist.push(arr[i]); + } + } + + // @ts-ignore + const dataSort = [] as any[]; + for (i = 0; i < arrlist.length; i++) { + dataSort[i] = { + initial: arrlist[i], + }; + dataSort[i].data = []; + for (j = 0; j < data.length; j++) { + // @ts-ignore + if (data[j].initial.toUpperCase() === dataSort[i].initial) { + dataSort[i].data.push(data[j]); + } + } + } + for (var i = 0; i < dataSort.length - 1; i++) { + for (var j = 1; j < dataSort.length - i; j++) { + if (dataSort[j - 1].initial > dataSort[j].initial) { + const a = dataSort[j]; + dataSort[j] = dataSort[j - 1]; + dataSort[j - 1] = a; + } + } + } + const NomalInitial = "QWERTYUIOPLKJHGFDSAZXCVBNM".split(""); + const special = { + initial: "#", + data: [] as any[], + }; + const newFilterData = dataSort.filter((d) => { + if (!NomalInitial.includes(d.initial)) { + special.data = [...special.data, ...d.data]; + } else { + return d; + } + }); + if (special.data.length > 0) { + newFilterData.push(special); + } + const indexList = newFilterData.map((item) => item.initial as string); + const dataList = newFilterData.map((item) => item.data as FriendUserItem[]); + return { + indexList, + dataList, + totalList: dataList.flat(), + groupCounts: dataList.map((data) => data.length), + }; + }; + + self.onmessage = (e) => self.postMessage(formatContacts(e.data)); +}; + +// 将函数转换为字符串,并创建一个Blob +const blob = new Blob(["(" + workerFunction + ")()"], { + type: "application/javascript", +}); + +// 创建一个指向该Blob的URL +const workerUrl = URL.createObjectURL(blob); + +// 使用这个URL创建一个新的Web Worker +const worker = new Worker(workerUrl); + +type ContactsData = { + indexList: string[]; + totalList: FriendUserItem[]; + groupCounts: number[]; +}; + +export const formatContactsByWorker = (data: FriendUserItem[]): Promise<ContactsData> => + new Promise((resolve) => { + worker.onmessage = (e) => resolve(e.data); + worker.postMessage(data); + }); diff --git a/pc-client/src/utils/events.ts b/pc-client/src/utils/events.ts new file mode 100644 index 0000000..ce1c597 --- /dev/null +++ b/pc-client/src/utils/events.ts @@ -0,0 +1,39 @@ +import { ChooseModalState } from "@/pages/common/ChooseModal"; +import { CheckListItem } from "@/pages/common/ChooseModal/ChooseBox/CheckItem"; +import mitt from "mitt"; +import { + GroupItem, + MessageItem, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import { InviteData } from "@/pages/common/RtcCallModal/data"; + +type EmitterEvents = { + OPEN_USER_CARD: OpenUserCardParams; + OPEN_GROUP_CARD: GroupItem; + OPEN_CHOOSE_MODAL: ChooseModalState; + CHAT_LIST_SCROLL_TO_BOTTOM: void; + OPEN_RTC_MODAL: InviteData; + // message store + PUSH_NEW_MSG: MessageItem; + UPDATE_ONE_MSG: MessageItem; + + SELECT_USER: SelectUserParams; +}; + +export type SelectUserParams = { + notConversation: boolean; + choosedList: CheckListItem[]; +}; + +export type OpenUserCardParams = { + userID?: string; + groupID?: string; + isSelf?: boolean; + notAdd?: boolean; +}; + +const emitter = mitt<EmitterEvents>(); + +export const emit = emitter.emit; + +export default emitter; diff --git a/pc-client/src/utils/imCommon.ts b/pc-client/src/utils/imCommon.ts new file mode 100644 index 0000000..99b9348 --- /dev/null +++ b/pc-client/src/utils/imCommon.ts @@ -0,0 +1,474 @@ +import dayjs from "dayjs"; +import { v4 as uuidV4 } from "uuid"; +import calendar from "dayjs/plugin/calendar"; +import relativeTime from "dayjs/plugin/relativeTime"; +import updateLocale from "dayjs/plugin/updateLocale"; +import { t } from "i18next"; +import default_group from "@/assets/images/contact/my_groups.png"; +import { v4 as uuidv4 } from "uuid"; + +import { GroupSessionTypes, SystemMessageTypes } from "@/constants/im"; +import { useConversationStore, useUserStore } from "@/store"; +import { useContactStore } from "@/store/contact"; + +import { generateAvatar, secondsToTime } from "./common"; +import { + AtTextElem, + ConversationItem, + MessageItem, + PublicUserItem, +} from "@openim/wasm-client-sdk/lib/types/entity"; +import { MessageType, SessionType } from "@openim/wasm-client-sdk"; +import { isThisYear } from "date-fns"; +import { FileWithPath } from "@/pages/chat/queryChat/ChatFooter/SendActionBar/useFileMessage"; +import { IMSDK } from "@/layout/MainContentWrap"; +import { UploadFileParams } from "@openim/wasm-client-sdk/lib/types/params"; +dayjs.extend(calendar); +dayjs.extend(relativeTime); +dayjs.extend(updateLocale); + +dayjs.updateLocale("en", { + calendar: { + sameDay: "HH:mm", + nextDay: "[tomorrow]", + nextWeek: "dddd", + lastDay: "[yesterday] HH:mm", + lastWeek: "dddd HH:mm", + sameElse: "YYYY/M/D HH:mm", + }, +}); +dayjs.updateLocale("zh-cn", { + calendar: { + sameDay: "A h:mm", + nextDay: "[明天]", + nextWeek: "dddd", + lastDay: "[昨天] HH:mm", + lastWeek: "dddd HH:mm", + sameElse: "YYYY年M月D日 HH:mm", + }, +}); + +const linkWrap = ({ + userID, + groupID, + name, + fromAt, +}: { + userID: string; + groupID: string; + name: string; + fromAt?: boolean; +}) => { + return `<span class='link-el${fromAt ? "" : " member-el" + } max-w-[200px] truncate inline-block align-bottom' onclick='userClick("${userID}","${groupID ?? "" + }")'>${name}</span>`; +}; + +export const notificationMessageFormat = (msg: MessageItem) => { + const selfID = useUserStore.getState().selfInfo.userID; + const getName = (user: PublicUserItem) => { + return user.userID === selfID ? t("you") : user.nickname; + }; + try { + switch (msg.contentType) { + case MessageType.FriendAdded: + return t("messageDescription.alreadyFriendMessage"); + case MessageType.GroupCreated: + const groupCreatedDetail = JSON.parse(msg.notificationElem!.detail); + const groupCreatedUser = groupCreatedDetail.opUser; + return t("messageDescription.createGroupMessage", { + creator: linkWrap({ + userID: groupCreatedUser.userID, + groupID: msg.groupID, + name: getName(groupCreatedUser), + }), + }); + case MessageType.GroupInfoUpdated: + const groupUpdateDetail = JSON.parse(msg.notificationElem!.detail); + const groupUpdateUser = groupUpdateDetail.opUser; + return t("messageDescription.updateGroupInfoMessage", { + operator: linkWrap({ + userID: groupUpdateUser.userID, + groupID: msg.groupID, + name: getName(groupUpdateUser), + }), + }); + case MessageType.GroupOwnerTransferred: + const transferDetails = JSON.parse(msg.notificationElem!.detail); + const transferOpUser = transferDetails.opUser; + const newOwner = transferDetails.newGroupOwner; + return t("messageDescription.transferGroupMessage", { + owner: linkWrap({ + userID: transferOpUser.userID, + groupID: msg.groupID, + name: getName(transferOpUser), + }), + newOwner: linkWrap({ + userID: newOwner.userID, + groupID: msg.groupID, + name: getName(newOwner), + }), + }); + case MessageType.MemberQuit: + const quitDetails = JSON.parse(msg.notificationElem!.detail); + const quitUser = quitDetails.quitUser; + return t("messageDescription.quitGroupMessage", { + name: linkWrap({ + userID: quitUser.userID, + groupID: msg.groupID, + name: getName(quitUser), + }), + }); + case MessageType.MemberInvited: + const inviteDetails = JSON.parse(msg.notificationElem!.detail); + const inviteOpUser = inviteDetails.opUser; + const invitedUserList = inviteDetails.invitedUserList ?? []; + let inviteStr = ""; + invitedUserList.slice(0, 3).map( + (user: any) => + (inviteStr += `${linkWrap({ + userID: user.userID, + groupID: msg.groupID, + name: getName(user), + })}、`), + ); + inviteStr = inviteStr.slice(0, -1); + return t("messageDescription.invitedToGroupMessage", { + operator: linkWrap({ + userID: inviteOpUser.userID, + groupID: msg.groupID, + name: getName(inviteOpUser), + }), + invitedUser: `${inviteStr}${invitedUserList.length > 3 + ? `${t("placeholder.and")}${t("placeholder.somePerson", { + num: invitedUserList.length, + })}` + : "" + }`, + }); + case MessageType.MemberKicked: + const kickDetails = JSON.parse(msg.notificationElem!.detail); + const kickOpUser = kickDetails.opUser; + const kickdUserList = kickDetails.kickedUserList ?? []; + let kickStr = ""; + kickdUserList.slice(0, 3).map( + (user: any) => + (kickStr += `${linkWrap({ + userID: user.userID, + groupID: msg.groupID, + name: getName(user), + })}、`), + ); + kickStr = kickStr.slice(0, -1); + return t("messageDescription.kickInGroupMessage", { + operator: linkWrap({ + userID: kickOpUser.userID, + groupID: msg.groupID, + name: getName(kickOpUser), + }), + kickedUser: `${kickStr}${kickdUserList.length > 3 ? "..." : ""}`, + }); + case MessageType.MemberEnter: + const enterDetails = JSON.parse(msg.notificationElem!.detail); + const enterUser = enterDetails.entrantUser; + return t("messageDescription.joinGroupMessage", { + name: linkWrap({ + userID: enterUser.userID, + groupID: msg.groupID, + name: getName(enterUser), + }), + }); + case MessageType.GroupDismissed: + const dismissDetails = JSON.parse(msg.notificationElem!.detail); + const dismissUser = dismissDetails.opUser; + return t("messageDescription.disbanedGroupMessage", { + operator: linkWrap({ + userID: dismissUser.userID, + groupID: msg.groupID, + name: getName(dismissUser), + }), + }); + default: + return ""; + } + } catch (error) { + return ""; + } +}; + +export const formatConversionTime = (timestemp: number): string => { + if (!timestemp) return ""; + + const fromNowStr = dayjs(timestemp).fromNow(); + + if (fromNowStr.includes(t("date.second"))) { + return t("date.justNow"); + } + + if ( + !fromNowStr.includes(t("date.second")) && + !fromNowStr.includes(t("date.minute")) + ) { + return dayjs(timestemp).calendar(); + } + + return fromNowStr; +}; + +export const formatMessageTime = (timestemp: number, keepSameYear = false): string => { + if (!timestemp) return ""; + + const isRecent = dayjs().diff(timestemp, "day") < 7; + const keepYear = keepSameYear || !isThisYear(timestemp); + + if (!isRecent && !keepYear) { + return dayjs(timestemp).format("M/D HH:mm"); + } + + return dayjs(timestemp).calendar(); +}; + +export const parseBr = (text: string) => { + return text + .replace(new RegExp("\\n", "g"), "<br>") + .replace(new RegExp("\n", "g"), "<br>"); +}; + +export const formatMessageByType = (message?: MessageItem): string => { + if (!message) return ""; + const selfUserID = useUserStore.getState().selfInfo.userID; + const isSelf = (id: string) => id === selfUserID; + const getName = (user: PublicUserItem) => { + return user.userID === selfUserID ? t("you") : user.nickname; + }; + try { + switch (message.contentType) { + case MessageType.TextMessage: + return message.textElem!.content; + case MessageType.PictureMessage: + return t("messageDescription.imageMessage"); + case MessageType.FriendAdded: + return t("messageDescription.alreadyFriendMessage"); + case MessageType.MemberEnter: + const enterDetails = JSON.parse(message.notificationElem!.detail); + const enterUser = enterDetails.entrantUser; + return t("messageDescription.joinGroupMessage", { + name: getName(enterUser), + }); + case MessageType.GroupCreated: + const groupCreatedDetail = JSON.parse(message.notificationElem!.detail); + const groupCreatedUser = groupCreatedDetail.opUser; + return t("messageDescription.createGroupMessage", { + creator: getName(groupCreatedUser), + }); + case MessageType.MemberInvited: + const inviteDetails = JSON.parse(message.notificationElem!.detail); + const inviteOpUser = inviteDetails.opUser; + const invitedUserList = inviteDetails.invitedUserList ?? []; + let inviteStr = ""; + invitedUserList + .slice(0, 3) + .map((user: any) => (inviteStr += `${getName(user)}、`)); + inviteStr = inviteStr.slice(0, -1); + return t("messageDescription.invitedToGroupMessage", { + operator: getName(inviteOpUser), + invitedUser: `${inviteStr}${invitedUserList.length > 3 + ? `${t("placeholder.and")}${t("placeholder.somePerson", { + num: invitedUserList.length, + })}` + : "" + }`, + }); + case MessageType.MemberKicked: + const kickDetails = JSON.parse(message.notificationElem!.detail); + const kickOpUser = kickDetails.opUser; + const kickdUserList = kickDetails.kickedUserList ?? []; + let kickStr = ""; + kickdUserList.slice(0, 3).map((user: any) => (kickStr += `${getName(user)}、`)); + kickStr = kickStr.slice(0, -1); + return t("messageDescription.kickInGroupMessage", { + operator: getName(kickOpUser), + kickedUser: `${kickStr}${kickdUserList.length > 3 + ? `${t("placeholder.and")}${t("placeholder.somePerson", { + num: kickdUserList.length, + })}` + : "" + }`, + }); + case MessageType.MemberQuit: + const quitDetails = JSON.parse(message.notificationElem!.detail); + const quitUser = quitDetails.quitUser; + return t("messageDescription.quitGroupMessage", { + name: getName(quitUser), + }); + case MessageType.GroupInfoUpdated: + const groupUpdateDetail = JSON.parse(message.notificationElem!.detail); + const groupUpdateUser = groupUpdateDetail.opUser; + return t("messageDescription.updateGroupInfoMessage", { + operator: getName(groupUpdateUser), + }); + case MessageType.GroupOwnerTransferred: + const transferDetails = JSON.parse(message.notificationElem!.detail); + const transferOpUser = transferDetails.opUser; + const newOwner = transferDetails.newGroupOwner; + return t("messageDescription.transferGroupMessage", { + owner: getName(transferOpUser), + newOwner: getName(newOwner), + }); + case MessageType.GroupDismissed: + const dismissDetails = JSON.parse(message.notificationElem!.detail); + const dismissUser = dismissDetails.opUser; + return t("messageDescription.disbanedGroupMessage", { + operator: getName(dismissUser), + }); + default: + return ""; + } + } catch (error) { + return ""; + } +}; + +export const initStore = () => { + calcApplicationBadge(); + const { getSelfInfoByReq } = useUserStore.getState(); + const { + getBlackListByReq, + getRecvFriendApplicationListByReq, + getRecvGroupApplicationListByReq, + getSendFriendApplicationListByReq, + getSendGroupApplicationListByReq, + } = useContactStore.getState(); + const { getConversationListByReq, getUnReadCountByReq } = + useConversationStore.getState(); + + getUnReadCountByReq(); + getConversationListByReq(); + getSelfInfoByReq(); + getBlackListByReq(); + getRecvFriendApplicationListByReq(); + getRecvGroupApplicationListByReq(); + getSendFriendApplicationListByReq(); + getSendGroupApplicationListByReq(); + getUnReadCountByReq(); +}; + +export const conversationSort = ( + conversationList: ConversationItem[], + originalList?: ConversationItem[], +) => { + const listWithIndex = conversationList.map((item, index) => ({ + ...item, + originalIndex: + originalList?.findIndex((c) => c.conversationID === item.conversationID) ?? index, + })); + + const arr: string[] = []; + const filterArr = listWithIndex.filter((c) => { + if (!arr.includes(c.conversationID)) { + arr.push(c.conversationID); + return true; + } + return false; + }); + + filterArr.sort((a, b) => { + if (a.isPinned === b.isPinned) { + const aCompare = + a.draftTextTime > a.latestMsgSendTime ? a.draftTextTime : a.latestMsgSendTime; + const bCompare = + b.draftTextTime > b.latestMsgSendTime ? b.draftTextTime : b.latestMsgSendTime; + if (aCompare > bCompare) { + return -1; + } else if (aCompare < bCompare) { + return 1; + } else { + if (!originalList) return 0; + return a.originalIndex - b.originalIndex; + } + } else if (a.isPinned && !b.isPinned) { + return -1; + } else { + return 1; + } + }); + + return filterArr.map(({ originalIndex, ...rest }) => rest); +}; + +export const isGroupSession = (sessionType?: SessionType) => + sessionType ? GroupSessionTypes.includes(sessionType) : false; + +const regex = + /\b(https?:\/\/|www\.)[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(:\d+)?(\.[a-zA-Z]{2,})?(\/[a-zA-Z0-9\/_.-]*(%[a-fA-F0-9]{2})*(\/[a-zA-Z0-9\/_.-]*)*(\?\S*)?(#\S*)?)?(?=([^a-zA-Z0-9\/_.-]|$))/g; + +export const formatLink = (content: string) => + content.replace(regex, (match) => { + let href = match; + if (!match.match(/^https?:\/\//)) { + href = "https://" + match; + } + return `<a href="${href}" target="_blank" class="link-el">${match}</a>`; + }); + +export const calcApplicationBadge = async () => { + const unHandleFriendApplicationNum = useContactStore + .getState() + .recvFriendApplicationList.filter( + (application) => + application.handleResult === 0, + ).length; + + const unHandleGroupApplicationNum = useContactStore + .getState() + .recvGroupApplicationList.filter( + (application) => + application.handleResult === 0, + ).length; + useContactStore + .getState() + .updateUnHandleFriendApplicationCount(unHandleFriendApplicationNum); + useContactStore + .getState() + .updateUnHandleGroupApplicationCount(unHandleGroupApplicationNum); +}; + +export const getConversationContent = (message: MessageItem) => { + if ( + !message.groupID || + SystemMessageTypes.includes(message.contentType) || + message.sendID === useUserStore.getState().selfInfo.userID + ) { + return formatMessageByType(message); + } + return `${message.senderNickname}:${formatMessageByType(message)}`; +}; + +export const uploadFile = async (file: FileWithPath, path?: string) => { + const params: UploadFileParams = { + name: file.name, + contentType: file.type, + uuid: uuidV4(), + cause: "", + }; + if (window.electronAPI) { + params.filepath = path ?? file.path; + } else { + params.file = file; + } + return IMSDK.uploadFile(params); +}; + +export const getConversationIDByMsg = (message: MessageItem) => { + if (message.sessionType === SessionType.Single) { + const ids = [message.sendID, message.recvID].sort(); + return `si_${ids[0]}_${ids[1]}`; + } + if (message.sessionType === SessionType.Group) { + return `sg_${message.groupID}`; + } + if (message.sessionType === SessionType.Notification) { + return `sn_${message.sendID}_${message.recvID}`; + } + return ""; +}; diff --git a/pc-client/src/utils/pinyin.ts b/pc-client/src/utils/pinyin.ts new file mode 100644 index 0000000..071f049 --- /dev/null +++ b/pc-client/src/utils/pinyin.ts @@ -0,0 +1,417 @@ +export default { + a: "\u554a\u963f\u9515", + ai: "\u57c3\u6328\u54ce\u5509\u54c0\u7691\u764c\u853c\u77ee\u827e\u788d\u7231\u9698\u8bf6\u6371\u55f3\u55cc\u5ad2\u7477\u66a7\u7839\u953f\u972d", + an: "\u978d\u6c28\u5b89\u4ffa\u6309\u6697\u5cb8\u80fa\u6848\u8c19\u57ef\u63de\u72b4\u5eb5\u6849\u94f5\u9e4c\u9878\u9eef", + ang: "\u80ae\u6602\u76ce", + ao: "\u51f9\u6556\u71ac\u7ff1\u8884\u50b2\u5965\u61ca\u6fb3\u5773\u62d7\u55f7\u5662\u5c99\u5ed2\u9068\u5aaa\u9a9c\u8071\u87af\u93ca\u9ccc\u93d6", + ba: "\u82ad\u634c\u6252\u53ed\u5427\u7b06\u516b\u75a4\u5df4\u62d4\u8dcb\u9776\u628a\u8019\u575d\u9738\u7f62\u7238\u8307\u83dd\u8406\u636d\u5c9c\u705e\u6777\u94af\u7c91\u9c85\u9b43", + bai: "\u767d\u67cf\u767e\u6446\u4f70\u8d25\u62dc\u7a17\u859c\u63b0\u97b4", + ban: "\u6591\u73ed\u642c\u6273\u822c\u9881\u677f\u7248\u626e\u62cc\u4f34\u74e3\u534a\u529e\u7eca\u962a\u5742\u8c73\u94a3\u7622\u764d\u8228", + bang: "\u90a6\u5e2e\u6886\u699c\u8180\u7ed1\u68d2\u78c5\u868c\u9551\u508d\u8c24\u84a1\u8783", + bao: "\u82de\u80de\u5305\u8912\u96f9\u4fdd\u5821\u9971\u5b9d\u62b1\u62a5\u66b4\u8c79\u9c8d\u7206\u52f9\u8446\u5b80\u5b62\u7172\u9e28\u8913\u8db5\u9f85", + bo: "\u5265\u8584\u73bb\u83e0\u64ad\u62e8\u94b5\u6ce2\u535a\u52c3\u640f\u94c2\u7b94\u4f2f\u5e1b\u8236\u8116\u818a\u6e24\u6cca\u9a73\u4eb3\u8543\u5575\u997d\u6a97\u64d8\u7934\u94b9\u9e41\u7c38\u8ddb", + bei: "\u676f\u7891\u60b2\u5351\u5317\u8f88\u80cc\u8d1d\u94a1\u500d\u72c8\u5907\u60eb\u7119\u88ab\u5b5b\u9642\u90b6\u57e4\u84d3\u5457\u602b\u6096\u789a\u9e4e\u8919\u943e", + ben: "\u5954\u82ef\u672c\u7b28\u755a\u574c\u951b", + beng: "\u5d29\u7ef7\u752d\u6cf5\u8e66\u8ff8\u552a\u5623\u750f", + bi: "\u903c\u9f3b\u6bd4\u9119\u7b14\u5f7c\u78a7\u84d6\u853d\u6bd5\u6bd9\u6bd6\u5e01\u5e87\u75f9\u95ed\u655d\u5f0a\u5fc5\u8f9f\u58c1\u81c2\u907f\u965b\u5315\u4ef3\u4ffe\u8298\u835c\u8378\u5421\u54d4\u72f4\u5eb3\u610e\u6ed7\u6fde\u5f3c\u59a3\u5a62\u5b16\u74a7\u8d32\u7540\u94cb\u79d5\u88e8\u7b5a\u7b85\u7be6\u822d\u895e\u8df8\u9ac0", + bian: "\u97ad\u8fb9\u7f16\u8d2c\u6241\u4fbf\u53d8\u535e\u8fa8\u8fa9\u8fab\u904d\u533e\u5f01\u82c4\u5fed\u6c74\u7f0f\u7178\u782d\u78a5\u7a39\u7a86\u8759\u7b3e\u9cca", + biao: "\u6807\u5f6a\u8198\u8868\u5a4a\u9aa0\u98d1\u98d9\u98da\u706c\u9556\u9573\u762d\u88f1\u9cd4", + bie: "\u9cd6\u618b\u522b\u762a\u8e69\u9cd8", + bin: "\u5f6c\u658c\u6fd2\u6ee8\u5bbe\u6448\u50a7\u6d5c\u7f24\u73a2\u6ba1\u8191\u9554\u9acc\u9b13", + bing: "\u5175\u51b0\u67c4\u4e19\u79c9\u997c\u70b3\u75c5\u5e76\u7980\u90b4\u6452\u7ee0\u678b\u69df\u71f9", + bu: "\u6355\u535c\u54fa\u8865\u57e0\u4e0d\u5e03\u6b65\u7c3f\u90e8\u6016\u62ca\u535f\u900b\u74ff\u6661\u949a\u91ad", + ca: "\u64e6\u5693\u7924", + cai: "\u731c\u88c1\u6750\u624d\u8d22\u776c\u8e29\u91c7\u5f69\u83dc\u8521", + can: "\u9910\u53c2\u8695\u6b8b\u60ed\u60e8\u707f\u9a96\u74a8\u7cb2\u9eea", + cang: "\u82cd\u8231\u4ed3\u6ca7\u85cf\u4f27", + cao: "\u64cd\u7cd9\u69fd\u66f9\u8349\u8279\u5608\u6f15\u87ac\u825a", + ce: "\u5395\u7b56\u4fa7\u518c\u6d4b\u5202\u5e3b\u607b", + ceng: "\u5c42\u8e6d\u564c", + cha: "\u63d2\u53c9\u832c\u8336\u67e5\u78b4\u643d\u5bdf\u5c94\u5dee\u8be7\u7339\u9987\u6c4a\u59f9\u6748\u6942\u69ce\u6aab\u9497\u9538\u9572\u8869", + chai: "\u62c6\u67f4\u8c7a\u4faa\u8308\u7625\u867f\u9f87", + chan: "\u6400\u63ba\u8749\u998b\u8c17\u7f20\u94f2\u4ea7\u9610\u98a4\u5181\u8c04\u8c36\u8487\u5edb\u5fcf\u6f7a\u6fb6\u5b71\u7fbc\u5a75\u5b17\u9aa3\u89c7\u7985\u9561\u88e3\u87fe\u8e94", + chang: + "\u660c\u7316\u573a\u5c1d\u5e38\u957f\u507f\u80a0\u5382\u655e\u7545\u5531\u5021\u4f25\u9b2f\u82cc\u83d6\u5f9c\u6005\u60dd\u960a\u5a3c\u5ae6\u6636\u6c05\u9cb3", + chao: "\u8d85\u6284\u949e\u671d\u5632\u6f6e\u5de2\u5435\u7092\u600a\u7ec9\u6641\u8016", + che: "\u8f66\u626f\u64a4\u63a3\u5f7b\u6f88\u577c\u5c6e\u7817", + chen: "\u90f4\u81e3\u8fb0\u5c18\u6668\u5ff1\u6c89\u9648\u8d81\u886c\u79f0\u8c0c\u62bb\u55d4\u5bb8\u741b\u6987\u809c\u80c2\u789c\u9f80", + cheng: + "\u6491\u57ce\u6a59\u6210\u5448\u4e58\u7a0b\u60e9\u6f84\u8bda\u627f\u901e\u9a8b\u79e4\u57d5\u5d4a\u5fb5\u6d48\u67a8\u67fd\u6a18\u665f\u584d\u77a0\u94d6\u88ce\u86cf\u9172", + chi: "\u5403\u75f4\u6301\u5319\u6c60\u8fdf\u5f1b\u9a70\u803b\u9f7f\u4f88\u5c3a\u8d64\u7fc5\u65a5\u70bd\u50ba\u5880\u82aa\u830c\u640b\u53f1\u54e7\u557b\u55e4\u5f73\u996c\u6cb2\u5ab8\u6555\u80dd\u7719\u7735\u9e31\u761b\u892b\u86a9\u87ad\u7b1e\u7bea\u8c49\u8e05\u8e1f\u9b51", + chong: "\u5145\u51b2\u866b\u5d07\u5ba0\u833a\u5fe1\u61a7\u94f3\u825f", + chou: "\u62bd\u916c\u7574\u8e0c\u7a20\u6101\u7b79\u4ec7\u7ef8\u7785\u4e11\u4fe6\u5733\u5e31\u60c6\u6eb4\u59af\u7633\u96e0\u9c8b", + chu: "\u81ed\u521d\u51fa\u6a71\u53a8\u8e87\u9504\u96cf\u6ec1\u9664\u695a\u7840\u50a8\u77d7\u6410\u89e6\u5904\u4e8d\u520d\u61b7\u7ecc\u6775\u696e\u6a17\u870d\u8e70\u9edc", + chuan: + "\u63e3\u5ddd\u7a7f\u693d\u4f20\u8239\u5598\u4e32\u63be\u821b\u60f4\u9044\u5ddb\u6c1a\u948f\u9569\u8221", + chuang: "\u75ae\u7a97\u5e62\u5e8a\u95ef\u521b\u6006", + chui: "\u5439\u708a\u6376\u9524\u5782\u9672\u68f0\u69cc", + chun: "\u6625\u693f\u9187\u5507\u6df3\u7eaf\u8822\u4fc3\u83bc\u6c8c\u80ab\u6710\u9e51\u877d", + chuo: "\u6233\u7ef0\u851f\u8fb6\u8f8d\u955e\u8e14\u9f8a", + ci: "\u75b5\u8328\u78c1\u96cc\u8f9e\u6148\u74f7\u8bcd\u6b64\u523a\u8d50\u6b21\u8360\u5472\u5d6f\u9e5a\u8785\u7ccd\u8d91", + cong: "\u806a\u8471\u56f1\u5306\u4ece\u4e1b\u506c\u82c1\u6dd9\u9aa2\u742e\u7481\u679e", + cu: "\u51d1\u7c97\u918b\u7c07\u731d\u6b82\u8e59", + cuan: "\u8e7f\u7be1\u7a9c\u6c46\u64ba\u6615\u7228", + cui: "\u6467\u5d14\u50ac\u8106\u7601\u7cb9\u6dec\u7fe0\u8403\u60b4\u7480\u69b1\u96b9", + cun: "\u6751\u5b58\u5bf8\u78cb\u5fd6\u76b4", + cuo: "\u64ae\u6413\u63aa\u632b\u9519\u539d\u811e\u9509\u77ec\u75e4\u9e7e\u8e49\u8e9c", + da: "\u642d\u8fbe\u7b54\u7629\u6253\u5927\u8037\u54d2\u55d2\u601b\u59b2\u75b8\u8921\u7b2a\u977c\u9791", + dai: "\u5446\u6b79\u50a3\u6234\u5e26\u6b86\u4ee3\u8d37\u888b\u5f85\u902e\u6020\u57ed\u7519\u5454\u5cb1\u8fe8\u902f\u9a80\u7ed0\u73b3\u9edb", + dan: "\u803d\u62c5\u4e39\u5355\u90f8\u63b8\u80c6\u65e6\u6c2e\u4f46\u60ee\u6de1\u8bde\u5f39\u86cb\u4ebb\u510b\u5369\u840f\u5556\u6fb9\u6a90\u6b9a\u8d55\u7708\u7605\u8043\u7baa", + dang: "\u5f53\u6321\u515a\u8361\u6863\u8c20\u51fc\u83ea\u5b95\u7800\u94db\u88c6", + dao: "\u5200\u6363\u8e48\u5012\u5c9b\u7977\u5bfc\u5230\u7a3b\u60bc\u9053\u76d7\u53e8\u5541\u5fc9\u6d2e\u6c18\u7118\u5fd1\u7e9b", + de: "\u5fb7\u5f97\u7684\u951d", + deng: "\u8e6c\u706f\u767b\u7b49\u77aa\u51f3\u9093\u5654\u5d9d\u6225\u78f4\u956b\u7c26", + di: "\u5824\u4f4e\u6ef4\u8fea\u654c\u7b1b\u72c4\u6da4\u5ae1\u62b5\u5e95\u5730\u8482\u7b2c\u5e1d\u5f1f\u9012\u7f14\u6c10\u7c74\u8bcb\u8c1b\u90b8\u577b\u839c\u837b\u5600\u5a23\u67e2\u68e3\u89cc\u7825\u78b2\u7747\u955d\u7f9d\u9ab6", + dian: "\u98a0\u6382\u6ec7\u7898\u70b9\u5178\u975b\u57ab\u7535\u4f43\u7538\u5e97\u60e6\u5960\u6dc0\u6bbf\u4e36\u963d\u576b\u57dd\u5dc5\u73b7\u765c\u766b\u7c1f\u8e2e", + diao: "\u7889\u53fc\u96d5\u51cb\u5201\u6389\u540a\u9493\u8c03\u8f7a\u94de\u8729\u7c9c\u8c82", + die: "\u8dcc\u7239\u789f\u8776\u8fed\u8c0d\u53e0\u4f5a\u57a4\u581e\u63f2\u558b\u6e2b\u8f76\u7252\u74de\u8936\u800b\u8e40\u9cbd\u9cce", + ding: "\u4e01\u76ef\u53ee\u9489\u9876\u9f0e\u952d\u5b9a\u8ba2\u4e22\u4ec3\u5576\u738e\u815a\u7887\u753a\u94e4\u7594\u8035\u914a", + dong: "\u4e1c\u51ac\u8463\u61c2\u52a8\u680b\u4f97\u606b\u51bb\u6d1e\u578c\u549a\u5cbd\u5cd2\u5902\u6c21\u80e8\u80f4\u7850\u9e2b", + dou: "\u515c\u6296\u6597\u9661\u8c46\u9017\u75d8\u8538\u94ad\u7aa6\u7aac\u86aa\u7bfc\u9161", + du: "\u90fd\u7763\u6bd2\u728a\u72ec\u8bfb\u5835\u7779\u8d4c\u675c\u9540\u809a\u5ea6\u6e21\u5992\u828f\u561f\u6e0e\u691f\u6a50\u724d\u8839\u7b03\u9ad1\u9ee9", + duan: "\u7aef\u77ed\u953b\u6bb5\u65ad\u7f0e\u5f56\u6934\u7145\u7c16", + dui: "\u5806\u5151\u961f\u5bf9\u603c\u619d\u7893", + dun: "\u58a9\u5428\u8e72\u6566\u987f\u56e4\u949d\u76fe\u9041\u7096\u7818\u7905\u76f9\u9566\u8db8", + duo: "\u6387\u54c6\u591a\u593a\u579b\u8eb2\u6735\u8dfa\u8235\u5241\u60f0\u5815\u5484\u54da\u7f0d\u67c1\u94ce\u88f0\u8e31", + e: "\u86fe\u5ce8\u9e45\u4fc4\u989d\u8bb9\u5a25\u6076\u5384\u627c\u904f\u9102\u997f\u5669\u8c14\u57a9\u57ad\u82ca\u83aa\u843c\u5443\u6115\u5c59\u5a40\u8f6d\u66f7\u816d\u786a\u9507\u9537\u9e57\u989a\u9cc4", + en: "\u6069\u84bd\u6441\u5514\u55ef", + er: "\u800c\u513f\u8033\u5c14\u9975\u6d31\u4e8c\u8d30\u8fe9\u73e5\u94d2\u9e38\u9c95", + fa: "\u53d1\u7f5a\u7b4f\u4f10\u4e4f\u9600\u6cd5\u73d0\u57a1\u781d", + fan: "\u85e9\u5e06\u756a\u7ffb\u6a0a\u77fe\u9492\u7e41\u51e1\u70e6\u53cd\u8fd4\u8303\u8d29\u72af\u996d\u6cdb\u8629\u5e61\u72ad\u68b5\u6535\u71d4\u7548\u8e6f", + fang: "\u574a\u82b3\u65b9\u80aa\u623f\u9632\u59a8\u4eff\u8bbf\u7eba\u653e\u531a\u90a1\u5f77\u94ab\u822b\u9c82", + fei: "\u83f2\u975e\u5561\u98de\u80a5\u532a\u8bfd\u5420\u80ba\u5e9f\u6cb8\u8d39\u82be\u72d2\u60b1\u6ddd\u5983\u7ecb\u7eef\u69a7\u8153\u6590\u6249\u7953\u7829\u9544\u75f1\u871a\u7bda\u7fe1\u970f\u9cb1", + fen: "\u82ac\u915a\u5429\u6c1b\u5206\u7eb7\u575f\u711a\u6c7e\u7c89\u594b\u4efd\u5fff\u6124\u7caa\u507e\u7035\u68fc\u610d\u9cbc\u9f22", + feng: "\u4e30\u5c01\u67ab\u8702\u5cf0\u950b\u98ce\u75af\u70fd\u9022\u51af\u7f1d\u8bbd\u5949\u51e4\u4ff8\u9146\u8451\u6ca3\u781c", + fu: "\u4f5b\u5426\u592b\u6577\u80a4\u5b75\u6276\u62c2\u8f90\u5e45\u6c1f\u7b26\u4f0f\u4fd8\u670d\u6d6e\u6daa\u798f\u88b1\u5f17\u752b\u629a\u8f85\u4fef\u91dc\u65a7\u812f\u8151\u5e9c\u8150\u8d74\u526f\u8986\u8d4b\u590d\u5085\u4ed8\u961c\u7236\u8179\u8d1f\u5bcc\u8ba3\u9644\u5987\u7f1a\u5490\u5310\u51eb\u90db\u8299\u82fb\u832f\u83a9\u83d4\u544b\u5e5e\u6ecf\u8274\u5b5a\u9a78\u7ec2\u6874\u8d59\u9efb\u9efc\u7f58\u7a03\u99a5\u864d\u86a8\u8709\u8760\u876e\u9eb8\u8dba\u8dd7\u9cc6", + ga: "\u5676\u560e\u86e4\u5c2c\u5477\u5c15\u5c1c\u65ee\u9486", + gai: "\u8be5\u6539\u6982\u9499\u76d6\u6e89\u4e10\u9654\u5793\u6224\u8d45\u80f2", + gan: "\u5e72\u7518\u6746\u67d1\u7aff\u809d\u8d76\u611f\u79c6\u6562\u8d63\u5769\u82f7\u5c34\u64c0\u6cd4\u6de6\u6f89\u7ec0\u6a44\u65f0\u77f8\u75b3\u9150", + gang: "\u5188\u521a\u94a2\u7f38\u809b\u7eb2\u5c97\u6e2f\u6206\u7f61\u9883\u7b7b", + gong: "\u6760\u5de5\u653b\u529f\u606d\u9f9a\u4f9b\u8eac\u516c\u5bab\u5f13\u5de9\u6c5e\u62f1\u8d21\u5171\u857b\u5efe\u54a3\u73d9\u80b1\u86a3\u86e9\u89e5", + gao: "\u7bd9\u768b\u9ad8\u818f\u7f94\u7cd5\u641e\u9550\u7a3f\u544a\u777e\u8bf0\u90dc\u84bf\u85c1\u7f1f\u69d4\u69c1\u6772\u9506", + ge: "\u54e5\u6b4c\u6401\u6208\u9e3d\u80f3\u7599\u5272\u9769\u845b\u683c\u9601\u9694\u94ec\u4e2a\u5404\u9b32\u4ee1\u54ff\u5865\u55dd\u7ea5\u643f\u8188\u784c\u94ea\u9549\u88bc\u988c\u867c\u8238\u9abc\u9ac2", + gei: "\u7ed9", + gen: "\u6839\u8ddf\u4e98\u831b\u54cf\u826e", + geng: "\u8015\u66f4\u5e9a\u7fb9\u57c2\u803f\u6897\u54fd\u8d53\u9ca0", + gou: "\u94a9\u52fe\u6c9f\u82df\u72d7\u57a2\u6784\u8d2d\u591f\u4f5d\u8bdf\u5ca3\u9058\u5abe\u7f11\u89cf\u5f40\u9e32\u7b31\u7bdd\u97b2", + gu: "\u8f9c\u83c7\u5495\u7b8d\u4f30\u6cbd\u5b64\u59d1\u9f13\u53e4\u86ca\u9aa8\u8c37\u80a1\u6545\u987e\u56fa\u96c7\u560f\u8bc2\u83f0\u54cc\u5d2e\u6c69\u688f\u8f71\u726f\u727f\u80cd\u81cc\u6bc2\u77bd\u7f5f\u94b4\u9522\u74e0\u9e2a\u9e44\u75fc\u86c4\u9164\u89da\u9cb4\u9ab0\u9e58", + gua: "\u522e\u74dc\u5250\u5be1\u6302\u8902\u5366\u8bd6\u5471\u681d\u9e39", + guai: "\u4e56\u62d0\u602a\u54d9", + guan: "\u68fa\u5173\u5b98\u51a0\u89c2\u7ba1\u9986\u7f50\u60ef\u704c\u8d2f\u500c\u839e\u63bc\u6dab\u76e5\u9e73\u9ccf", + guang: "\u5149\u5e7f\u901b\u72b7\u6844\u80f1\u7592", + gui: "\u7470\u89c4\u572d\u7845\u5f52\u9f9f\u95fa\u8f68\u9b3c\u8be1\u7678\u6842\u67dc\u8dea\u8d35\u523d\u5326\u523f\u5e8b\u5b84\u59ab\u6867\u7085\u6677\u7688\u7c0b\u9c91\u9cdc", + gun: "\u8f8a\u6eda\u68cd\u4e28\u886e\u7ef2\u78d9\u9ca7", + guo: "\u9505\u90ed\u56fd\u679c\u88f9\u8fc7\u9998\u8803\u57da\u63b4\u5459\u56d7\u5e3c\u5d1e\u7313\u6901\u8662\u951e\u8052\u872e\u873e\u8748", + ha: "\u54c8", + hai: "\u9ab8\u5b69\u6d77\u6c26\u4ea5\u5bb3\u9a87\u54b4\u55e8\u988f\u91a2", + han: "\u9163\u61a8\u90af\u97e9\u542b\u6db5\u5bd2\u51fd\u558a\u7f55\u7ff0\u64bc\u634d\u65f1\u61be\u608d\u710a\u6c57\u6c49\u9097\u83e1\u6496\u961a\u701a\u6657\u7113\u9894\u86b6\u9f3e", + hen: "\u592f\u75d5\u5f88\u72e0\u6068", + hang: "\u676d\u822a\u6c86\u7ed7\u73e9\u6841", + hao: "\u58d5\u568e\u8c6a\u6beb\u90dd\u597d\u8017\u53f7\u6d69\u8585\u55e5\u5686\u6fe0\u704f\u660a\u7693\u98a2\u869d", + he: "\u5475\u559d\u8377\u83cf\u6838\u79be\u548c\u4f55\u5408\u76d2\u8c89\u9602\u6cb3\u6db8\u8d6b\u8910\u9e64\u8d3a\u8bc3\u52be\u58d1\u85ff\u55d1\u55ec\u9616\u76cd\u86b5\u7fee", + hei: "\u563f\u9ed1", + heng: "\u54fc\u4ea8\u6a2a\u8861\u6052\u8a07\u8605", + hong: "\u8f70\u54c4\u70d8\u8679\u9e3f\u6d2a\u5b8f\u5f18\u7ea2\u9ec9\u8ba7\u836d\u85a8\u95f3\u6cd3", + hou: "\u5589\u4faf\u7334\u543c\u539a\u5019\u540e\u5820\u5f8c\u9005\u760a\u7bcc\u7cc7\u9c8e\u9aba", + hu: "\u547c\u4e4e\u5ffd\u745a\u58f6\u846b\u80e1\u8774\u72d0\u7cca\u6e56\u5f27\u864e\u552c\u62a4\u4e92\u6caa\u6237\u51b1\u553f\u56eb\u5cb5\u7322\u6019\u60da\u6d52\u6ef9\u7425\u69f2\u8f77\u89f3\u70c0\u7173\u623d\u6248\u795c\u9e55\u9e71\u7b0f\u9190\u659b", + hua: "\u82b1\u54d7\u534e\u733e\u6ed1\u753b\u5212\u5316\u8bdd\u5290\u6d4d\u9a85\u6866\u94e7\u7a1e", + huai: "\u69d0\u5f8a\u6000\u6dee\u574f\u8fd8\u8e1d", + huan: "\u6b22\u73af\u6853\u7f13\u6362\u60a3\u5524\u75ea\u8c62\u7115\u6da3\u5ba6\u5e7b\u90c7\u5942\u57b8\u64d0\u571c\u6d39\u6d63\u6f36\u5bf0\u902d\u7f33\u953e\u9ca9\u9b1f", + huang: + "\u8352\u614c\u9ec4\u78fa\u8757\u7c27\u7687\u51f0\u60f6\u714c\u6643\u5e4c\u604d\u8c0e\u968d\u5fa8\u6e5f\u6f62\u9051\u749c\u8093\u7640\u87e5\u7bc1\u9cc7", + hui: "\u7070\u6325\u8f89\u5fbd\u6062\u86d4\u56de\u6bc1\u6094\u6167\u5349\u60e0\u6666\u8d3f\u79fd\u4f1a\u70e9\u6c47\u8bb3\u8bf2\u7ed8\u8bd9\u8334\u835f\u8559\u54d5\u5599\u96b3\u6d04\u5f57\u7f0b\u73f2\u6656\u605a\u867a\u87ea\u9ebe", + hun: "\u8364\u660f\u5a5a\u9b42\u6d51\u6df7\u8be8\u9984\u960d\u6eb7\u7f17", + huo: "\u8c41\u6d3b\u4f19\u706b\u83b7\u6216\u60d1\u970d\u8d27\u7978\u6509\u56af\u5925\u94ac\u952a\u956c\u8020\u8816", + ji: "\u51fb\u573e\u57fa\u673a\u7578\u7a3d\u79ef\u7b95\u808c\u9965\u8ff9\u6fc0\u8ba5\u9e21\u59ec\u7ee9\u7f09\u5409\u6781\u68d8\u8f91\u7c4d\u96c6\u53ca\u6025\u75be\u6c72\u5373\u5ac9\u7ea7\u6324\u51e0\u810a\u5df1\u84df\u6280\u5180\u5b63\u4f0e\u796d\u5242\u60b8\u6d4e\u5bc4\u5bc2\u8ba1\u8bb0\u65e2\u5fcc\u9645\u5993\u7ee7\u7eaa\u5c45\u4e0c\u4e69\u525e\u4f76\u4f74\u8114\u58bc\u82a8\u82b0\u8401\u84ba\u857a\u638e\u53fd\u54ad\u54dc\u5527\u5c8c\u5d74\u6d0e\u5f50\u5c50\u9aa5\u757f\u7391\u696b\u6b9b\u621f\u6222\u8d4d\u89ca\u7284\u9f51\u77f6\u7f81\u5d47\u7a37\u7620\u7635\u866e\u7b08\u7b04\u66a8\u8dfb\u8dfd\u9701\u9c9a\u9cab\u9afb\u9e82", + jia: "\u5609\u67b7\u5939\u4f73\u5bb6\u52a0\u835a\u988a\u8d3e\u7532\u94be\u5047\u7a3c\u4ef7\u67b6\u9a7e\u5ac1\u4f3d\u90cf\u62ee\u5cac\u6d43\u8fe6\u73c8\u621b\u80db\u605d\u94d7\u9553\u75c2\u86f1\u7b33\u8888\u8dcf", + jian: "\u6b7c\u76d1\u575a\u5c16\u7b3a\u95f4\u714e\u517c\u80a9\u8270\u5978\u7f04\u8327\u68c0\u67ec\u78b1\u7877\u62e3\u6361\u7b80\u4fed\u526a\u51cf\u8350\u69db\u9274\u8df5\u8d31\u89c1\u952e\u7bad\u4ef6\u5065\u8230\u5251\u996f\u6e10\u6e85\u6da7\u5efa\u50ed\u8c0f\u8c2b\u83c5\u84b9\u641b\u56dd\u6e54\u8e47\u8b07\u7f23\u67a7\u67d9\u6957\u620b\u622c\u726e\u728d\u6bfd\u8171\u7751\u950f\u9e63\u88e5\u7b15\u7bb4\u7fe6\u8dbc\u8e3a\u9ca3\u97af", + jiang: + "\u50f5\u59dc\u5c06\u6d46\u6c5f\u7586\u848b\u6868\u5956\u8bb2\u5320\u9171\u964d\u8333\u6d1a\u7edb\u7f30\u729f\u7913\u8029\u7ce8\u8c47", + jiao: "\u8549\u6912\u7901\u7126\u80f6\u4ea4\u90ca\u6d47\u9a84\u5a07\u56bc\u6405\u94f0\u77eb\u4fa5\u811a\u72e1\u89d2\u997a\u7f34\u7ede\u527f\u6559\u9175\u8f7f\u8f83\u53eb\u4f7c\u50ec\u832d\u6322\u564d\u5ce4\u5fbc\u59e3\u7e9f\u656b\u768e\u9e6a\u86df\u91ae\u8de4\u9c9b", + jie: "\u7a96\u63ed\u63a5\u7686\u79f8\u8857\u9636\u622a\u52ab\u8282\u6854\u6770\u6377\u776b\u7aed\u6d01\u7ed3\u89e3\u59d0\u6212\u85c9\u82a5\u754c\u501f\u4ecb\u75a5\u8beb\u5c4a\u5048\u8ba6\u8bd8\u5588\u55df\u736c\u5a55\u5b51\u6840\u7352\u78a3\u9534\u7596\u88b7\u9889\u86a7\u7faf\u9c92\u9ab1\u9aeb", + jin: "\u5dfe\u7b4b\u65a4\u91d1\u4eca\u6d25\u895f\u7d27\u9526\u4ec5\u8c28\u8fdb\u9773\u664b\u7981\u8fd1\u70ec\u6d78\u5c3d\u537a\u8369\u5807\u5664\u9991\u5ed1\u5997\u7f19\u747e\u69ff\u8d46\u89d0\u9485\u9513\u887f\u77dc", + jing: "\u52b2\u8346\u5162\u830e\u775b\u6676\u9cb8\u4eac\u60ca\u7cbe\u7cb3\u7ecf\u4e95\u8b66\u666f\u9888\u9759\u5883\u656c\u955c\u5f84\u75c9\u9756\u7adf\u7ade\u51c0\u522d\u5106\u9631\u83c1\u734d\u61ac\u6cfe\u8ff3\u5f2a\u5a67\u80bc\u80eb\u8148\u65cc", + jiong: "\u70af\u7a98\u5182\u8fe5\u6243", + jiu: "\u63ea\u7a76\u7ea0\u7396\u97ed\u4e45\u7078\u4e5d\u9152\u53a9\u6551\u65e7\u81fc\u8205\u548e\u5c31\u759a\u50e6\u557e\u9604\u67e9\u6855\u9e6b\u8d73\u9b0f", + ju: "\u97a0\u62d8\u72d9\u75bd\u9a79\u83ca\u5c40\u5480\u77e9\u4e3e\u6cae\u805a\u62d2\u636e\u5de8\u5177\u8ddd\u8e1e\u952f\u4ff1\u53e5\u60e7\u70ac\u5267\u5028\u8bb5\u82e3\u82f4\u8392\u63ac\u907d\u5c66\u741a\u67b8\u6910\u6998\u6989\u6a58\u728b\u98d3\u949c\u9514\u7aad\u88fe\u8d84\u91b5\u8e3d\u9f83\u96ce\u97ab", + juan: "\u6350\u9e43\u5a1f\u5026\u7737\u5377\u7ee2\u9104\u72f7\u6d93\u684a\u8832\u9529\u954c\u96bd", + jue: "\u6485\u652b\u6289\u6398\u5014\u7235\u89c9\u51b3\u8bc0\u7edd\u53a5\u5282\u8c32\u77cd\u8568\u5658\u5d1b\u7357\u5b53\u73cf\u6877\u6a5b\u721d\u9562\u8e76\u89d6", + jun: "\u5747\u83cc\u94a7\u519b\u541b\u5cfb\u4fca\u7ae3\u6d5a\u90e1\u9a8f\u6343\u72fb\u76b2\u7b60\u9e87", + ka: "\u5580\u5496\u5361\u4f67\u5494\u80e9", + ke: "\u54af\u5777\u82db\u67ef\u68f5\u78d5\u9897\u79d1\u58f3\u54b3\u53ef\u6e34\u514b\u523b\u5ba2\u8bfe\u5ca2\u606a\u6e98\u9a92\u7f02\u73c2\u8f72\u6c2a\u778c\u94b6\u75b4\u7aa0\u874c\u9ac1", + kai: "\u5f00\u63e9\u6977\u51ef\u6168\u5240\u57b2\u8488\u5ffe\u607a\u94e0\u950e", + kan: "\u520a\u582a\u52d8\u574e\u780d\u770b\u4f83\u51f5\u83b0\u83b6\u6221\u9f9b\u77b0", + kang: "\u5eb7\u6177\u7ce0\u625b\u6297\u4ea2\u7095\u5751\u4f09\u95f6\u94aa", + kao: "\u8003\u62f7\u70e4\u9760\u5c3b\u6832\u7292\u94d0", + ken: "\u80af\u5543\u57a6\u6073\u57a0\u88c9\u9880", + keng: "\u542d\u5fd0\u94ff", + kong: "\u7a7a\u6050\u5b54\u63a7\u5025\u5d06\u7b9c", + kou: "\u62a0\u53e3\u6263\u5bc7\u82a4\u853b\u53e9\u770d\u7b58", + ku: "\u67af\u54ed\u7a9f\u82e6\u9177\u5e93\u88e4\u5233\u5800\u55be\u7ed4\u9ab7", + kua: "\u5938\u57ae\u630e\u8de8\u80ef\u4f89", + kuai: "\u5757\u7b77\u4fa9\u5feb\u84af\u90d0\u8489\u72ef\u810d", + kuan: "\u5bbd\u6b3e\u9acb", + kuang: + "\u5321\u7b50\u72c2\u6846\u77ff\u7736\u65f7\u51b5\u8bd3\u8bf3\u909d\u5739\u593c\u54d0\u7ea9\u8d36", + kui: "\u4e8f\u76d4\u5cbf\u7aa5\u8475\u594e\u9b41\u5080\u9988\u6127\u6e83\u9997\u532e\u5914\u9697\u63c6\u55b9\u559f\u609d\u6126\u9615\u9035\u668c\u777d\u8069\u8770\u7bd1\u81fe\u8dec", + kun: "\u5764\u6606\u6346\u56f0\u6083\u9603\u7428\u951f\u918c\u9cb2\u9ae1", + kuo: "\u62ec\u6269\u5ed3\u9614\u86de", + la: "\u5783\u62c9\u5587\u8721\u814a\u8fa3\u5566\u524c\u647a\u908b\u65ef\u782c\u760c", + lai: "\u83b1\u6765\u8d56\u5d03\u5f95\u6d9e\u6fd1\u8d49\u7750\u94fc\u765e\u7c41", + lan: "\u84dd\u5a6a\u680f\u62e6\u7bee\u9611\u5170\u6f9c\u8c30\u63fd\u89c8\u61d2\u7f06\u70c2\u6ee5\u5549\u5c9a\u61d4\u6f24\u6984\u6593\u7f71\u9567\u8934", + lang: "\u7405\u6994\u72fc\u5eca\u90ce\u6717\u6d6a\u83a8\u8497\u5577\u9606\u9512\u7a02\u8782", + lao: "\u635e\u52b3\u7262\u8001\u4f6c\u59e5\u916a\u70d9\u6d9d\u5520\u5d02\u6833\u94d1\u94f9\u75e8\u91aa", + le: "\u52d2\u4e50\u808b\u4ec2\u53fb\u561e\u6cd0\u9cd3", + lei: "\u96f7\u956d\u857e\u78ca\u7d2f\u5121\u5792\u64c2\u7c7b\u6cea\u7fb8\u8bd4\u837d\u54a7\u6f2f\u5ad8\u7f27\u6a91\u8012\u9179", + ling: "\u68f1\u51b7\u62ce\u73b2\u83f1\u96f6\u9f84\u94c3\u4f36\u7f9a\u51cc\u7075\u9675\u5cad\u9886\u53e6\u4ee4\u9143\u5844\u82d3\u5464\u56f9\u6ce0\u7eeb\u67c3\u68c2\u74f4\u8046\u86c9\u7fce\u9cae", + leng: "\u695e\u6123", + li: "\u5398\u68a8\u7281\u9ece\u7bf1\u72f8\u79bb\u6f13\u7406\u674e\u91cc\u9ca4\u793c\u8389\u8354\u540f\u6817\u4e3d\u5389\u52b1\u783e\u5386\u5229\u5088\u4f8b\u4fd0\u75e2\u7acb\u7c92\u6ca5\u96b6\u529b\u7483\u54e9\u4fea\u4fda\u90e6\u575c\u82c8\u8385\u84e0\u85dc\u6369\u5456\u5533\u55b1\u7301\u6ea7\u6fa7\u9026\u5a0c\u5ae0\u9a8a\u7f21\u73de\u67a5\u680e\u8f79\u623e\u783a\u8a48\u7f79\u9502\u9e42\u75a0\u75ac\u86ce\u870a\u8821\u7b20\u7be5\u7c9d\u91b4\u8dde\u96f3\u9ca1\u9ce2\u9ee7", + lian: "\u4fe9\u8054\u83b2\u8fde\u9570\u5ec9\u601c\u6d9f\u5e18\u655b\u8138\u94fe\u604b\u70bc\u7ec3\u631b\u8539\u5941\u6f4b\u6fc2\u5a08\u740f\u695d\u6b93\u81c1\u81a6\u88e2\u880a\u9ca2", + liang: + "\u7cae\u51c9\u6881\u7cb1\u826f\u4e24\u8f86\u91cf\u667e\u4eae\u8c05\u589a\u690b\u8e09\u9753\u9b49", + liao: "\u64a9\u804a\u50da\u7597\u71ce\u5be5\u8fbd\u6f66\u4e86\u6482\u9563\u5ed6\u6599\u84fc\u5c25\u5639\u7360\u5bee\u7f2d\u948c\u9e69\u8022", + lie: "\u5217\u88c2\u70c8\u52a3\u730e\u51bd\u57d2\u6d0c\u8d94\u8e90\u9b23", + lin: "\u7433\u6797\u78f7\u9716\u4e34\u90bb\u9cde\u6dcb\u51db\u8d41\u541d\u853a\u5d99\u5eea\u9074\u6aa9\u8f9a\u77b5\u7cbc\u8e8f\u9e9f", + liu: "\u6e9c\u7409\u69b4\u786b\u998f\u7559\u5218\u7624\u6d41\u67f3\u516d\u62a1\u507b\u848c\u6cd6\u6d4f\u905b\u9a9d\u7efa\u65d2\u7198\u950d\u954f\u9e68\u938f", + long: "\u9f99\u804b\u5499\u7b3c\u7abf\u9686\u5784\u62e2\u9647\u5f04\u5785\u830f\u6cf7\u73d1\u680a\u80e7\u783b\u7643", + lou: "\u697c\u5a04\u6402\u7bd3\u6f0f\u964b\u55bd\u5d5d\u9542\u7618\u8027\u877c\u9ac5", + lu: "\u82a6\u5362\u9885\u5e90\u7089\u63b3\u5364\u864f\u9c81\u9e93\u788c\u9732\u8def\u8d42\u9e7f\u6f5e\u7984\u5f55\u9646\u622e\u5786\u6445\u64b8\u565c\u6cf8\u6e0c\u6f09\u7490\u680c\u6a79\u8f73\u8f82\u8f98\u6c07\u80ea\u9565\u9e2c\u9e6d\u7c0f\u823b\u9c88", + lv: "\u9a74\u5415\u94dd\u4fa3\u65c5\u5c65\u5c61\u7f15\u8651\u6c2f\u5f8b\u7387\u6ee4\u7eff\u634b\u95fe\u6988\u8182\u7a06\u891b", + luan: "\u5ce6\u5b6a\u6ee6\u5375\u4e71\u683e\u9e3e\u92ae", + lue: "\u63a0\u7565\u950a", + lun: "\u8f6e\u4f26\u4ed1\u6ca6\u7eb6\u8bba\u56f5", + luo: "\u841d\u87ba\u7f57\u903b\u9523\u7ba9\u9aa1\u88f8\u843d\u6d1b\u9a86\u7edc\u502e\u8366\u645e\u7321\u6cfa\u6924\u8136\u9559\u7630\u96d2", + ma: "\u5988\u9ebb\u739b\u7801\u8682\u9a6c\u9a82\u561b\u5417\u551b\u72b8\u5b37\u6769\u9ebd", + mai: "\u57cb\u4e70\u9ea6\u5356\u8fc8\u8109\u52a2\u836c\u54aa\u973e", + man: "\u7792\u9992\u86ee\u6ee1\u8513\u66fc\u6162\u6f2b\u8c29\u5881\u5e54\u7f26\u71b3\u9558\u989f\u87a8\u9cd7\u9794", + mang: "\u8292\u832b\u76f2\u5fd9\u83bd\u9099\u6f2d\u6726\u786d\u87d2", + meng: "\u6c13\u840c\u8499\u6aac\u76df\u9530\u731b\u68a6\u5b5f\u52d0\u750d\u77a2\u61f5\u791e\u867b\u8722\u8813\u824b\u8268\u9efe", + miao: "\u732b\u82d7\u63cf\u7784\u85d0\u79d2\u6e3a\u5e99\u5999\u55b5\u9088\u7f08\u7f2a\u676a\u6dfc\u7707\u9e4b\u8731", + mao: "\u8305\u951a\u6bdb\u77db\u94c6\u536f\u8302\u5192\u5e3d\u8c8c\u8d38\u4f94\u88a4\u52d6\u8306\u5cc1\u7441\u6634\u7266\u8004\u65c4\u61cb\u7780\u86d1\u8765\u87ca\u9ae6", + me: "\u4e48", + mei: "\u73ab\u679a\u6885\u9176\u9709\u7164\u6ca1\u7709\u5a92\u9541\u6bcf\u7f8e\u6627\u5bd0\u59b9\u5a9a\u5776\u8393\u5d4b\u7338\u6d7c\u6e44\u6963\u9545\u9e5b\u8882\u9b45", + men: "\u95e8\u95f7\u4eec\u626a\u739f\u7116\u61d1\u9494", + mi: "\u772f\u919a\u9761\u7cdc\u8ff7\u8c1c\u5f25\u7c73\u79d8\u89c5\u6ccc\u871c\u5bc6\u5e42\u8288\u5196\u8c27\u863c\u5627\u7315\u736f\u6c68\u5b93\u5f2d\u8112\u6549\u7cf8\u7e3b\u9e8b", + mian: "\u68c9\u7720\u7ef5\u5195\u514d\u52c9\u5a29\u7f05\u9762\u6c94\u6e4e\u817c\u7704", + mie: "\u8511\u706d\u54a9\u881b\u7bfe", + min: "\u6c11\u62bf\u76bf\u654f\u60af\u95fd\u82e0\u5cb7\u95f5\u6cef\u73c9", + ming: "\u660e\u879f\u9e23\u94ed\u540d\u547d\u51a5\u8317\u6e9f\u669d\u7791\u9169", + miu: "\u8c2c", + mo: "\u6478\u6479\u8611\u6a21\u819c\u78e8\u6469\u9b54\u62b9\u672b\u83ab\u58a8\u9ed8\u6cab\u6f20\u5bde\u964c\u8c1f\u8309\u84e6\u998d\u5aeb\u9546\u79e3\u763c\u8031\u87c6\u8c8a\u8c98", + mou: "\u8c0b\u725f\u67d0\u53b6\u54de\u5a7a\u7738\u936a", + mu: "\u62c7\u7261\u4ea9\u59c6\u6bcd\u5893\u66ae\u5e55\u52df\u6155\u6728\u76ee\u7766\u7267\u7a46\u4eeb\u82dc\u5452\u6c90\u6bea\u94bc", + na: "\u62ff\u54ea\u5450\u94a0\u90a3\u5a1c\u7eb3\u5185\u637a\u80ad\u954e\u8872\u7bac", + nai: "\u6c16\u4e43\u5976\u8010\u5948\u9f10\u827f\u8418\u67f0", + nan: "\u5357\u7537\u96be\u56ca\u5583\u56e1\u6960\u8169\u877b\u8d67", + nao: "\u6320\u8111\u607c\u95f9\u5b6c\u57b4\u7331\u7459\u7847\u94d9\u86f2", + ne: "\u6dd6\u5462\u8bb7", + nei: "\u9981", + nen: "\u5ae9\u80fd\u6798\u6041", + ni: "\u59ae\u9713\u502a\u6ce5\u5c3c\u62df\u4f60\u533f\u817b\u9006\u6eba\u4f32\u576d\u730a\u6029\u6ee0\u6635\u65ce\u7962\u615d\u7768\u94cc\u9cb5", + nian: "\u852b\u62c8\u5e74\u78be\u64b5\u637b\u5ff5\u5eff\u8f87\u9ecf\u9c87\u9cb6", + niang: "\u5a18\u917f", + niao: "\u9e1f\u5c3f\u8311\u5b32\u8132\u8885", + nie: "\u634f\u8042\u5b7d\u556e\u954a\u954d\u6d85\u4e5c\u9667\u8616\u55eb\u8080\u989e\u81ec\u8e51", + nin: "\u60a8\u67e0", + ning: "\u72de\u51dd\u5b81\u62e7\u6cde\u4f5e\u84e5\u549b\u752f\u804d", + niu: "\u725b\u626d\u94ae\u7ebd\u72c3\u5ff8\u599e\u86b4", + nong: "\u8113\u6d53\u519c\u4fac", + nu: "\u5974\u52aa\u6012\u5476\u5e11\u5f29\u80ec\u5b65\u9a7d", + nv: "\u5973\u6067\u9495\u8844", + nuan: "\u6696", + nuenue: "\u8650", + nue: "\u759f\u8c11", + nuo: "\u632a\u61e6\u7cef\u8bfa\u50a9\u6426\u558f\u9518", + ou: "\u54e6\u6b27\u9e25\u6bb4\u85d5\u5455\u5076\u6ca4\u6004\u74ef\u8026", + pa: "\u556a\u8db4\u722c\u5e15\u6015\u7436\u8469\u7b62", + pai: "\u62cd\u6392\u724c\u5f98\u6e43\u6d3e\u4ff3\u848e", + pan: "\u6500\u6f58\u76d8\u78d0\u76fc\u7554\u5224\u53db\u723f\u6cee\u88a2\u897b\u87e0\u8e52", + pang: "\u4e53\u5e9e\u65c1\u802a\u80d6\u6ec2\u9004", + pao: "\u629b\u5486\u5228\u70ae\u888d\u8dd1\u6ce1\u530f\u72cd\u5e96\u812c\u75b1", + pei: "\u5478\u80da\u57f9\u88f4\u8d54\u966a\u914d\u4f69\u6c9b\u638a\u8f94\u5e14\u6de0\u65c6\u952b\u9185\u9708", + pen: "\u55b7\u76c6\u6e53", + peng: "\u7830\u62a8\u70f9\u6f8e\u5f6d\u84ec\u68da\u787c\u7bf7\u81a8\u670b\u9e4f\u6367\u78b0\u576f\u580b\u562d\u6026\u87db", + pi: "\u7812\u9739\u6279\u62ab\u5288\u7435\u6bd7\u5564\u813e\u75b2\u76ae\u5339\u75de\u50fb\u5c41\u8b6c\u4e15\u9674\u90b3\u90eb\u572e\u9f19\u64d7\u567c\u5e80\u5ab2\u7eb0\u6787\u7513\u7765\u7f74\u94cd\u75e6\u7656\u758b\u868d\u8c94", + pian: "\u7bc7\u504f\u7247\u9a97\u8c1d\u9a88\u728f\u80fc\u890a\u7fe9\u8e41", + piao: "\u98d8\u6f02\u74e2\u7968\u527d\u560c\u5ad6\u7f25\u6b8d\u779f\u87b5", + pie: "\u6487\u77a5\u4e3f\u82e4\u6c15", + pin: "\u62fc\u9891\u8d2b\u54c1\u8058\u62da\u59d8\u5ad4\u6980\u725d\u98a6", + ping: "\u4e52\u576a\u82f9\u840d\u5e73\u51ed\u74f6\u8bc4\u5c4f\u4fdc\u5a09\u67b0\u9c86", + po: "\u5761\u6cfc\u9887\u5a46\u7834\u9b44\u8feb\u7c95\u53f5\u9131\u6ea5\u73c0\u948b\u94b7\u76a4\u7b38", + pou: "\u5256\u88d2\u8e23", + pu: "\u6251\u94fa\u4ec6\u8386\u8461\u83e9\u84b2\u57d4\u6734\u5703\u666e\u6d66\u8c31\u66dd\u7011\u530d\u5657\u6fee\u749e\u6c06\u9564\u9568\u8e7c", + qi: "\u671f\u6b3a\u6816\u621a\u59bb\u4e03\u51c4\u6f06\u67d2\u6c8f\u5176\u68cb\u5947\u6b67\u7566\u5d0e\u8110\u9f50\u65d7\u7948\u7941\u9a91\u8d77\u5c82\u4e5e\u4f01\u542f\u5951\u780c\u5668\u6c14\u8fc4\u5f03\u6c7d\u6ce3\u8bab\u4e9f\u4e93\u573b\u8291\u840b\u847a\u5601\u5c7a\u5c90\u6c54\u6dc7\u9a90\u7eee\u742a\u7426\u675e\u6864\u69ed\u6b39\u797a\u61a9\u789b\u86f4\u871e\u7da6\u7dae\u8dbf\u8e4a\u9ccd\u9e92", + qia: "\u6390\u6070\u6d3d\u845c", + qian: "\u7275\u6266\u948e\u94c5\u5343\u8fc1\u7b7e\u4edf\u8c26\u4e7e\u9ed4\u94b1\u94b3\u524d\u6f5c\u9063\u6d45\u8c34\u5811\u5d4c\u6b20\u6b49\u4f65\u9621\u828a\u82a1\u8368\u63ae\u5c8d\u60ad\u614a\u9a9e\u6434\u8930\u7f31\u6920\u80b7\u6106\u94a4\u8654\u7b9d", + qiang: + "\u67aa\u545b\u8154\u7f8c\u5899\u8537\u5f3a\u62a2\u5af1\u6a2f\u6217\u709d\u9516\u9535\u956a\u8941\u8723\u7f9f\u8deb\u8dc4", + qiao: "\u6a47\u9539\u6572\u6084\u6865\u77a7\u4e54\u4fa8\u5de7\u9798\u64ac\u7fd8\u5ced\u4fcf\u7a8d\u5281\u8bee\u8c2f\u835e\u6100\u6194\u7f32\u6a35\u6bf3\u7857\u8df7\u9792", + qie: "\u5207\u8304\u4e14\u602f\u7a83\u90c4\u553c\u60ec\u59be\u6308\u9532\u7ba7", + qin: "\u94a6\u4fb5\u4eb2\u79e6\u7434\u52e4\u82b9\u64d2\u79bd\u5bdd\u6c81\u82a9\u84c1\u8572\u63ff\u5423\u55ea\u5659\u6eb1\u6a8e\u8793\u887e", + qing: "\u9752\u8f7b\u6c22\u503e\u537f\u6e05\u64ce\u6674\u6c30\u60c5\u9877\u8bf7\u5e86\u5029\u82d8\u570a\u6aa0\u78ec\u873b\u7f44\u7b90\u8b26\u9cad\u9ee5", + qiong: "\u743c\u7a77\u909b\u8315\u7a79\u7b47\u928e", + qiu: "\u79cb\u4e18\u90b1\u7403\u6c42\u56da\u914b\u6cc5\u4fc5\u6c3d\u5def\u827d\u72b0\u6e6b\u9011\u9052\u6978\u8d47\u9e20\u866c\u86af\u8764\u88d8\u7cd7\u9cc5\u9f3d", + qu: "\u8d8b\u533a\u86c6\u66f2\u8eaf\u5c48\u9a71\u6e20\u53d6\u5a36\u9f8b\u8da3\u53bb\u8bce\u52ac\u8556\u8627\u5c96\u8862\u9612\u74a9\u89d1\u6c0d\u795b\u78f2\u766f\u86d0\u883c\u9eb4\u77bf\u9ee2", + quan: "\u5708\u98a7\u6743\u919b\u6cc9\u5168\u75ca\u62f3\u72ac\u5238\u529d\u8be0\u8343\u737e\u609b\u7efb\u8f81\u754e\u94e8\u8737\u7b4c\u9b08", + que: "\u7f3a\u7094\u7638\u5374\u9e4a\u69b7\u786e\u96c0\u9619\u60ab", + qun: "\u88d9\u7fa4\u9021", + ran: "\u7136\u71c3\u5189\u67d3\u82d2\u9aef", + rang: "\u74e4\u58e4\u6518\u56b7\u8ba9\u79b3\u7a70", + rao: "\u9976\u6270\u7ed5\u835b\u5a06\u6861", + ruo: "\u60f9\u82e5\u5f31", + re: "\u70ed\u504c", + ren: "\u58ec\u4ec1\u4eba\u5fcd\u97e7\u4efb\u8ba4\u5203\u598a\u7eab\u4ede\u834f\u845a\u996a\u8f6b\u7a14\u887d", + reng: "\u6254\u4ecd", + ri: "\u65e5", + rong: "\u620e\u8338\u84c9\u8363\u878d\u7194\u6eb6\u5bb9\u7ed2\u5197\u5d58\u72e8\u7f1b\u6995\u877e", + rou: "\u63c9\u67d4\u8089\u7cc5\u8e42\u97a3", + ru: "\u8339\u8815\u5112\u5b7a\u5982\u8fb1\u4e73\u6c5d\u5165\u8925\u84d0\u85b7\u5685\u6d33\u6ebd\u6fe1\u94f7\u8966\u98a5", + ruan: "\u8f6f\u962e\u670a", + rui: "\u854a\u745e\u9510\u82ae\u8564\u777f\u868b", + run: "\u95f0\u6da6", + sa: "\u6492\u6d12\u8428\u5345\u4ee8\u6332\u98d2", + sai: "\u816e\u9cc3\u585e\u8d5b\u567b", + san: "\u4e09\u53c1\u4f1e\u6563\u5f61\u9993\u6c35\u6bf5\u7cc1\u9730", + sang: "\u6851\u55d3\u4e27\u6421\u78c9\u98a1", + sao: "\u6414\u9a9a\u626b\u5ac2\u57fd\u81ca\u7619\u9ccb", + se: "\u745f\u8272\u6da9\u556c\u94e9\u94ef\u7a51", + sen: "\u68ee", + seng: "\u50e7", + sha: "\u838e\u7802\u6740\u5239\u6c99\u7eb1\u50bb\u5565\u715e\u810e\u6b43\u75e7\u88df\u970e\u9ca8", + shai: "\u7b5b\u6652\u917e", + shan: "\u73ca\u82eb\u6749\u5c71\u5220\u717d\u886b\u95ea\u9655\u64c5\u8d61\u81b3\u5584\u6c55\u6247\u7f2e\u5261\u8baa\u912f\u57cf\u829f\u6f78\u59d7\u9a9f\u81bb\u9490\u759d\u87ee\u8222\u8dda\u9cdd", + shang: + "\u5892\u4f24\u5546\u8d4f\u664c\u4e0a\u5c1a\u88f3\u57a7\u7ef1\u6b87\u71b5\u89de", + shao: "\u68a2\u634e\u7a0d\u70e7\u828d\u52fa\u97f6\u5c11\u54e8\u90b5\u7ecd\u52ad\u82d5\u6f72\u86f8\u7b24\u7b72\u8244", + she: "\u5962\u8d4a\u86c7\u820c\u820d\u8d66\u6444\u5c04\u6151\u6d89\u793e\u8bbe\u538d\u4f58\u731e\u7572\u9e9d", + shen: "\u7837\u7533\u547b\u4f38\u8eab\u6df1\u5a20\u7ec5\u795e\u6c88\u5ba1\u5a76\u751a\u80be\u614e\u6e17\u8bdc\u8c02\u5432\u54c2\u6e16\u6939\u77e7\u8703", + sheng: + "\u58f0\u751f\u7525\u7272\u5347\u7ef3\u7701\u76db\u5269\u80dc\u5723\u4e1e\u6e11\u5ab5\u771a\u7b19", + shi: "\u5e08\u5931\u72ee\u65bd\u6e7f\u8bd7\u5c38\u8671\u5341\u77f3\u62fe\u65f6\u4ec0\u98df\u8680\u5b9e\u8bc6\u53f2\u77e2\u4f7f\u5c4e\u9a76\u59cb\u5f0f\u793a\u58eb\u4e16\u67ff\u4e8b\u62ed\u8a93\u901d\u52bf\u662f\u55dc\u566c\u9002\u4ed5\u4f8d\u91ca\u9970\u6c0f\u5e02\u6043\u5ba4\u89c6\u8bd5\u8c25\u57d8\u83b3\u84cd\u5f11\u5511\u9963\u8f7c\u8006\u8d33\u70bb\u793b\u94c8\u94ca\u87ab\u8210\u7b6e\u8c55\u9ca5\u9cba", + shou: "\u6536\u624b\u9996\u5b88\u5bff\u6388\u552e\u53d7\u7626\u517d\u624c\u72e9\u7ef6\u824f", + shu: "\u852c\u67a2\u68b3\u6b8a\u6292\u8f93\u53d4\u8212\u6dd1\u758f\u4e66\u8d4e\u5b70\u719f\u85af\u6691\u66d9\u7f72\u8700\u9ecd\u9f20\u5c5e\u672f\u8ff0\u6811\u675f\u620d\u7ad6\u5885\u5eb6\u6570\u6f31\u6055\u500f\u587e\u83fd\u5fc4\u6cad\u6d91\u6f8d\u59dd\u7ebe\u6bf9\u8167\u6bb3\u956f\u79eb\u9e6c", + shua: "\u5237\u800d\u5530\u6dae", + shuai: "\u6454\u8870\u7529\u5e05\u87c0", + shuan: "\u6813\u62f4\u95e9", + shuang: "\u971c\u53cc\u723d\u5b40", + shui: "\u8c01\u6c34\u7761\u7a0e", + shun: "\u542e\u77ac\u987a\u821c\u6042", + shuo: "\u8bf4\u7855\u6714\u70c1\u84b4\u6420\u55cd\u6fef\u5981\u69ca\u94c4", + si: "\u65af\u6495\u5636\u601d\u79c1\u53f8\u4e1d\u6b7b\u8086\u5bfa\u55e3\u56db\u4f3a\u4f3c\u9972\u5df3\u53ae\u4fdf\u5155\u83e5\u549d\u6c5c\u6cd7\u6f8c\u59d2\u9a77\u7f0c\u7940\u7960\u9536\u9e36\u801c\u86f3\u7b25", + song: "\u677e\u8038\u6002\u9882\u9001\u5b8b\u8bbc\u8bf5\u51c7\u83d8\u5d27\u5d69\u5fea\u609a\u6dde\u7ae6", + sou: "\u641c\u8258\u64de\u55fd\u53df\u55d6\u55fe\u998a\u6eb2\u98d5\u778d\u953c\u878b", + su: "\u82cf\u9165\u4fd7\u7d20\u901f\u7c9f\u50f3\u5851\u6eaf\u5bbf\u8bc9\u8083\u5919\u8c21\u850c\u55c9\u612b\u7c0c\u89eb\u7a23", + suan: "\u9178\u849c\u7b97", + sui: "\u867d\u968b\u968f\u7ee5\u9ad3\u788e\u5c81\u7a57\u9042\u96a7\u795f\u84d1\u51ab\u8c07\u6fc9\u9083\u71e7\u772d\u7762", + sun: "\u5b59\u635f\u7b0b\u836a\u72f2\u98e7\u69ab\u8de3\u96bc", + suo: "\u68ad\u5506\u7f29\u7410\u7d22\u9501\u6240\u5522\u55e6\u5a11\u686b\u7743\u7fa7", + ta: "\u584c\u4ed6\u5b83\u5979\u5854\u736d\u631e\u8e4b\u8e0f\u95fc\u6ebb\u9062\u69bb\u6c93", + tai: "\u80ce\u82d4\u62ac\u53f0\u6cf0\u915e\u592a\u6001\u6c70\u90b0\u85b9\u80bd\u70b1\u949b\u8dc6\u9c90", + tan: "\u574d\u644a\u8d2a\u762b\u6ee9\u575b\u6a80\u75f0\u6f6d\u8c2d\u8c08\u5766\u6bef\u8892\u78b3\u63a2\u53f9\u70ad\u90ef\u8548\u6619\u94bd\u952c\u8983", + tang: "\u6c64\u5858\u642a\u5802\u68e0\u819b\u5510\u7cd6\u50a5\u9967\u6e8f\u746d\u94f4\u9557\u8025\u8797\u87b3\u7fb0\u91a3", + thang: "\u5018\u8eba\u6dcc", + theng: "\u8d9f\u70eb", + tao: "\u638f\u6d9b\u6ed4\u7ee6\u8404\u6843\u9003\u6dd8\u9676\u8ba8\u5957\u6311\u9f17\u5555\u97ec\u9955", + te: "\u7279", + teng: "\u85e4\u817e\u75bc\u8a8a\u6ed5", + ti: "\u68af\u5254\u8e22\u9511\u63d0\u9898\u8e44\u557c\u4f53\u66ff\u568f\u60d5\u6d95\u5243\u5c49\u8351\u608c\u9016\u7ee8\u7f07\u9e48\u88fc\u918d", + tian: "\u5929\u6dfb\u586b\u7530\u751c\u606c\u8214\u8146\u63ad\u5fdd\u9617\u6b84\u754b\u94bf\u86ba", + tiao: "\u6761\u8fe2\u773a\u8df3\u4f7b\u7967\u94eb\u7a95\u9f86\u9ca6", + tie: "\u8d34\u94c1\u5e16\u841c\u992e", + ting: "\u5385\u542c\u70c3\u6c40\u5ef7\u505c\u4ead\u5ead\u633a\u8247\u839b\u8476\u5a77\u6883\u8713\u9706", + tong: "\u901a\u6850\u916e\u77b3\u540c\u94dc\u5f64\u7ae5\u6876\u6345\u7b52\u7edf\u75db\u4f5f\u50ee\u4edd\u833c\u55f5\u6078\u6f7c\u783c", + tou: "\u5077\u6295\u5934\u900f\u4ea0", + tu: "\u51f8\u79c3\u7a81\u56fe\u5f92\u9014\u6d82\u5c60\u571f\u5410\u5154\u580d\u837c\u83df\u948d\u9174", + tuan: "\u6e4d\u56e2\u7583", + tui: "\u63a8\u9893\u817f\u8715\u892a\u9000\u5fd2\u717a", + tun: "\u541e\u5c6f\u81c0\u9968\u66be\u8c5a\u7a80", + tuo: "\u62d6\u6258\u8131\u9e35\u9640\u9a6e\u9a7c\u692d\u59a5\u62d3\u553e\u4e47\u4f57\u5768\u5eb9\u6cb1\u67dd\u7823\u7ba8\u8204\u8dce\u9f0d", + wa: "\u6316\u54c7\u86d9\u6d3c\u5a03\u74e6\u889c\u4f64\u5a32\u817d", + wai: "\u6b6a\u5916", + wan: "\u8c4c\u5f2f\u6e7e\u73a9\u987d\u4e38\u70f7\u5b8c\u7897\u633d\u665a\u7696\u60cb\u5b9b\u5a49\u4e07\u8155\u525c\u8284\u82cb\u83c0\u7ea8\u7efe\u742c\u8118\u7579\u873f\u7ba2", + wang: "\u6c6a\u738b\u4ea1\u6789\u7f51\u5f80\u65fa\u671b\u5fd8\u5984\u7f54\u5c22\u60d8\u8f8b\u9b4d", + wei: "\u5a01\u5dcd\u5fae\u5371\u97e6\u8fdd\u6845\u56f4\u552f\u60df\u4e3a\u6f4d\u7ef4\u82c7\u840e\u59d4\u4f1f\u4f2a\u5c3e\u7eac\u672a\u851a\u5473\u754f\u80c3\u5582\u9b4f\u4f4d\u6e2d\u8c13\u5c09\u6170\u536b\u502d\u504e\u8bff\u9688\u8473\u8587\u5e0f\u5e37\u5d34\u5d6c\u7325\u732c\u95f1\u6ca9\u6d27\u6da0\u9036\u5a13\u73ae\u97ea\u8ece\u709c\u7168\u71a8\u75ff\u8249\u9c94", + wen: "\u761f\u6e29\u868a\u6587\u95fb\u7eb9\u543b\u7a33\u7d0a\u95ee\u520e\u6120\u960c\u6c76\u74ba\u97eb\u6b81\u96ef", + weng: "\u55e1\u7fc1\u74ee\u84ca\u8579", + wo: "\u631d\u8717\u6da1\u7a9d\u6211\u65a1\u5367\u63e1\u6c83\u83b4\u5e44\u6e25\u674c\u809f\u9f8c", + wu: "\u5deb\u545c\u94a8\u4e4c\u6c61\u8bec\u5c4b\u65e0\u829c\u68a7\u543e\u5434\u6bcb\u6b66\u4e94\u6342\u5348\u821e\u4f0d\u4fae\u575e\u620a\u96fe\u6664\u7269\u52ff\u52a1\u609f\u8bef\u5140\u4ef5\u9622\u90ac\u572c\u82b4\u5e91\u6003\u5fe4\u6d6f\u5be4\u8fd5\u59a9\u9a9b\u727e\u7110\u9e49\u9e5c\u8708\u92c8\u9f2f", + xi: "\u6614\u7199\u6790\u897f\u7852\u77fd\u6670\u563b\u5438\u9521\u727a\u7a00\u606f\u5e0c\u6089\u819d\u5915\u60dc\u7184\u70ef\u6eaa\u6c50\u7280\u6a84\u88ad\u5e2d\u4e60\u5ab3\u559c\u94e3\u6d17\u7cfb\u9699\u620f\u7ec6\u50d6\u516e\u96b0\u90d7\u831c\u8478\u84f0\u595a\u550f\u5f99\u9969\u960b\u6d60\u6dc5\u5c63\u5b09\u73ba\u6a28\u66e6\u89cb\u6b37\u71b9\u798a\u79a7\u94b8\u7699\u7a78\u8725\u87cb\u823e\u7fb2\u7c9e\u7fd5\u91af\u9f37", + xia: "\u778e\u867e\u5323\u971e\u8f96\u6687\u5ce1\u4fa0\u72ed\u4e0b\u53a6\u590f\u5413\u6380\u846d\u55c4\u72ce\u9050\u7455\u7856\u7615\u7f45\u9ee0", + xian: "\u9528\u5148\u4ed9\u9c9c\u7ea4\u54b8\u8d24\u8854\u8237\u95f2\u6d8e\u5f26\u5acc\u663e\u9669\u73b0\u732e\u53bf\u817a\u9985\u7fa1\u5baa\u9677\u9650\u7ebf\u51bc\u85d3\u5c98\u7303\u66b9\u5a34\u6c19\u7946\u9e47\u75eb\u86ac\u7b45\u7c7c\u9170\u8df9", + xiang: + "\u76f8\u53a2\u9576\u9999\u7bb1\u8944\u6e58\u4e61\u7fd4\u7965\u8be6\u60f3\u54cd\u4eab\u9879\u5df7\u6a61\u50cf\u5411\u8c61\u8297\u8459\u9977\u5ea0\u9aa7\u7f03\u87d3\u9c9e\u98e8", + xiao: "\u8427\u785d\u9704\u524a\u54ee\u56a3\u9500\u6d88\u5bb5\u6dc6\u6653\u5c0f\u5b5d\u6821\u8096\u5578\u7b11\u6548\u54d3\u54bb\u5d24\u6f47\u900d\u9a81\u7ee1\u67ad\u67b5\u7b71\u7bab\u9b48", + xie: "\u6954\u4e9b\u6b47\u874e\u978b\u534f\u631f\u643a\u90aa\u659c\u80c1\u8c10\u5199\u68b0\u5378\u87f9\u61c8\u6cc4\u6cfb\u8c22\u5c51\u5055\u4eb5\u52f0\u71ee\u85a4\u64b7\u5ee8\u7023\u9082\u7ec1\u7f2c\u69ad\u698d\u6b59\u8e9e", + xin: "\u85aa\u82af\u950c\u6b23\u8f9b\u65b0\u5ffb\u5fc3\u4fe1\u8845\u56df\u99a8\u8398\u6b46\u94fd\u946b", + xing: "\u661f\u8165\u7329\u60fa\u5174\u5211\u578b\u5f62\u90a2\u884c\u9192\u5e78\u674f\u6027\u59d3\u9649\u8347\u8365\u64e4\u60bb\u784e", + xiong: "\u5144\u51f6\u80f8\u5308\u6c79\u96c4\u718a\u828e", + xiu: "\u4f11\u4fee\u7f9e\u673d\u55c5\u9508\u79c0\u8896\u7ee3\u83a0\u5cab\u9990\u5ea5\u9e3a\u8c85\u9af9", + xu: "\u589f\u620c\u9700\u865a\u5618\u987b\u5f90\u8bb8\u84c4\u9157\u53d9\u65ed\u5e8f\u755c\u6064\u7d6e\u5a7f\u7eea\u7eed\u8bb4\u8be9\u5729\u84ff\u6035\u6d2b\u6e86\u987c\u6829\u7166\u7809\u76f1\u80e5\u7cc8\u9191", + xuan: "\u8f69\u55a7\u5ba3\u60ac\u65cb\u7384\u9009\u7663\u7729\u7eda\u5107\u8c16\u8431\u63ce\u9994\u6ceb\u6d35\u6e32\u6f29\u7487\u6966\u6684\u70ab\u714a\u78b9\u94c9\u955f\u75c3", + xue: "\u9774\u859b\u5b66\u7a74\u96ea\u8840\u5671\u6cf6\u9cd5", + xun: "\u52cb\u718f\u5faa\u65ec\u8be2\u5bfb\u9a6f\u5de1\u6b89\u6c5b\u8bad\u8baf\u900a\u8fc5\u5dfd\u57d9\u8340\u85b0\u5ccb\u5f87\u6d54\u66db\u7aa8\u91ba\u9c9f", + ya: "\u538b\u62bc\u9e26\u9e2d\u5440\u4e2b\u82bd\u7259\u869c\u5d16\u8859\u6daf\u96c5\u54d1\u4e9a\u8bb6\u4f22\u63e0\u5416\u5c88\u8fd3\u5a05\u740a\u6860\u6c29\u7811\u775a\u75d6", + yan: "\u7109\u54bd\u9609\u70df\u6df9\u76d0\u4e25\u7814\u8712\u5ca9\u5ef6\u8a00\u989c\u960e\u708e\u6cbf\u5944\u63a9\u773c\u884d\u6f14\u8273\u5830\u71d5\u538c\u781a\u96c1\u5501\u5f66\u7130\u5bb4\u8c1a\u9a8c\u53a3\u9765\u8d5d\u4fe8\u5043\u5156\u8ba0\u8c33\u90fe\u9122\u82ab\u83f8\u5d26\u6079\u95eb\u960f\u6d07\u6e6e\u6edf\u598d\u5ae3\u7430\u664f\u80ed\u814c\u7131\u7f68\u7b75\u917d\u9b47\u990d\u9f39", + yang: "\u6b83\u592e\u9e2f\u79e7\u6768\u626c\u4f6f\u75a1\u7f8a\u6d0b\u9633\u6c27\u4ef0\u75d2\u517b\u6837\u6f3e\u5f89\u600f\u6cf1\u7080\u70ca\u6059\u86d8\u9785", + yao: "\u9080\u8170\u5996\u7476\u6447\u5c27\u9065\u7a91\u8c23\u59da\u54ac\u8200\u836f\u8981\u8000\u592d\u723b\u5406\u5d3e\u5fad\u7039\u5e7a\u73e7\u6773\u66dc\u80b4\u9e5e\u7a88\u7e47\u9cd0", + ye: "\u6930\u564e\u8036\u7237\u91ce\u51b6\u4e5f\u9875\u6396\u4e1a\u53f6\u66f3\u814b\u591c\u6db2\u8c12\u90ba\u63f6\u9980\u6654\u70e8\u94d8", + yi: "\u4e00\u58f9\u533b\u63d6\u94f1\u4f9d\u4f0a\u8863\u9890\u5937\u9057\u79fb\u4eea\u80f0\u7591\u6c82\u5b9c\u59e8\u5f5d\u6905\u8681\u501a\u5df2\u4e59\u77e3\u4ee5\u827a\u6291\u6613\u9091\u5c79\u4ebf\u5f79\u81c6\u9038\u8084\u75ab\u4ea6\u88d4\u610f\u6bc5\u5fc6\u4e49\u76ca\u6ea2\u8be3\u8bae\u8c0a\u8bd1\u5f02\u7ffc\u7fcc\u7ece\u5208\u5293\u4f7e\u8bd2\u572a\u572f\u57f8\u61ff\u82e1\u858f\u5f08\u5955\u6339\u5f0b\u5453\u54a6\u54bf\u566b\u5cc4\u5db7\u7317\u9974\u603f\u6021\u6092\u6f2a\u8fe4\u9a7f\u7f22\u6baa\u8d3b\u65d6\u71a0\u9487\u9552\u9571\u75cd\u7617\u7654\u7fca\u8864\u8734\u8223\u7fbf\u7ff3\u914f\u9edf", + yin: "\u8335\u836b\u56e0\u6bb7\u97f3\u9634\u59fb\u541f\u94f6\u6deb\u5bc5\u996e\u5c39\u5f15\u9690\u5370\u80e4\u911e\u5819\u831a\u5591\u72fa\u5924\u6c24\u94df\u763e\u8693\u972a\u9f88", + ying: "\u82f1\u6a31\u5a74\u9e70\u5e94\u7f28\u83b9\u8424\u8425\u8367\u8747\u8fce\u8d62\u76c8\u5f71\u9896\u786c\u6620\u5b34\u90e2\u8314\u83ba\u8426\u6484\u5624\u81ba\u6ee2\u6f46\u701b\u745b\u748e\u6979\u9e66\u763f\u988d\u7f42", + yo: "\u54df\u5537", + yong: "\u62e5\u4f63\u81c3\u75c8\u5eb8\u96cd\u8e0a\u86f9\u548f\u6cf3\u6d8c\u6c38\u607f\u52c7\u7528\u4fd1\u58c5\u5889\u6175\u9095\u955b\u752c\u9cd9\u9954", + you: "\u5e7d\u4f18\u60a0\u5fe7\u5c24\u7531\u90ae\u94c0\u72b9\u6cb9\u6e38\u9149\u6709\u53cb\u53f3\u4f51\u91c9\u8bf1\u53c8\u5e7c\u5363\u6538\u4f91\u83b8\u5466\u56ff\u5ba5\u67da\u7337\u7256\u94d5\u75a3\u8763\u9c7f\u9edd\u9f2c", + yu: "\u8fc2\u6de4\u4e8e\u76c2\u6986\u865e\u611a\u8206\u4f59\u4fde\u903e\u9c7c\u6109\u6e1d\u6e14\u9685\u4e88\u5a31\u96e8\u4e0e\u5c7f\u79b9\u5b87\u8bed\u7fbd\u7389\u57df\u828b\u90c1\u5401\u9047\u55bb\u5cea\u5fa1\u6108\u6b32\u72f1\u80b2\u8a89\u6d74\u5bd3\u88d5\u9884\u8c6b\u9a6d\u79ba\u6bd3\u4f1b\u4fe3\u8c00\u8c15\u8438\u84e3\u63c4\u5581\u5704\u5709\u5d5b\u72f3\u996b\u5ebe\u9608\u59aa\u59a4\u7ea1\u745c\u6631\u89ce\u8174\u6b24\u65bc\u715c\u71e0\u807f\u94b0\u9e46\u7610\u7600\u7ab3\u8753\u7afd\u8201\u96e9\u9f89", + yuan: "\u9e33\u6e0a\u51a4\u5143\u57a3\u8881\u539f\u63f4\u8f95\u56ed\u5458\u5706\u733f\u6e90\u7f18\u8fdc\u82d1\u613f\u6028\u9662\u586c\u6c85\u5a9b\u7457\u6a7c\u7230\u7722\u9e22\u8788\u9f0b", + yue: "\u66f0\u7ea6\u8d8a\u8dc3\u94a5\u5cb3\u7ca4\u6708\u60a6\u9605\u9fa0\u6a3e\u5216\u94ba", + yun: "\u8018\u4e91\u90e7\u5300\u9668\u5141\u8fd0\u8574\u915d\u6655\u97f5\u5b55\u90d3\u82b8\u72c1\u607d\u7ead\u6b92\u6600\u6c32", + za: "\u531d\u7838\u6742\u62f6\u5482", + zai: "\u683d\u54c9\u707e\u5bb0\u8f7d\u518d\u5728\u54b1\u5d3d\u753e", + zan: "\u6512\u6682\u8d5e\u74d2\u661d\u7c2a\u7ccc\u8db1\u933e", + zang: "\u8d43\u810f\u846c\u5958\u6215\u81e7", + zao: "\u906d\u7cdf\u51ff\u85fb\u67a3\u65e9\u6fa1\u86a4\u8e81\u566a\u9020\u7682\u7076\u71e5\u5523\u7f2b", + ze: "\u8d23\u62e9\u5219\u6cfd\u4ec4\u8d5c\u5567\u8fee\u6603\u7b2e\u7ba6\u8234", + zei: "\u8d3c", + zen: "\u600e\u8c2e", + zeng: "\u589e\u618e\u66fe\u8d60\u7f2f\u7511\u7f7e\u9503", + zha: "\u624e\u55b3\u6e23\u672d\u8f67\u94e1\u95f8\u7728\u6805\u69a8\u548b\u4e4d\u70b8\u8bc8\u63f8\u5412\u54a4\u54f3\u600d\u781f\u75c4\u86b1\u9f44", + zhai: "\u6458\u658b\u5b85\u7a84\u503a\u5be8\u7826", + zhan: "\u77bb\u6be1\u8a79\u7c98\u6cbe\u76cf\u65a9\u8f97\u5d2d\u5c55\u8638\u6808\u5360\u6218\u7ad9\u6e5b\u7efd\u8c35\u640c\u65c3", + zhang: + "\u6a1f\u7ae0\u5f70\u6f33\u5f20\u638c\u6da8\u6756\u4e08\u5e10\u8d26\u4ed7\u80c0\u7634\u969c\u4ec9\u9123\u5e5b\u5d82\u7350\u5adc\u748b\u87d1", + zhao: "\u62db\u662d\u627e\u6cbc\u8d75\u7167\u7f69\u5146\u8087\u53ec\u722a\u8bcf\u68f9\u948a\u7b0a", + zhe: "\u906e\u6298\u54f2\u86f0\u8f99\u8005\u9517\u8517\u8fd9\u6d59\u8c2a\u966c\u67d8\u8f84\u78d4\u9e67\u891a\u8707\u8d6d", + zhen: "\u73cd\u659f\u771f\u7504\u7827\u81fb\u8d1e\u9488\u4fa6\u6795\u75b9\u8bca\u9707\u632f\u9547\u9635\u7f1c\u6862\u699b\u8f78\u8d48\u80d7\u6715\u796f\u755b\u9e29", + zheng: + "\u84b8\u6323\u7741\u5f81\u72f0\u4e89\u6014\u6574\u62ef\u6b63\u653f\u5e27\u75c7\u90d1\u8bc1\u8be4\u5ce5\u94b2\u94ee\u7b5d", + zhi: "\u829d\u679d\u652f\u5431\u8718\u77e5\u80a2\u8102\u6c41\u4e4b\u7ec7\u804c\u76f4\u690d\u6b96\u6267\u503c\u4f84\u5740\u6307\u6b62\u8dbe\u53ea\u65e8\u7eb8\u5fd7\u631a\u63b7\u81f3\u81f4\u7f6e\u5e1c\u5cd9\u5236\u667a\u79e9\u7a1a\u8d28\u7099\u75d4\u6ede\u6cbb\u7a92\u536e\u965f\u90c5\u57f4\u82b7\u646d\u5e19\u5fee\u5f58\u54ab\u9a98\u6809\u67b3\u6800\u684e\u8f75\u8f7e\u6534\u8d3d\u81a3\u7949\u7957\u9ef9\u96c9\u9e37\u75e3\u86ed\u7d77\u916f\u8dd6\u8e2c\u8e2f\u8c78\u89ef", + zhong: + "\u4e2d\u76c5\u5fe0\u949f\u8877\u7ec8\u79cd\u80bf\u91cd\u4ef2\u4f17\u51a2\u953a\u87bd\u8202\u822f\u8e35", + zhou: "\u821f\u5468\u5dde\u6d32\u8bcc\u7ca5\u8f74\u8098\u5e1a\u5492\u76b1\u5b99\u663c\u9aa4\u5544\u7740\u501c\u8bf9\u836e\u9b3b\u7ea3\u80c4\u78a1\u7c40\u8233\u914e\u9cb7", + zhu: "\u73e0\u682a\u86db\u6731\u732a\u8bf8\u8bdb\u9010\u7af9\u70db\u716e\u62c4\u77a9\u5631\u4e3b\u8457\u67f1\u52a9\u86c0\u8d2e\u94f8\u7b51\u4f4f\u6ce8\u795d\u9a7b\u4f2b\u4f8f\u90be\u82ce\u8331\u6d19\u6e1a\u6f74\u9a7a\u677c\u69e0\u6a65\u70b7\u94e2\u75b0\u7603\u86b0\u7afa\u7bb8\u7fe5\u8e85\u9e88", + zhua: "\u6293", + zhuai: "\u62fd", + zhuan: "\u4e13\u7816\u8f6c\u64b0\u8d5a\u7bc6\u629f\u556d\u989b", + zhuang: "\u6869\u5e84\u88c5\u5986\u649e\u58ee\u72b6\u4e2c", + zhui: "\u690e\u9525\u8ffd\u8d58\u5760\u7f00\u8411\u9a93\u7f12", + zhun: "\u8c06\u51c6", + zhuo: "\u6349\u62d9\u5353\u684c\u7422\u8301\u914c\u707c\u6d4a\u502c\u8bfc\u5ef4\u855e\u64e2\u555c\u6d5e\u6dbf\u6753\u712f\u799a\u65ab", + zi: "\u5179\u54a8\u8d44\u59ff\u6ecb\u6dc4\u5b5c\u7d2b\u4ed4\u7c7d\u6ed3\u5b50\u81ea\u6e0d\u5b57\u8c18\u5d6b\u59ca\u5b73\u7f01\u6893\u8f8e\u8d40\u6063\u7726\u9531\u79ed\u8014\u7b2b\u7ca2\u89dc\u8a3e\u9cbb\u9aed", + zong: "\u9b03\u68d5\u8e2a\u5b97\u7efc\u603b\u7eb5\u8159\u7cbd", + zou: "\u90b9\u8d70\u594f\u63cd\u9139\u9cb0", + zu: "\u79df\u8db3\u5352\u65cf\u7956\u8bc5\u963b\u7ec4\u4fce\u83f9\u5550\u5f82\u9a75\u8e74", + zuan: "\u94bb\u7e82\u6525\u7f35", + zui: "\u5634\u9189\u6700\u7f6a", + zun: "\u5c0a\u9075\u6499\u6a3d\u9cdf", + zuo: "\u6628\u5de6\u4f50\u67de\u505a\u4f5c\u5750\u5ea7\u961d\u963c\u80d9\u795a\u9162", + cou: "\u85ae\u6971\u8f8f\u8160", + nang: "\u652e\u54dd\u56d4\u9995\u66e9", + o: "\u5594", + dia: "\u55f2", + chuai: "\u562c\u81aa\u8e39", + cen: "\u5c91\u6d94", + diu: "\u94e5", + nou: "\u8028", + fou: "\u7f36", + bia: "\u9adf", +}; diff --git a/pc-client/src/utils/request.ts b/pc-client/src/utils/request.ts new file mode 100644 index 0000000..72c7b3f --- /dev/null +++ b/pc-client/src/utils/request.ts @@ -0,0 +1,58 @@ +import axios from "axios"; +import { t } from "i18next"; +import { v4 as uuidv4 } from "uuid"; + +import { useUserStore } from "@/store"; + +import { getChatToken, getIMToken } from "./storage"; +import { feedbackToast } from "./common"; + +const tokenErrorCodeList = [1501, 1503, 1504, 1505]; + +const createAxiosInstance = (baseURL: string, imToken = true) => { + const serves = axios.create({ + baseURL, + timeout: 25000, + }); + + serves.interceptors.request.use( + async (config) => { + const token = imToken ? await getIMToken() : await getChatToken(); + config.headers.token = config.headers.token ?? token; + config.headers.operationID = uuidv4(); + return config; + }, + (err) => Promise.reject(err), + ); + + serves.interceptors.response.use( + (res) => { + if (tokenErrorCodeList.includes(res.data.errCode)) { + feedbackToast({ + msg: t("toast.loginExpiration"), + error: t("toast.loginExpiration"), + onClose: () => { + useUserStore.getState().userLogout(true); + }, + }); + } + if (res.data.errCode !== 0) { + return Promise.reject(res.data); + } + return res.data; + }, + (err) => { + if (err.message.includes("timeout")) { + console.error("error", err); + } + if (err.message.includes("Network Error")) { + console.error("error", err); + } + return Promise.reject(err); + }, + ); + + return serves; +}; + +export default createAxiosInstance; diff --git a/pc-client/src/utils/storage.ts b/pc-client/src/utils/storage.ts new file mode 100644 index 0000000..e362145 --- /dev/null +++ b/pc-client/src/utils/storage.ts @@ -0,0 +1,54 @@ +import { LocaleString } from "@/store/type"; +import * as localForage from "localforage"; + +localForage.config({ + name: "OpenCorp-Config", +}); + +export const setAreaCode = (areaCode: string) => + localStorage.setItem("IM_AREA_CODE", areaCode); +export const setPhoneNumber = (account: string) => + localStorage.setItem("IM_PHONE_NUM", account); +export const setEmail = (email: string) => localStorage.setItem("IM_EMAIL", email); +export const setLoginMethod = (method: string) => + localStorage.setItem("IM_LOGIN_METHOD", method); +export const setTMToken = (token: string) => localForage.setItem("IM_TOKEN", token); +export const setChatToken = (token: string) => + localForage.setItem("IM_CHAT_TOKEN", token); +export const setTMUserID = (userID: string) => localForage.setItem("IM_USERID", userID); +export const setIMProfile = ({ + chatToken, + imToken, + userID, +}: { + chatToken: string; + imToken: string; + userID: string; +}) => { + setTMToken(imToken); + setChatToken(chatToken); + setTMUserID(userID); +}; + +export const setLocale = (locale: string) => localStorage.setItem("IM_LOCALE", locale); + +export const clearIMProfile = () => { + localForage.removeItem("IM_TOKEN"); + localForage.removeItem("IM_CHAT_TOKEN"); + localForage.removeItem("IM_USERID"); +}; + +export const getAreaCode = () => localStorage.getItem("IM_AREA_CODE"); +export const getPhoneNumber = () => localStorage.getItem("IM_PHONE_NUM"); +export const getEmail = () => localStorage.getItem("IM_EMAIL"); +export const getLoginMethod = () => + (localStorage.getItem("IM_LOGIN_METHOD") ?? "phone") as "phone" | "email"; +export const getIMToken = async () => await localForage.getItem("IM_TOKEN"); +export const getChatToken = async () => await localForage.getItem("IM_CHAT_TOKEN"); +export const getIMUserID = async () => await localForage.getItem("IM_USERID"); + +export const getLocale = (): LocaleString => + window.electronAPI?.ipcSendSync("getKeyStoreSync", { key: "language" }) || + (localStorage.getItem("IM_LOCALE") as LocaleString) || + window.navigator.language || + "zh-CN"; diff --git a/pc-client/src/vite-env.d.ts b/pc-client/src/vite-env.d.ts new file mode 100644 index 0000000..11f02fe --- /dev/null +++ b/pc-client/src/vite-env.d.ts @@ -0,0 +1 @@ +/// <reference types="vite/client" /> diff --git a/pc-client/tailwind.config.js b/pc-client/tailwind.config.js new file mode 100644 index 0000000..12d0ae9 --- /dev/null +++ b/pc-client/tailwind.config.js @@ -0,0 +1,30 @@ +/** @type {import('tailwindcss').Config} */ +module.exports = { + content: ["./index.html", "./src/**/*.{js,ts,jsx,tsx}"], + theme: { + extend: { + padding: { + 1.5: "0.375rem", + 2.5: "0.625rem", + 3.5: "0.875rem", + 4.5: "1.125rem", + 5.5: "1.375rem", + 6.5: "1.625rem", + }, + margin: { + 2.5: "0.625rem", + 3.5: "0.875rem", + 4.5: "1.125rem", + 5.5: "1.375rem", + 6.5: "1.625rem", + }, + width: { + 10.5: "2.625rem", + }, + height: { + 10.5: "2.625rem", + }, + }, + }, + darkMode: "class", +}; diff --git a/pc-client/tsconfig.json b/pc-client/tsconfig.json new file mode 100644 index 0000000..5c63679 --- /dev/null +++ b/pc-client/tsconfig.json @@ -0,0 +1,25 @@ +{ + "compilerOptions": { + "target": "ESNext", + "useDefineForClassFields": true, + "lib": ["DOM", "DOM.Iterable", "ESNext"], + "allowJs": false, + "skipLibCheck": true, + "esModuleInterop": false, + "allowSyntheticDefaultImports": true, + "strict": true, + "forceConsistentCasingInFileNames": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "isolatedModules": true, + "noEmit": true, + "jsx": "react-jsx", + "baseUrl": "./", + "paths": { + "@/*": ["src/*"] + } + }, + "include": ["src"], + "references": [{ "path": "./tsconfig.node.json" }] +} diff --git a/pc-client/tsconfig.node.json b/pc-client/tsconfig.node.json new file mode 100644 index 0000000..ed1b586 --- /dev/null +++ b/pc-client/tsconfig.node.json @@ -0,0 +1,10 @@ +{ + "compilerOptions": { + "composite": true, + "module": "ESNext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "allowSyntheticDefaultImports": true + }, + "include": ["vite.config.ts", "package.json", "electron"] +} diff --git a/pc-client/vite.config.ts b/pc-client/vite.config.ts new file mode 100644 index 0000000..a80d355 --- /dev/null +++ b/pc-client/vite.config.ts @@ -0,0 +1,85 @@ +import { rmSync } from "node:fs"; +import path from "node:path"; +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import electron from "vite-electron-plugin"; +import { customStart, loadViteEnv } from "vite-electron-plugin/plugin"; +import pkg from "./package.json"; +import legacy from "@vitejs/plugin-legacy"; +import { createRequire } from "node:module"; +const require = createRequire(import.meta.url); +// import visualizer from "rollup-plugin-visualizer"; + +// https://vitejs.dev/config/ +export default defineConfig(({ command }) => { + rmSync("dist-electron", { recursive: true, force: true }); + + const sourcemap = command === "serve" || !!process.env.VSCODE_DEBUG; + + return { + resolve: { + alias: { + "@": path.join(__dirname, "src"), + }, + }, + css: { + preprocessorOptions: { + scss: { + silenceDeprecations: ["legacy-js-api"], + }, + }, + }, + plugins: [ + react(), + electron({ + include: ["electron"], + transformOptions: { + sourcemap, + }, + plugins: [ + ...(!!process.env.VSCODE_DEBUG + ? [ + // Will start Electron via VSCode Debug + customStart(() => + console.log( + /* For `.vscode/.debug.script.mjs` */ "[startup] Electron App", + ), + ), + ] + : []), + // Allow use `import.meta.env.VITE_SOME_KEY` in Electron-Main + loadViteEnv(), + ], + }), + // legacy({ + // targets: ["defaults", "not IE 11"], + // }), + // visualizer({ open: true }), + ], + server: !!process.env.VSCODE_DEBUG + ? (() => { + const url = new URL(pkg.debug.env.VITE_DEV_SERVER_URL); + return { + host: url.hostname, + port: +url.port, + }; + })() + : undefined, + clearScreen: false, + build: { + sourcemap: false, + cssCodeSplit: true, + chunkSizeWarningLimit: 500, + terserOptions: { + compress: { + drop_console: true, + drop_debugger: true, + }, + }, + rollupOptions: { + output: { + }, + }, + }, + }; +}); diff --git a/pc-client/vite.legacy.config.ts b/pc-client/vite.legacy.config.ts new file mode 100644 index 0000000..67e12f1 --- /dev/null +++ b/pc-client/vite.legacy.config.ts @@ -0,0 +1,80 @@ +import { rmSync } from "node:fs"; +import path from "node:path"; +import { defineConfig } from "vite"; +import react from "@vitejs/plugin-react"; +import electron from "vite-electron-plugin"; +import { customStart, loadViteEnv } from "vite-electron-plugin/plugin"; +import preload from "vite-plugin-electron"; +import pkg from "./package.json"; + +let preloadHasReady = false; + +// https://vitejs.dev/config/ +export default defineConfig(({ command }) => { + rmSync("dist-electron", { recursive: true, force: true }); + + const sourcemap = command === "serve" || !!process.env.VSCODE_DEBUG; + + return { + resolve: { + alias: { + "@": path.join(__dirname, "src"), + }, + }, + plugins: [ + react(), + electron({ + include: ["electron/main"], + transformOptions: { + sourcemap, + }, + plugins: [ + customStart((args) => { + if (process.env.VSCODE_DEBUG) { + // Start Electron via VSCode + console.log( + /* For `.vscode/.debug.script.mjs` */ "[startup] Electron App", + ); + } else { + if (preloadHasReady) { + args?.startup(); + } else { + console.log("[startup] waiting for preload"); + } + } + }), + // Allow use `import.meta.env.VITE_SOME_KEY` in Main process + loadViteEnv(), + ], + }), + // Preload scripts + preload({ + entry: ["electron/preload/index.ts"], + vite: { + build: { + minify: false, + outDir: "dist-electron/preload", + }, + }, + onstart(args) { + if (preloadHasReady) { + args.reload(); + } else { + preloadHasReady = true; + args.startup(); + } + }, + }), + ], + server: !!process.env.VSCODE_DEBUG + ? (() => { + const url = new URL(pkg.debug.env.VITE_DEV_SERVER_URL); + return { + host: url.hostname, + port: +url.port, + }; + })() + : undefined, + clearScreen: false, + }; +});