From 84691ccc3a26951eea17d1ed21682d52009870ba Mon Sep 17 00:00:00 2001 From: Eric Woodward Date: Tue, 12 May 2026 23:57:41 -0400 Subject: [PATCH] Initial release --- .editorconfig | 17 +- .gitignore | 60 +- .prettierrc.json | 11 + .yarnrc.yml | 3 + LICENSE | 21 + README.md | 187 +- dist/package.json | 43 + dist/src/constants.d.ts | 1 + dist/src/constants.js | 4 + dist/src/constants.js.map | 1 + dist/src/emojiButton/client/emoji.css | 114 + dist/src/emojiButton/client/emoji.js | 2160 ++++++++++++++ dist/src/emojiButton/index.d.ts | 1 + dist/src/emojiButton/index.js | 2 + dist/src/emojiButton/index.js.map | 1 + dist/src/emojiButton/plugin.d.ts | 3 + dist/src/emojiButton/plugin.js | 32 + dist/src/emojiButton/plugin.js.map | 1 + dist/src/index.d.ts | 3 + dist/src/index.js | 4 + dist/src/index.js.map | 1 + dist/src/postToMastodon/client/script.js | 34 + dist/src/postToMastodon/index.d.ts | 1 + dist/src/postToMastodon/index.js | 2 + dist/src/postToMastodon/index.js.map | 1 + dist/src/postToMastodon/plugin.d.ts | 3 + dist/src/postToMastodon/plugin.js | 59 + dist/src/postToMastodon/plugin.js.map | 1 + dist/src/uploadButton/client/script.js | 154 + dist/src/uploadButton/client/styles.css | 37 + dist/src/uploadButton/defaults.d.ts | 12 + dist/src/uploadButton/defaults.js | 39 + dist/src/uploadButton/defaults.js.map | 1 + dist/src/uploadButton/index.d.ts | 1 + dist/src/uploadButton/index.js | 2 + dist/src/uploadButton/index.js.map | 1 + dist/src/uploadButton/plugin.d.ts | 3 + dist/src/uploadButton/plugin.js | 167 ++ dist/src/uploadButton/plugin.js.map | 1 + dist/src/uploadButton/types.d.ts | 13 + dist/src/uploadButton/types.js | 2 + dist/src/uploadButton/types.js.map | 1 + dist/src/uploadButton/utils.d.ts | 7 + dist/src/uploadButton/utils.js | 48 + dist/src/uploadButton/utils.js.map | 1 + eslint.config.js | 42 + package-lock.json | 30 + package.json | 54 +- src/constants.ts | 4 + src/emojiButton/client/emoji.css | 114 + src/emojiButton/client/emoji.js | 2160 ++++++++++++++ src/emojiButton/index.ts | 1 + src/emojiButton/plugin.ts | 47 + src/index.ts | 3 + src/postToMastodon/client/script.js | 34 + src/postToMastodon/index.ts | 1 + src/postToMastodon/plugin.ts | 88 + src/uploadButton/client/script.js | 154 + src/uploadButton/client/styles.css | 37 + src/uploadButton/defaults.ts | 40 + src/uploadButton/index.ts | 1 + src/uploadButton/plugin.ts | 237 ++ src/uploadButton/types.ts | 18 + src/uploadButton/utils.ts | 58 + tsconfig.json | 17 + yarn.lock | 3311 +++++++++++++++++++++- 66 files changed, 9689 insertions(+), 23 deletions(-) create mode 100644 .prettierrc.json create mode 100644 .yarnrc.yml create mode 100644 LICENSE create mode 100644 dist/package.json create mode 100644 dist/src/constants.d.ts create mode 100644 dist/src/constants.js create mode 100644 dist/src/constants.js.map create mode 100644 dist/src/emojiButton/client/emoji.css create mode 100644 dist/src/emojiButton/client/emoji.js create mode 100644 dist/src/emojiButton/index.d.ts create mode 100644 dist/src/emojiButton/index.js create mode 100644 dist/src/emojiButton/index.js.map create mode 100644 dist/src/emojiButton/plugin.d.ts create mode 100644 dist/src/emojiButton/plugin.js create mode 100644 dist/src/emojiButton/plugin.js.map create mode 100644 dist/src/index.d.ts create mode 100644 dist/src/index.js create mode 100644 dist/src/index.js.map create mode 100644 dist/src/postToMastodon/client/script.js create mode 100644 dist/src/postToMastodon/index.d.ts create mode 100644 dist/src/postToMastodon/index.js create mode 100644 dist/src/postToMastodon/index.js.map create mode 100644 dist/src/postToMastodon/plugin.d.ts create mode 100644 dist/src/postToMastodon/plugin.js create mode 100644 dist/src/postToMastodon/plugin.js.map create mode 100644 dist/src/uploadButton/client/script.js create mode 100644 dist/src/uploadButton/client/styles.css create mode 100644 dist/src/uploadButton/defaults.d.ts create mode 100644 dist/src/uploadButton/defaults.js create mode 100644 dist/src/uploadButton/defaults.js.map create mode 100644 dist/src/uploadButton/index.d.ts create mode 100644 dist/src/uploadButton/index.js create mode 100644 dist/src/uploadButton/index.js.map create mode 100644 dist/src/uploadButton/plugin.d.ts create mode 100644 dist/src/uploadButton/plugin.js create mode 100644 dist/src/uploadButton/plugin.js.map create mode 100644 dist/src/uploadButton/types.d.ts create mode 100644 dist/src/uploadButton/types.js create mode 100644 dist/src/uploadButton/types.js.map create mode 100644 dist/src/uploadButton/utils.d.ts create mode 100644 dist/src/uploadButton/utils.js create mode 100644 dist/src/uploadButton/utils.js.map create mode 100644 eslint.config.js create mode 100644 package-lock.json create mode 100644 src/constants.ts create mode 100644 src/emojiButton/client/emoji.css create mode 100644 src/emojiButton/client/emoji.js create mode 100644 src/emojiButton/index.ts create mode 100644 src/emojiButton/plugin.ts create mode 100644 src/index.ts create mode 100644 src/postToMastodon/client/script.js create mode 100644 src/postToMastodon/index.ts create mode 100644 src/postToMastodon/plugin.ts create mode 100644 src/uploadButton/client/script.js create mode 100644 src/uploadButton/client/styles.css create mode 100644 src/uploadButton/defaults.ts create mode 100644 src/uploadButton/index.ts create mode 100644 src/uploadButton/plugin.ts create mode 100644 src/uploadButton/types.ts create mode 100644 src/uploadButton/utils.ts create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig index 025dd8c..c8c9992 100644 --- a/.editorconfig +++ b/.editorconfig @@ -1,8 +1,19 @@ +# EditorConfig is awesome: https://editorconfig.org + root = true [*] charset = utf-8 -end_of_line = lf -indent_size = 2 -indent_style = space +end_of_line = lf +indent_size = tab +indent_style = tab insert_final_newline = true +trim_trailing_whitespace = true + +[*.json] +indent_size = 2 +indent_style = spaces + +[*.md] +indent_style = tab +trim_trailing_whitespace = false diff --git a/.gitignore b/.gitignore index f03eaec..6f91717 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,49 @@ -.yarn/* -!.yarn/patches -!.yarn/plugins -!.yarn/releases -!.yarn/sdks -!.yarn/versions +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* -# Whether you use PnP or not, the node_modules folder is often used to store -# build artifacts that should be gitignored -node_modules +# Runtime data +pids +*.pid +*.seed +*.pid.lock -# Swap the comments on the following lines if you wish to use zero-installs -# In that case, don't forget to run `yarn config set enableGlobalCache false`! -# Documentation here: https://yarnpkg.com/features/caching#zero-installs +# node-waf configuration +.lock-wscript -#!.yarn/cache -.pnp.* +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn setups files +.yarn +.yarn-integrity + +# dotenv environment variables file +.env + +# parcel-bundler cache (https://parceljs.org/) +.cache + +# twtkpr data file directory +.data + +TODO.md diff --git a/.prettierrc.json b/.prettierrc.json new file mode 100644 index 0000000..ec4313b --- /dev/null +++ b/.prettierrc.json @@ -0,0 +1,11 @@ +{ + "printWidth": 80, + "semi": true, + "singleQuote": true, + "trailingComma": "es5", + "bracketSpacing": true, + "arrowParens": "always", + "endOfLine": "lf", + "embeddedLanguageFormatting": "auto", + "quoteProps": "as-needed" +} diff --git a/.yarnrc.yml b/.yarnrc.yml new file mode 100644 index 0000000..a88a1ab --- /dev/null +++ b/.yarnrc.yml @@ -0,0 +1,3 @@ +nodeLinker: node-modules +#enableImmutableInstalls: true +npmMinimalAgeGate: 7d diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..e0503f5 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2026 Eric Woodward [https://www.itsericwoodward.com] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md index 47c37e3..98b6bfb 100644 --- a/README.md +++ b/README.md @@ -1 +1,186 @@ -# express-twtkpr-upload-button +# express-twtkpr-core-plugins + +> [!WARNING] +> **STILL IN ALPHA**: Although this is a fully-functional set of plugins which are actively deployed to at least one +> site (my own), it currently lacks documentation, examples, tests, installation flexibility, or polish (and still has +> a couple of bugs that need to be fixed). +> _USE AT YOUR OWN RISK_ + +A collection of 3 recommended plugins to expand the functionality of your `express-twtkpr` installation. + +These plugins include: + +- [`emojiButton`](#emojibutton): Adds a simple button to the textarea which appends an emoji to your twt. +- [`postToMastodon`](#posttomastodon): Enables automatic posting to your Mastodon account. +- [`uploadButton`](#uploadbutton): Adds support for drag-and-drop and button-driven file uploads, with optional + automatic hashing, renaming, metadata stripping, and resizing of images. + +``` +import express, { Request, Response } from "express"; + +import twtkpr from "express-twtkpr"; +import { + emojiButton, + postToMastodon, + uploadButton, +} from "express-twtkpr-core-plugins"; + +// import other middleware + +const app = express(); + +// add other middleware + +app.use( + "/", + twtkpr( + { + // config options + }, + [emojiButton, postToMastodon, uploadButton], + ), +); + +// add error handler + +export default app; + +``` + +## emojiButton + +Adds a simple button to the textarea which appends an emoji to your twt. + +- Uses [jwz's](https://www.jwz.org/) [emoji.js](https://www.dnalounge.com/webcast/emoji.js) and [emoji.css](https://www.dnalounge.com/webcast/emoji.css) files to generate the button. +- Keeps track of recently used emoji. +- Includes support for a _massive list_ of emojis. + +### Usage + +``` +import express, { Request, Response } from "express"; + +import twtkpr from "express-twtkpr"; +import { + emojiButton, + postToMastodon, + uploadButton, +} from "express-twtkpr-core-plugins"; + +// import other middleware + +const app = express(); + +// add other middleware + +app.use( + "/", + twtkpr( + { + // config options + }, + [emojiButton], + ), +); + +// add error handler + +export default app; + +``` + +## postToMastodon + +Enables automatic posting to your Mastodon account. + +- Follows principle of POSSE (Publish Own Site, Syndicate Elsewhere) + +### Usage + +For it to work, you _MUST_ include both of the following values: + +- `application_token`: On your Mastodon client, go to "Preferences", then "Development". Create a + new application, then look for the value "Your access token". +- `server_url`: The root URL for your Mastodon server (ex: "https://toot.cafe") + +The preferred way to include them _WILL BE_ via ENV variables (once the work is complete). + +``` +import express, { Request, Response } from "express"; + +import twtkpr from "express-twtkpr"; +import { + emojiButton, + postToMastodon, + uploadButton, +} from "express-twtkpr-core-plugins"; + +// import other middleware + +const app = express(); + +// add other middleware + +app.use( + "/", + twtkpr( + { + plugins: { + postToMastodon: { + application_token: "", // or via ENV variable TWTKPR_PLUGIN_PTM_APP_TOKEN + server_url: "", // or via ENV variable TWTKPR_PLUGIN_PTM_APP_TOKEN + }, + }, + // other config options + }, + [postToMastodon], + ), +); + +// add error handler + +export default app; + +``` + +## uploadButton + +Adds support for drag-and-drop and button-driven file uploads, with optional automatic hashing, +renaming, metadata stripping, and resizing of images. + +``` +import express, { Request, Response } from "express"; + +import twtkpr from "express-twtkpr"; +import { + emojiButton, + postToMastodon, + uploadButton, +} from "express-twtkpr-core-plugins"; + +// import other middleware + +const app = express(); + +// add other middleware + +app.use( + "/", + twtkpr( + { + // config options + }, + [uploadButton], + ), +); + +// add error handler + +export default app; + +``` + +## License + +Copyright (c) 2026 Eric Woodward, released under the +[MIT License](https://www.itsericwoodward.com/licenses/mit/). diff --git a/dist/package.json b/dist/package.json new file mode 100644 index 0000000..faede1a --- /dev/null +++ b/dist/package.json @@ -0,0 +1,43 @@ +{ + "name": "express-twtkpr-core-plugins", + "version": "0.9.0", + "packageManager": "yarn@4.14.1", + "type": "module", + "main": "./dist/src/index.js", + "module": "./dist/src/index.js", + "types": "./dist/src/index.d.ts", + "exports": { + ".": { + "import": "./dist/src/index.js" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsc && rsync -avm --include '*/' --include '*/client/*.*' --exclude '*' src/ dist/src", + "lint": "eslint --fix src test", + "prepublishOnly": "yarn build", + "test": "vitest", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "debug": "^4.4.3", + "express": "^5.2.1", + "express-twtkpr": "^0.9.0", + "formidable": "^3.5.4", + "sharp": "^0.34.5" + }, + "devDependencies": { + "@types/debug": "^4.1.13", + "@types/express": "^5.0.6", + "@types/formidable": "^3.5.1", + "eslint": "^10.3.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.5", + "eslint-plugin-security": "^4.0.0", + "prettier": "^3.8.3", + "typescript": "^6.0.3", + "vitest": "^4.1.5" + } +} diff --git a/dist/src/constants.d.ts b/dist/src/constants.d.ts new file mode 100644 index 0000000..90ef16e --- /dev/null +++ b/dist/src/constants.d.ts @@ -0,0 +1 @@ +export declare const __dirname: string; diff --git a/dist/src/constants.js b/dist/src/constants.js new file mode 100644 index 0000000..223ffb2 --- /dev/null +++ b/dist/src/constants.js @@ -0,0 +1,4 @@ +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; +export const __dirname = resolve(dirname(fileURLToPath(import.meta.url)), '..'); +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/src/constants.js.map b/dist/src/constants.js.map new file mode 100644 index 0000000..a9f2ca8 --- /dev/null +++ b/dist/src/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,CAAC,MAAM,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/src/emojiButton/client/emoji.css b/dist/src/emojiButton/client/emoji.css new file mode 100644 index 0000000..0153896 --- /dev/null +++ b/dist/src/emojiButton/client/emoji.css @@ -0,0 +1,114 @@ +/* Copyright ยฉ 2020 Jamie Zawinski + + Permission to use, copy, modify, distribute, and sell this software + and its documentation for any purpose is hereby granted without + fee, provided that the above copyright notice appear in all copies + and that both that copyright notice and this permission notice + appear in supporting documentation. No representations are made + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + Emoji popup menu. There are many like it. This one is mine. + + Created: 24-May-2020 +*/ + +#emoji_blocker { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: none; + z-index: 1000; +} + +.emoji_menu { + position: fixed; + display: inline-block; + border: 1px solid; + width: 22em; + text-align: center; + z-index: 1001; + background: #000; +} + +.emoji_tab_bar { + display: block; + text-align: center; +} + +.emoji_tab { + display: inline-block; + text-align: center; + width: 1.8em; + height: 1.3em; + padding: 0px 2px 8px 2px; + cursor: pointer; +} + +.emoji_tab.selected { + background: #040; +} + +.emoji_page_box { + height: 16em; + overflow-y: auto; + background: #040; +} + +.emoji_page { + display: none; + text-align: center; + width: 100%; +} + +.emoji_page > b { + display: block; + font-size: smaller; + margin: 4px; +} + +.emoji_square { + display: inline-block; + text-align: center; + width: 1.3em; + height: 1.3em; + margin: 2px; + cursor: pointer; +} + +.emoji_button { + display: inline-block; + font-size: smaller; + padding: 0 4px 0 8px; + cursor: pointer; +} + +/* Light modifications by Eric Woodward */ + +.emoji_button { + position: absolute; + right: 0.5rem; + bottom: 0.5rem; +} + +.emoji_menu { + background: rgb(10, 10, 20, 0.6); +} + +.emoji_tab.selected { + background: rgb(27, 27, 39); +} + +.emoji_page_box { + background: rgb(27, 27, 39); +} + +.twtControls-contentInput { + padding-bottom: 2rem; +} + +.twtControls-contentLabel { + position: relative; +} diff --git a/dist/src/emojiButton/client/emoji.js b/dist/src/emojiButton/client/emoji.js new file mode 100644 index 0000000..14642b0 --- /dev/null +++ b/dist/src/emojiButton/client/emoji.js @@ -0,0 +1,2160 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT +/* Copyright ยฉ 2020-2024 Jamie Zawinski + + Permission to use, copy, modify, distribute, and sell this software + and its documentation for any purpose is hereby granted without + fee, provided that the above copyright notice appear in all copies + and that both that copyright notice and this permission notice + appear in supporting documentation. No representations are made + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + Emoji popup menu. There are many like it. This one is mine. + + I would have just used one of the dozens that alread exist, but the + way people write Javascript modules and their dependencies today is + INSANE and I will have no part of it. + + To use it: + + - Add the class "emoji_target" to one or more INPUT or TEXTAREA fields. + + - Load "emoji.js" and "emoji.css". + + - It will add a smiley at the right of each of those fields, which, + when clicked, will pop up a tabbed dialog box. The selected emoji + will be inserted. + + - The "Recently Used" set is stored in LocalStorage. + + To update it with the new hotness from the latest Unicode drop: + https://www.dnalounge.com/webcast/emoji-build.pl + + Created: 24-May-2020 + Updated: 10-Jun-2024 + */ + +(function () { + var emoji_categories = [ + { name: 'recent', icon: '๐Ÿ•’', label: 'Recently Used' }, + { name: 'smilies', icon: '๐Ÿ˜€', label: 'Smileys & Emotion' }, + { name: 'people', icon: '๐Ÿง‘', label: 'People & Body' }, + { name: 'nature', icon: '๐Ÿฑ', label: 'Animals & Nature' }, + { name: 'food', icon: '๐Ÿ•', label: 'Food & Drink' }, + { name: 'activity', icon: '๐ŸŽณ', label: 'Activities' }, + { name: 'travel', icon: '๐ŸŒŽ', label: 'Travel & Places' }, + { name: 'object', icon: '๐Ÿ“€', label: 'Objects' }, + { name: 'symbol', icon: 'โš ๏ธ', label: 'Symbols' }, + { name: 'flag', icon: '๐Ÿณ๏ธโ€๐ŸŒˆ', label: 'Flags' }, + ]; + + var emoji = { + smilies: [ + '๐Ÿ˜€', + '๐Ÿ˜ƒ', + '๐Ÿ˜„', + '๐Ÿ˜', + '๐Ÿ˜†', + '๐Ÿ˜…', + '๐Ÿคฃ', + '๐Ÿ˜‚', + '๐Ÿ™‚', + '๐Ÿ™ƒ', + '๐Ÿซ ', + '๐Ÿ˜‰', + '๐Ÿ˜Š', + '๐Ÿ˜‡', + '๐Ÿฅฐ', + '๐Ÿ˜', + '๐Ÿคฉ', + '๐Ÿ˜˜', + '๐Ÿ˜—', + 'โ˜บ๏ธ', + '๐Ÿ˜š', + '๐Ÿ˜™', + '๐Ÿฅฒ', + '๐Ÿ˜‹', + '๐Ÿ˜›', + '๐Ÿ˜œ', + '๐Ÿคช', + '๐Ÿ˜', + '๐Ÿค‘', + '๐Ÿค—', + '๐Ÿคญ', + '๐Ÿซข', + '๐Ÿซฃ', + '๐Ÿคซ', + '๐Ÿค”', + '๐Ÿซก', + '๐Ÿค', + '๐Ÿคจ', + '๐Ÿ˜', + '๐Ÿ˜‘', + '๐Ÿ˜ถ', + '๐Ÿซฅ', + '๐Ÿ˜ถโ€๐ŸŒซ๏ธ', + '๐Ÿ˜', + '๐Ÿ˜’', + '๐Ÿ™„', + '๐Ÿ˜ฌ', + '๐Ÿ˜ฎโ€๐Ÿ’จ', + '๐Ÿคฅ', + '๐Ÿซจ', + '๐Ÿ™‚โ€โ†”๏ธ', + '๐Ÿ™‚โ€โ†•๏ธ', + '๐Ÿ˜Œ', + '๐Ÿ˜”', + '๐Ÿ˜ช', + '๐Ÿคค', + '๐Ÿ˜ด', + '๐Ÿ˜ท', + '๐Ÿค’', + '๐Ÿค•', + '๐Ÿคข', + '๐Ÿคฎ', + '๐Ÿคง', + '๐Ÿฅต', + '๐Ÿฅถ', + '๐Ÿฅด', + '๐Ÿ˜ต', + '๐Ÿ˜ตโ€๐Ÿ’ซ', + '๐Ÿคฏ', + '๐Ÿค ', + '๐Ÿฅณ', + '๐Ÿฅธ', + '๐Ÿ˜Ž', + '๐Ÿค“', + '๐Ÿง', + '๐Ÿ˜•', + '๐Ÿซค', + '๐Ÿ˜Ÿ', + '๐Ÿ™', + 'โ˜น๏ธ', + '๐Ÿ˜ฎ', + '๐Ÿ˜ฏ', + '๐Ÿ˜ฒ', + '๐Ÿ˜ณ', + '๐Ÿฅบ', + '๐Ÿฅน', + '๐Ÿ˜ฆ', + '๐Ÿ˜ง', + '๐Ÿ˜จ', + '๐Ÿ˜ฐ', + '๐Ÿ˜ฅ', + '๐Ÿ˜ข', + '๐Ÿ˜ญ', + '๐Ÿ˜ฑ', + '๐Ÿ˜–', + '๐Ÿ˜ฃ', + '๐Ÿ˜ž', + '๐Ÿ˜“', + '๐Ÿ˜ฉ', + '๐Ÿ˜ซ', + '๐Ÿฅฑ', + '๐Ÿ˜ค', + '๐Ÿ˜ก', + '๐Ÿ˜ ', + '๐Ÿคฌ', + '๐Ÿ˜ˆ', + '๐Ÿ‘ฟ', + '๐Ÿ’€', + 'โ˜ ๏ธ', + '๐Ÿ’ฉ', + '๐Ÿคก', + '๐Ÿ‘น', + '๐Ÿ‘บ', + '๐Ÿ‘ป', + '๐Ÿ‘ฝ', + '๐Ÿ‘พ', + '๐Ÿค–', + '๐Ÿ˜บ', + '๐Ÿ˜ธ', + '๐Ÿ˜น', + '๐Ÿ˜ป', + '๐Ÿ˜ผ', + '๐Ÿ˜ฝ', + '๐Ÿ™€', + '๐Ÿ˜ฟ', + '๐Ÿ˜พ', + '๐Ÿ™ˆ', + '๐Ÿ™‰', + '๐Ÿ™Š', + '๐Ÿ’Œ', + '๐Ÿ’˜', + '๐Ÿ’', + '๐Ÿ’–', + '๐Ÿ’—', + '๐Ÿ’“', + '๐Ÿ’ž', + '๐Ÿ’•', + '๐Ÿ’Ÿ', + 'โฃ๏ธ', + '๐Ÿ’”', + 'โค๏ธโ€๐Ÿ”ฅ', + 'โค๏ธโ€๐Ÿฉน', + 'โค๏ธ', + '๐Ÿฉท', + '๐Ÿงก', + '๐Ÿ’›', + '๐Ÿ’š', + '๐Ÿ’™', + '๐Ÿฉต', + '๐Ÿ’œ', + '๐ŸคŽ', + '๐Ÿ–ค', + '๐Ÿฉถ', + '๐Ÿค', + '๐Ÿ’‹', + '๐Ÿ’ฏ', + '๐Ÿ’ข', + '๐Ÿ’ฅ', + '๐Ÿ’ซ', + '๐Ÿ’ฆ', + '๐Ÿ’จ', + '๐Ÿ•ณ๏ธ', + '๐Ÿ’ฌ', + '๐Ÿ‘๏ธโ€๐Ÿ—จ๏ธ', + '๐Ÿ—จ๏ธ', + '๐Ÿ—ฏ๏ธ', + '๐Ÿ’ญ', + '๐Ÿ’ค', + ], + people: [ + '๐Ÿ‘‹', + '๐Ÿคš', + '๐Ÿ–๏ธ', + 'โœ‹', + '๐Ÿ––', + '๐Ÿซฑ', + '๐Ÿซฒ', + '๐Ÿซณ', + '๐Ÿซด', + '๐Ÿซท', + '๐Ÿซธ', + '๐Ÿ‘Œ', + '๐ŸคŒ', + '๐Ÿค', + 'โœŒ๏ธ', + '๐Ÿคž', + '๐Ÿซฐ', + '๐ŸคŸ', + '๐Ÿค˜', + '๐Ÿค™', + '๐Ÿ‘ˆ', + '๐Ÿ‘‰', + '๐Ÿ‘†', + '๐Ÿ–•', + '๐Ÿ‘‡', + 'โ˜๏ธ', + '๐Ÿซต', + '๐Ÿ‘', + '๐Ÿ‘Ž', + 'โœŠ', + '๐Ÿ‘Š', + '๐Ÿค›', + '๐Ÿคœ', + '๐Ÿ‘', + '๐Ÿ™Œ', + '๐Ÿซถ', + '๐Ÿ‘', + '๐Ÿคฒ', + '๐Ÿค', + '๐Ÿ™', + 'โœ๏ธ', + '๐Ÿ’…', + '๐Ÿคณ', + '๐Ÿ’ช', + '๐Ÿฆพ', + '๐Ÿฆฟ', + '๐Ÿฆต', + '๐Ÿฆถ', + '๐Ÿ‘‚', + '๐Ÿฆป', + '๐Ÿ‘ƒ', + '๐Ÿง ', + '๐Ÿซ€', + '๐Ÿซ', + '๐Ÿฆท', + '๐Ÿฆด', + '๐Ÿ‘€', + '๐Ÿ‘๏ธ', + '๐Ÿ‘…', + '๐Ÿ‘„', + '๐Ÿซฆ', + '๐Ÿ‘ถ', + '๐Ÿง’', + '๐Ÿ‘ฆ', + '๐Ÿ‘ง', + '๐Ÿง‘', + '๐Ÿ‘ฑ', + '๐Ÿ‘จ', + '๐Ÿง”', + '๐Ÿง”โ€โ™‚๏ธ', + '๐Ÿง”โ€โ™€๏ธ', + '๐Ÿ‘จโ€๐Ÿฆฐ', + '๐Ÿ‘จโ€๐Ÿฆฑ', + '๐Ÿ‘จโ€๐Ÿฆณ', + '๐Ÿ‘จโ€๐Ÿฆฒ', + '๐Ÿ‘ฉ', + '๐Ÿ‘ฉโ€๐Ÿฆฐ', + '๐Ÿง‘โ€๐Ÿฆฐ', + '๐Ÿ‘ฉโ€๐Ÿฆฑ', + '๐Ÿง‘โ€๐Ÿฆฑ', + '๐Ÿ‘ฉโ€๐Ÿฆณ', + '๐Ÿง‘โ€๐Ÿฆณ', + '๐Ÿ‘ฉโ€๐Ÿฆฒ', + '๐Ÿง‘โ€๐Ÿฆฒ', + '๐Ÿ‘ฑโ€โ™€๏ธ', + '๐Ÿ‘ฑโ€โ™‚๏ธ', + '๐Ÿง“', + '๐Ÿ‘ด', + '๐Ÿ‘ต', + '๐Ÿ™', + '๐Ÿ™โ€โ™‚๏ธ', + '๐Ÿ™โ€โ™€๏ธ', + '๐Ÿ™Ž', + '๐Ÿ™Žโ€โ™‚๏ธ', + '๐Ÿ™Žโ€โ™€๏ธ', + '๐Ÿ™…', + '๐Ÿ™…โ€โ™‚๏ธ', + '๐Ÿ™…โ€โ™€๏ธ', + '๐Ÿ™†', + '๐Ÿ™†โ€โ™‚๏ธ', + '๐Ÿ™†โ€โ™€๏ธ', + '๐Ÿ’', + '๐Ÿ’โ€โ™‚๏ธ', + '๐Ÿ’โ€โ™€๏ธ', + '๐Ÿ™‹', + '๐Ÿ™‹โ€โ™‚๏ธ', + '๐Ÿ™‹โ€โ™€๏ธ', + '๐Ÿง', + '๐Ÿงโ€โ™‚๏ธ', + '๐Ÿงโ€โ™€๏ธ', + '๐Ÿ™‡', + '๐Ÿ™‡โ€โ™‚๏ธ', + '๐Ÿ™‡โ€โ™€๏ธ', + '๐Ÿคฆ', + '๐Ÿคฆโ€โ™‚๏ธ', + '๐Ÿคฆโ€โ™€๏ธ', + '๐Ÿคท', + '๐Ÿคทโ€โ™‚๏ธ', + '๐Ÿคทโ€โ™€๏ธ', + '๐Ÿง‘โ€โš•๏ธ', + '๐Ÿ‘จโ€โš•๏ธ', + '๐Ÿ‘ฉโ€โš•๏ธ', + '๐Ÿง‘โ€๐ŸŽ“', + '๐Ÿ‘จโ€๐ŸŽ“', + '๐Ÿ‘ฉโ€๐ŸŽ“', + '๐Ÿง‘โ€๐Ÿซ', + '๐Ÿ‘จโ€๐Ÿซ', + '๐Ÿ‘ฉโ€๐Ÿซ', + '๐Ÿง‘โ€โš–๏ธ', + '๐Ÿ‘จโ€โš–๏ธ', + '๐Ÿ‘ฉโ€โš–๏ธ', + '๐Ÿง‘โ€๐ŸŒพ', + '๐Ÿ‘จโ€๐ŸŒพ', + '๐Ÿ‘ฉโ€๐ŸŒพ', + '๐Ÿง‘โ€๐Ÿณ', + '๐Ÿ‘จโ€๐Ÿณ', + '๐Ÿ‘ฉโ€๐Ÿณ', + '๐Ÿง‘โ€๐Ÿ”ง', + '๐Ÿ‘จโ€๐Ÿ”ง', + '๐Ÿ‘ฉโ€๐Ÿ”ง', + '๐Ÿง‘โ€๐Ÿญ', + '๐Ÿ‘จโ€๐Ÿญ', + '๐Ÿ‘ฉโ€๐Ÿญ', + '๐Ÿง‘โ€๐Ÿ’ผ', + '๐Ÿ‘จโ€๐Ÿ’ผ', + '๐Ÿ‘ฉโ€๐Ÿ’ผ', + '๐Ÿง‘โ€๐Ÿ”ฌ', + '๐Ÿ‘จโ€๐Ÿ”ฌ', + '๐Ÿ‘ฉโ€๐Ÿ”ฌ', + '๐Ÿง‘โ€๐Ÿ’ป', + '๐Ÿ‘จโ€๐Ÿ’ป', + '๐Ÿ‘ฉโ€๐Ÿ’ป', + '๐Ÿง‘โ€๐ŸŽค', + '๐Ÿ‘จโ€๐ŸŽค', + '๐Ÿ‘ฉโ€๐ŸŽค', + '๐Ÿง‘โ€๐ŸŽจ', + '๐Ÿ‘จโ€๐ŸŽจ', + '๐Ÿ‘ฉโ€๐ŸŽจ', + '๐Ÿง‘โ€โœˆ๏ธ', + '๐Ÿ‘จโ€โœˆ๏ธ', + '๐Ÿ‘ฉโ€โœˆ๏ธ', + '๐Ÿง‘โ€๐Ÿš€', + '๐Ÿ‘จโ€๐Ÿš€', + '๐Ÿ‘ฉโ€๐Ÿš€', + '๐Ÿง‘โ€๐Ÿš’', + '๐Ÿ‘จโ€๐Ÿš’', + '๐Ÿ‘ฉโ€๐Ÿš’', + '๐Ÿ‘ฎ', + '๐Ÿ‘ฎโ€โ™‚๏ธ', + '๐Ÿ‘ฎโ€โ™€๏ธ', + '๐Ÿ•ต๏ธ', + '๐Ÿ•ต๏ธโ€โ™‚๏ธ', + '๐Ÿ•ต๏ธโ€โ™€๏ธ', + '๐Ÿ’‚', + '๐Ÿ’‚โ€โ™‚๏ธ', + '๐Ÿ’‚โ€โ™€๏ธ', + '๐Ÿฅท', + '๐Ÿ‘ท', + '๐Ÿ‘ทโ€โ™‚๏ธ', + '๐Ÿ‘ทโ€โ™€๏ธ', + '๐Ÿซ…', + '๐Ÿคด', + '๐Ÿ‘ธ', + '๐Ÿ‘ณ', + '๐Ÿ‘ณโ€โ™‚๏ธ', + '๐Ÿ‘ณโ€โ™€๏ธ', + '๐Ÿ‘ฒ', + '๐Ÿง•', + '๐Ÿคต', + '๐Ÿคตโ€โ™‚๏ธ', + '๐Ÿคตโ€โ™€๏ธ', + '๐Ÿ‘ฐ', + '๐Ÿ‘ฐโ€โ™‚๏ธ', + '๐Ÿ‘ฐโ€โ™€๏ธ', + '๐Ÿคฐ', + '๐Ÿซƒ', + '๐Ÿซ„', + '๐Ÿคฑ', + '๐Ÿ‘ฉโ€๐Ÿผ', + '๐Ÿ‘จโ€๐Ÿผ', + '๐Ÿง‘โ€๐Ÿผ', + '๐Ÿ‘ผ', + '๐ŸŽ…', + '๐Ÿคถ', + '๐Ÿง‘โ€๐ŸŽ„', + '๐Ÿฆธ', + '๐Ÿฆธโ€โ™‚๏ธ', + '๐Ÿฆธโ€โ™€๏ธ', + '๐Ÿฆน', + '๐Ÿฆนโ€โ™‚๏ธ', + '๐Ÿฆนโ€โ™€๏ธ', + '๐Ÿง™', + '๐Ÿง™โ€โ™‚๏ธ', + '๐Ÿง™โ€โ™€๏ธ', + '๐Ÿงš', + '๐Ÿงšโ€โ™‚๏ธ', + '๐Ÿงšโ€โ™€๏ธ', + '๐Ÿง›', + '๐Ÿง›โ€โ™‚๏ธ', + '๐Ÿง›โ€โ™€๏ธ', + '๐Ÿงœ', + '๐Ÿงœโ€โ™‚๏ธ', + '๐Ÿงœโ€โ™€๏ธ', + '๐Ÿง', + '๐Ÿงโ€โ™‚๏ธ', + '๐Ÿงโ€โ™€๏ธ', + '๐Ÿงž', + '๐Ÿงžโ€โ™‚๏ธ', + '๐Ÿงžโ€โ™€๏ธ', + '๐ŸงŸ', + '๐ŸงŸโ€โ™‚๏ธ', + '๐ŸงŸโ€โ™€๏ธ', + '๐ŸงŒ', + '๐Ÿ’†', + '๐Ÿ’†โ€โ™‚๏ธ', + '๐Ÿ’†โ€โ™€๏ธ', + '๐Ÿ’‡', + '๐Ÿ’‡โ€โ™‚๏ธ', + '๐Ÿ’‡โ€โ™€๏ธ', + '๐Ÿšถ', + '๐Ÿšถโ€โ™‚๏ธ', + '๐Ÿšถโ€โ™€๏ธ', + '๐Ÿšถโ€โžก๏ธ', + '๐Ÿšถโ€โ™€๏ธโ€โžก๏ธ', + '๐Ÿšถโ€โ™‚๏ธโ€โžก๏ธ', + '๐Ÿง', + '๐Ÿงโ€โ™‚๏ธ', + '๐Ÿงโ€โ™€๏ธ', + '๐ŸงŽ', + '๐ŸงŽโ€โ™‚๏ธ', + '๐ŸงŽโ€โ™€๏ธ', + '๐ŸงŽโ€โžก๏ธ', + '๐ŸงŽโ€โ™€๏ธโ€โžก๏ธ', + '๐ŸงŽโ€โ™‚๏ธโ€โžก๏ธ', + '๐Ÿง‘โ€๐Ÿฆฏ', + '๐Ÿง‘โ€๐Ÿฆฏโ€โžก๏ธ', + '๐Ÿ‘จโ€๐Ÿฆฏ', + '๐Ÿ‘จโ€๐Ÿฆฏโ€โžก๏ธ', + '๐Ÿ‘ฉโ€๐Ÿฆฏ', + '๐Ÿ‘ฉโ€๐Ÿฆฏโ€โžก๏ธ', + '๐Ÿง‘โ€๐Ÿฆผ', + '๐Ÿง‘โ€๐Ÿฆผโ€โžก๏ธ', + '๐Ÿ‘จโ€๐Ÿฆผ', + '๐Ÿ‘จโ€๐Ÿฆผโ€โžก๏ธ', + '๐Ÿ‘ฉโ€๐Ÿฆผ', + '๐Ÿ‘ฉโ€๐Ÿฆผโ€โžก๏ธ', + '๐Ÿง‘โ€๐Ÿฆฝ', + '๐Ÿง‘โ€๐Ÿฆฝโ€โžก๏ธ', + '๐Ÿ‘จโ€๐Ÿฆฝ', + '๐Ÿ‘จโ€๐Ÿฆฝโ€โžก๏ธ', + '๐Ÿ‘ฉโ€๐Ÿฆฝ', + '๐Ÿ‘ฉโ€๐Ÿฆฝโ€โžก๏ธ', + '๐Ÿƒ', + '๐Ÿƒโ€โ™‚๏ธ', + '๐Ÿƒโ€โ™€๏ธ', + '๐Ÿƒโ€โžก๏ธ', + '๐Ÿƒโ€โ™€๏ธโ€โžก๏ธ', + '๐Ÿƒโ€โ™‚๏ธโ€โžก๏ธ', + '๐Ÿ’ƒ', + '๐Ÿ•บ', + '๐Ÿ•ด๏ธ', + '๐Ÿ‘ฏ', + '๐Ÿ‘ฏโ€โ™‚๏ธ', + '๐Ÿ‘ฏโ€โ™€๏ธ', + '๐Ÿง–', + '๐Ÿง–โ€โ™‚๏ธ', + '๐Ÿง–โ€โ™€๏ธ', + '๐Ÿง—', + '๐Ÿง—โ€โ™‚๏ธ', + '๐Ÿง—โ€โ™€๏ธ', + '๐Ÿคบ', + '๐Ÿ‡', + 'โ›ท๏ธ', + '๐Ÿ‚', + '๐ŸŒ๏ธ', + '๐ŸŒ๏ธโ€โ™‚๏ธ', + '๐ŸŒ๏ธโ€โ™€๏ธ', + '๐Ÿ„', + '๐Ÿ„โ€โ™‚๏ธ', + '๐Ÿ„โ€โ™€๏ธ', + '๐Ÿšฃ', + '๐Ÿšฃโ€โ™‚๏ธ', + '๐Ÿšฃโ€โ™€๏ธ', + '๐ŸŠ', + '๐ŸŠโ€โ™‚๏ธ', + '๐ŸŠโ€โ™€๏ธ', + 'โ›น๏ธ', + 'โ›น๏ธโ€โ™‚๏ธ', + 'โ›น๏ธโ€โ™€๏ธ', + '๐Ÿ‹๏ธ', + '๐Ÿ‹๏ธโ€โ™‚๏ธ', + '๐Ÿ‹๏ธโ€โ™€๏ธ', + '๐Ÿšด', + '๐Ÿšดโ€โ™‚๏ธ', + '๐Ÿšดโ€โ™€๏ธ', + '๐Ÿšต', + '๐Ÿšตโ€โ™‚๏ธ', + '๐Ÿšตโ€โ™€๏ธ', + '๐Ÿคธ', + '๐Ÿคธโ€โ™‚๏ธ', + '๐Ÿคธโ€โ™€๏ธ', + '๐Ÿคผ', + '๐Ÿคผโ€โ™‚๏ธ', + '๐Ÿคผโ€โ™€๏ธ', + '๐Ÿคฝ', + '๐Ÿคฝโ€โ™‚๏ธ', + '๐Ÿคฝโ€โ™€๏ธ', + '๐Ÿคพ', + '๐Ÿคพโ€โ™‚๏ธ', + '๐Ÿคพโ€โ™€๏ธ', + '๐Ÿคน', + '๐Ÿคนโ€โ™‚๏ธ', + '๐Ÿคนโ€โ™€๏ธ', + '๐Ÿง˜', + '๐Ÿง˜โ€โ™‚๏ธ', + '๐Ÿง˜โ€โ™€๏ธ', + '๐Ÿ›€', + '๐Ÿ›Œ', + '๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘', + '๐Ÿ‘ญ', + '๐Ÿ‘ซ', + '๐Ÿ‘ฌ', + '๐Ÿ’', + '๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ', + '๐Ÿ‘จโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ', + '๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘ฉ', + '๐Ÿ’‘', + '๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘จ', + '๐Ÿ‘จโ€โค๏ธโ€๐Ÿ‘จ', + '๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘ฉ', + '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง', + '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', + '๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง', + '๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง', + '๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง', + '๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', + '๐Ÿ‘จโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘ง', + '๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง', + '๐Ÿ‘ฉโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘ง', + '๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', + '๐Ÿ—ฃ๏ธ', + '๐Ÿ‘ค', + '๐Ÿ‘ฅ', + '๐Ÿซ‚', + '๐Ÿ‘ช', + '๐Ÿง‘โ€๐Ÿง‘โ€๐Ÿง’', + '๐Ÿง‘โ€๐Ÿง‘โ€๐Ÿง’โ€๐Ÿง’', + '๐Ÿง‘โ€๐Ÿง’', + '๐Ÿง‘โ€๐Ÿง’โ€๐Ÿง’', + '๐Ÿ‘ฃ', + ], + nature: [ + '๐Ÿต', + '๐Ÿ’', + '๐Ÿฆ', + '๐Ÿฆง', + '๐Ÿถ', + '๐Ÿ•', + '๐Ÿฆฎ', + '๐Ÿ•โ€๐Ÿฆบ', + '๐Ÿฉ', + '๐Ÿบ', + '๐ŸฆŠ', + '๐Ÿฆ', + '๐Ÿฑ', + '๐Ÿˆ', + '๐Ÿˆโ€โฌ›', + '๐Ÿฆ', + '๐Ÿฏ', + '๐Ÿ…', + '๐Ÿ†', + '๐Ÿด', + '๐ŸซŽ', + '๐Ÿซ', + '๐ŸŽ', + '๐Ÿฆ„', + '๐Ÿฆ“', + '๐ŸฆŒ', + '๐Ÿฆฌ', + '๐Ÿฎ', + '๐Ÿ‚', + '๐Ÿƒ', + '๐Ÿ„', + '๐Ÿท', + '๐Ÿ–', + '๐Ÿ—', + '๐Ÿฝ', + '๐Ÿ', + '๐Ÿ‘', + '๐Ÿ', + '๐Ÿช', + '๐Ÿซ', + '๐Ÿฆ™', + '๐Ÿฆ’', + '๐Ÿ˜', + '๐Ÿฆฃ', + '๐Ÿฆ', + '๐Ÿฆ›', + '๐Ÿญ', + '๐Ÿ', + '๐Ÿ€', + '๐Ÿน', + '๐Ÿฐ', + '๐Ÿ‡', + '๐Ÿฟ๏ธ', + '๐Ÿฆซ', + '๐Ÿฆ”', + '๐Ÿฆ‡', + '๐Ÿป', + '๐Ÿปโ€โ„๏ธ', + '๐Ÿจ', + '๐Ÿผ', + '๐Ÿฆฅ', + '๐Ÿฆฆ', + '๐Ÿฆจ', + '๐Ÿฆ˜', + '๐Ÿฆก', + '๐Ÿพ', + '๐Ÿฆƒ', + '๐Ÿ”', + '๐Ÿ“', + '๐Ÿฃ', + '๐Ÿค', + '๐Ÿฅ', + '๐Ÿฆ', + '๐Ÿง', + '๐Ÿ•Š๏ธ', + '๐Ÿฆ…', + '๐Ÿฆ†', + '๐Ÿฆข', + '๐Ÿฆ‰', + '๐Ÿฆค', + '๐Ÿชถ', + '๐Ÿฆฉ', + '๐Ÿฆš', + '๐Ÿฆœ', + '๐Ÿชฝ', + '๐Ÿฆโ€โฌ›', + '๐Ÿชฟ', + '๐Ÿฆโ€๐Ÿ”ฅ', + '๐Ÿธ', + '๐ŸŠ', + '๐Ÿข', + '๐ŸฆŽ', + '๐Ÿ', + '๐Ÿฒ', + '๐Ÿ‰', + '๐Ÿฆ•', + '๐Ÿฆ–', + '๐Ÿณ', + '๐Ÿ‹', + '๐Ÿฌ', + '๐Ÿฆญ', + '๐ŸŸ', + '๐Ÿ ', + '๐Ÿก', + '๐Ÿฆˆ', + '๐Ÿ™', + '๐Ÿš', + '๐Ÿชธ', + '๐Ÿชผ', + '๐ŸŒ', + '๐Ÿฆ‹', + '๐Ÿ›', + '๐Ÿœ', + '๐Ÿ', + '๐Ÿชฒ', + '๐Ÿž', + '๐Ÿฆ—', + '๐Ÿชณ', + '๐Ÿ•ท๏ธ', + '๐Ÿ•ธ๏ธ', + '๐Ÿฆ‚', + '๐ŸฆŸ', + '๐Ÿชฐ', + '๐Ÿชฑ', + '๐Ÿฆ ', + '๐Ÿ’', + '๐ŸŒธ', + '๐Ÿ’ฎ', + '๐Ÿชท', + '๐Ÿต๏ธ', + '๐ŸŒน', + '๐Ÿฅ€', + '๐ŸŒบ', + '๐ŸŒป', + '๐ŸŒผ', + '๐ŸŒท', + '๐Ÿชป', + '๐ŸŒฑ', + '๐Ÿชด', + '๐ŸŒฒ', + '๐ŸŒณ', + '๐ŸŒด', + '๐ŸŒต', + '๐ŸŒพ', + '๐ŸŒฟ', + 'โ˜˜๏ธ', + '๐Ÿ€', + '๐Ÿ', + '๐Ÿ‚', + '๐Ÿƒ', + '๐Ÿชน', + '๐Ÿชบ', + '๐Ÿ„', + ], + food: [ + '๐Ÿ‡', + '๐Ÿˆ', + '๐Ÿ‰', + '๐ŸŠ', + '๐Ÿ‹', + '๐Ÿ‹โ€๐ŸŸฉ', + '๐ŸŒ', + '๐Ÿ', + '๐Ÿฅญ', + '๐ŸŽ', + '๐Ÿ', + '๐Ÿ', + '๐Ÿ‘', + '๐Ÿ’', + '๐Ÿ“', + '๐Ÿซ', + '๐Ÿฅ', + '๐Ÿ…', + '๐Ÿซ’', + '๐Ÿฅฅ', + '๐Ÿฅ‘', + '๐Ÿ†', + '๐Ÿฅ”', + '๐Ÿฅ•', + '๐ŸŒฝ', + '๐ŸŒถ๏ธ', + '๐Ÿซ‘', + '๐Ÿฅ’', + '๐Ÿฅฌ', + '๐Ÿฅฆ', + '๐Ÿง„', + '๐Ÿง…', + '๐Ÿฅœ', + '๐Ÿซ˜', + '๐ŸŒฐ', + '๐Ÿซš', + '๐Ÿซ›', + '๐Ÿ„โ€๐ŸŸซ', + '๐Ÿž', + '๐Ÿฅ', + '๐Ÿฅ–', + '๐Ÿซ“', + '๐Ÿฅจ', + '๐Ÿฅฏ', + '๐Ÿฅž', + '๐Ÿง‡', + '๐Ÿง€', + '๐Ÿ–', + '๐Ÿ—', + '๐Ÿฅฉ', + '๐Ÿฅ“', + '๐Ÿ”', + '๐ŸŸ', + '๐Ÿ•', + '๐ŸŒญ', + '๐Ÿฅช', + '๐ŸŒฎ', + '๐ŸŒฏ', + '๐Ÿซ”', + '๐Ÿฅ™', + '๐Ÿง†', + '๐Ÿฅš', + '๐Ÿณ', + '๐Ÿฅ˜', + '๐Ÿฒ', + '๐Ÿซ•', + '๐Ÿฅฃ', + '๐Ÿฅ—', + '๐Ÿฟ', + '๐Ÿงˆ', + '๐Ÿง‚', + '๐Ÿฅซ', + '๐Ÿฑ', + '๐Ÿ˜', + '๐Ÿ™', + '๐Ÿš', + '๐Ÿ›', + '๐Ÿœ', + '๐Ÿ', + '๐Ÿ ', + '๐Ÿข', + '๐Ÿฃ', + '๐Ÿค', + '๐Ÿฅ', + '๐Ÿฅฎ', + '๐Ÿก', + '๐ŸฅŸ', + '๐Ÿฅ ', + '๐Ÿฅก', + '๐Ÿฆ€', + '๐Ÿฆž', + '๐Ÿฆ', + '๐Ÿฆ‘', + '๐Ÿฆช', + '๐Ÿฆ', + '๐Ÿง', + '๐Ÿจ', + '๐Ÿฉ', + '๐Ÿช', + '๐ŸŽ‚', + '๐Ÿฐ', + '๐Ÿง', + '๐Ÿฅง', + '๐Ÿซ', + '๐Ÿฌ', + '๐Ÿญ', + '๐Ÿฎ', + '๐Ÿฏ', + '๐Ÿผ', + '๐Ÿฅ›', + 'โ˜•', + '๐Ÿซ–', + '๐Ÿต', + '๐Ÿถ', + '๐Ÿพ', + '๐Ÿท', + '๐Ÿธ', + '๐Ÿน', + '๐Ÿบ', + '๐Ÿป', + '๐Ÿฅ‚', + '๐Ÿฅƒ', + '๐Ÿซ—', + '๐Ÿฅค', + '๐Ÿง‹', + '๐Ÿงƒ', + '๐Ÿง‰', + '๐ŸงŠ', + '๐Ÿฅข', + '๐Ÿฝ๏ธ', + '๐Ÿด', + '๐Ÿฅ„', + '๐Ÿ”ช', + '๐Ÿซ™', + '๐Ÿบ', + ], + activity: [ + '๐ŸŽƒ', + '๐ŸŽ„', + '๐ŸŽ†', + '๐ŸŽ‡', + '๐Ÿงจ', + 'โœจ', + '๐ŸŽˆ', + '๐ŸŽ‰', + '๐ŸŽŠ', + '๐ŸŽ‹', + '๐ŸŽ', + '๐ŸŽŽ', + '๐ŸŽ', + '๐ŸŽ', + '๐ŸŽ‘', + '๐Ÿงง', + '๐ŸŽ€', + '๐ŸŽ', + '๐ŸŽ—๏ธ', + '๐ŸŽŸ๏ธ', + '๐ŸŽซ', + '๐ŸŽ–๏ธ', + '๐Ÿ†', + '๐Ÿ…', + '๐Ÿฅ‡', + '๐Ÿฅˆ', + '๐Ÿฅ‰', + 'โšฝ', + 'โšพ', + '๐ŸฅŽ', + '๐Ÿ€', + '๐Ÿ', + '๐Ÿˆ', + '๐Ÿ‰', + '๐ŸŽพ', + '๐Ÿฅ', + '๐ŸŽณ', + '๐Ÿ', + '๐Ÿ‘', + '๐Ÿ’', + '๐Ÿฅ', + '๐Ÿ“', + '๐Ÿธ', + '๐ŸฅŠ', + '๐Ÿฅ‹', + '๐Ÿฅ…', + 'โ›ณ', + 'โ›ธ๏ธ', + '๐ŸŽฃ', + '๐Ÿคฟ', + '๐ŸŽฝ', + '๐ŸŽฟ', + '๐Ÿ›ท', + '๐ŸฅŒ', + '๐ŸŽฏ', + '๐Ÿช€', + '๐Ÿช', + '๐Ÿ”ซ', + '๐ŸŽฑ', + '๐Ÿ”ฎ', + '๐Ÿช„', + '๐ŸŽฎ', + '๐Ÿ•น๏ธ', + '๐ŸŽฐ', + '๐ŸŽฒ', + '๐Ÿงฉ', + '๐Ÿงธ', + '๐Ÿช…', + '๐Ÿชฉ', + '๐Ÿช†', + 'โ™ ๏ธ', + 'โ™ฅ๏ธ', + 'โ™ฆ๏ธ', + 'โ™ฃ๏ธ', + 'โ™Ÿ๏ธ', + '๐Ÿƒ', + '๐Ÿ€„', + '๐ŸŽด', + '๐ŸŽญ', + '๐Ÿ–ผ๏ธ', + '๐ŸŽจ', + '๐Ÿงต', + '๐Ÿชก', + '๐Ÿงถ', + '๐Ÿชข', + ], + travel: [ + '๐ŸŒ', + '๐ŸŒŽ', + '๐ŸŒ', + '๐ŸŒ', + '๐Ÿ—บ๏ธ', + '๐Ÿ—พ', + '๐Ÿงญ', + '๐Ÿ”๏ธ', + 'โ›ฐ๏ธ', + '๐ŸŒ‹', + '๐Ÿ—ป', + '๐Ÿ•๏ธ', + '๐Ÿ–๏ธ', + '๐Ÿœ๏ธ', + '๐Ÿ๏ธ', + '๐Ÿž๏ธ', + '๐ŸŸ๏ธ', + '๐Ÿ›๏ธ', + '๐Ÿ—๏ธ', + '๐Ÿงฑ', + '๐Ÿชจ', + '๐Ÿชต', + '๐Ÿ›–', + '๐Ÿ˜๏ธ', + '๐Ÿš๏ธ', + '๐Ÿ ', + '๐Ÿก', + '๐Ÿข', + '๐Ÿฃ', + '๐Ÿค', + '๐Ÿฅ', + '๐Ÿฆ', + '๐Ÿจ', + '๐Ÿฉ', + '๐Ÿช', + '๐Ÿซ', + '๐Ÿฌ', + '๐Ÿญ', + '๐Ÿฏ', + '๐Ÿฐ', + '๐Ÿ’’', + '๐Ÿ—ผ', + '๐Ÿ—ฝ', + 'โ›ช', + '๐Ÿ•Œ', + '๐Ÿ›•', + '๐Ÿ•', + 'โ›ฉ๏ธ', + '๐Ÿ•‹', + 'โ›ฒ', + 'โ›บ', + '๐ŸŒ', + '๐ŸŒƒ', + '๐Ÿ™๏ธ', + '๐ŸŒ„', + '๐ŸŒ…', + '๐ŸŒ†', + '๐ŸŒ‡', + '๐ŸŒ‰', + 'โ™จ๏ธ', + '๐ŸŽ ', + '๐Ÿ›', + '๐ŸŽก', + '๐ŸŽข', + '๐Ÿ’ˆ', + '๐ŸŽช', + '๐Ÿš‚', + '๐Ÿšƒ', + '๐Ÿš„', + '๐Ÿš…', + '๐Ÿš†', + '๐Ÿš‡', + '๐Ÿšˆ', + '๐Ÿš‰', + '๐ŸšŠ', + '๐Ÿš', + '๐Ÿšž', + '๐Ÿš‹', + '๐ŸšŒ', + '๐Ÿš', + '๐ŸšŽ', + '๐Ÿš', + '๐Ÿš‘', + '๐Ÿš’', + '๐Ÿš“', + '๐Ÿš”', + '๐Ÿš•', + '๐Ÿš–', + '๐Ÿš—', + '๐Ÿš˜', + '๐Ÿš™', + '๐Ÿ›ป', + '๐Ÿšš', + '๐Ÿš›', + '๐Ÿšœ', + '๐ŸŽ๏ธ', + '๐Ÿ๏ธ', + '๐Ÿ›ต', + '๐Ÿฆฝ', + '๐Ÿฆผ', + '๐Ÿ›บ', + '๐Ÿšฒ', + '๐Ÿ›ด', + '๐Ÿ›น', + '๐Ÿ›ผ', + '๐Ÿš', + '๐Ÿ›ฃ๏ธ', + '๐Ÿ›ค๏ธ', + '๐Ÿ›ข๏ธ', + 'โ›ฝ', + '๐Ÿ›ž', + '๐Ÿšจ', + '๐Ÿšฅ', + '๐Ÿšฆ', + '๐Ÿ›‘', + '๐Ÿšง', + 'โš“', + '๐Ÿ›Ÿ', + 'โ›ต', + '๐Ÿ›ถ', + '๐Ÿšค', + '๐Ÿ›ณ๏ธ', + 'โ›ด๏ธ', + '๐Ÿ›ฅ๏ธ', + '๐Ÿšข', + 'โœˆ๏ธ', + '๐Ÿ›ฉ๏ธ', + '๐Ÿ›ซ', + '๐Ÿ›ฌ', + '๐Ÿช‚', + '๐Ÿ’บ', + '๐Ÿš', + '๐ŸšŸ', + '๐Ÿš ', + '๐Ÿšก', + '๐Ÿ›ฐ๏ธ', + '๐Ÿš€', + '๐Ÿ›ธ', + '๐Ÿ›Ž๏ธ', + '๐Ÿงณ', + 'โŒ›', + 'โณ', + 'โŒš', + 'โฐ', + 'โฑ๏ธ', + 'โฒ๏ธ', + '๐Ÿ•ฐ๏ธ', + '๐Ÿ•›', + '๐Ÿ•ง', + '๐Ÿ•', + '๐Ÿ•œ', + '๐Ÿ•‘', + '๐Ÿ•', + '๐Ÿ•’', + '๐Ÿ•ž', + '๐Ÿ•“', + '๐Ÿ•Ÿ', + '๐Ÿ•”', + '๐Ÿ• ', + '๐Ÿ••', + '๐Ÿ•ก', + '๐Ÿ•–', + '๐Ÿ•ข', + '๐Ÿ•—', + '๐Ÿ•ฃ', + '๐Ÿ•˜', + '๐Ÿ•ค', + '๐Ÿ•™', + '๐Ÿ•ฅ', + '๐Ÿ•š', + '๐Ÿ•ฆ', + '๐ŸŒ‘', + '๐ŸŒ’', + '๐ŸŒ“', + '๐ŸŒ”', + '๐ŸŒ•', + '๐ŸŒ–', + '๐ŸŒ—', + '๐ŸŒ˜', + '๐ŸŒ™', + '๐ŸŒš', + '๐ŸŒ›', + '๐ŸŒœ', + '๐ŸŒก๏ธ', + 'โ˜€๏ธ', + '๐ŸŒ', + '๐ŸŒž', + '๐Ÿช', + 'โญ', + '๐ŸŒŸ', + '๐ŸŒ ', + '๐ŸŒŒ', + 'โ˜๏ธ', + 'โ›…', + 'โ›ˆ๏ธ', + '๐ŸŒค๏ธ', + '๐ŸŒฅ๏ธ', + '๐ŸŒฆ๏ธ', + '๐ŸŒง๏ธ', + '๐ŸŒจ๏ธ', + '๐ŸŒฉ๏ธ', + '๐ŸŒช๏ธ', + '๐ŸŒซ๏ธ', + '๐ŸŒฌ๏ธ', + '๐ŸŒ€', + '๐ŸŒˆ', + '๐ŸŒ‚', + 'โ˜‚๏ธ', + 'โ˜”', + 'โ›ฑ๏ธ', + 'โšก', + 'โ„๏ธ', + 'โ˜ƒ๏ธ', + 'โ›„', + 'โ˜„๏ธ', + '๐Ÿ”ฅ', + '๐Ÿ’ง', + '๐ŸŒŠ', + ], + object: [ + '๐Ÿ‘“', + '๐Ÿ•ถ๏ธ', + '๐Ÿฅฝ', + '๐Ÿฅผ', + '๐Ÿฆบ', + '๐Ÿ‘”', + '๐Ÿ‘•', + '๐Ÿ‘–', + '๐Ÿงฃ', + '๐Ÿงค', + '๐Ÿงฅ', + '๐Ÿงฆ', + '๐Ÿ‘—', + '๐Ÿ‘˜', + '๐Ÿฅป', + '๐Ÿฉฑ', + '๐Ÿฉฒ', + '๐Ÿฉณ', + '๐Ÿ‘™', + '๐Ÿ‘š', + '๐Ÿชญ', + '๐Ÿ‘›', + '๐Ÿ‘œ', + '๐Ÿ‘', + '๐Ÿ›๏ธ', + '๐ŸŽ’', + '๐Ÿฉด', + '๐Ÿ‘ž', + '๐Ÿ‘Ÿ', + '๐Ÿฅพ', + '๐Ÿฅฟ', + '๐Ÿ‘ ', + '๐Ÿ‘ก', + '๐Ÿฉฐ', + '๐Ÿ‘ข', + '๐Ÿชฎ', + '๐Ÿ‘‘', + '๐Ÿ‘’', + '๐ŸŽฉ', + '๐ŸŽ“', + '๐Ÿงข', + '๐Ÿช–', + 'โ›‘๏ธ', + '๐Ÿ“ฟ', + '๐Ÿ’„', + '๐Ÿ’', + '๐Ÿ’Ž', + '๐Ÿ”‡', + '๐Ÿ”ˆ', + '๐Ÿ”‰', + '๐Ÿ”Š', + '๐Ÿ“ข', + '๐Ÿ“ฃ', + '๐Ÿ“ฏ', + '๐Ÿ””', + '๐Ÿ”•', + '๐ŸŽผ', + '๐ŸŽต', + '๐ŸŽถ', + '๐ŸŽ™๏ธ', + '๐ŸŽš๏ธ', + '๐ŸŽ›๏ธ', + '๐ŸŽค', + '๐ŸŽง', + '๐Ÿ“ป', + '๐ŸŽท', + '๐Ÿช—', + '๐ŸŽธ', + '๐ŸŽน', + '๐ŸŽบ', + '๐ŸŽป', + '๐Ÿช•', + '๐Ÿฅ', + '๐Ÿช˜', + '๐Ÿช‡', + '๐Ÿชˆ', + '๐Ÿ“ฑ', + '๐Ÿ“ฒ', + 'โ˜Ž๏ธ', + '๐Ÿ“ž', + '๐Ÿ“Ÿ', + '๐Ÿ“ ', + '๐Ÿ”‹', + '๐Ÿชซ', + '๐Ÿ”Œ', + '๐Ÿ’ป', + '๐Ÿ–ฅ๏ธ', + '๐Ÿ–จ๏ธ', + 'โŒจ๏ธ', + '๐Ÿ–ฑ๏ธ', + '๐Ÿ–ฒ๏ธ', + '๐Ÿ’ฝ', + '๐Ÿ’พ', + '๐Ÿ’ฟ', + '๐Ÿ“€', + '๐Ÿงฎ', + '๐ŸŽฅ', + '๐ŸŽž๏ธ', + '๐Ÿ“ฝ๏ธ', + '๐ŸŽฌ', + '๐Ÿ“บ', + '๐Ÿ“ท', + '๐Ÿ“ธ', + '๐Ÿ“น', + '๐Ÿ“ผ', + '๐Ÿ”', + '๐Ÿ”Ž', + '๐Ÿ•ฏ๏ธ', + '๐Ÿ’ก', + '๐Ÿ”ฆ', + '๐Ÿฎ', + '๐Ÿช”', + '๐Ÿ“”', + '๐Ÿ“•', + '๐Ÿ“–', + '๐Ÿ“—', + '๐Ÿ“˜', + '๐Ÿ“™', + '๐Ÿ“š', + '๐Ÿ““', + '๐Ÿ“’', + '๐Ÿ“ƒ', + '๐Ÿ“œ', + '๐Ÿ“„', + '๐Ÿ“ฐ', + '๐Ÿ—ž๏ธ', + '๐Ÿ“‘', + '๐Ÿ”–', + '๐Ÿท๏ธ', + '๐Ÿ’ฐ', + '๐Ÿช™', + '๐Ÿ’ด', + '๐Ÿ’ต', + '๐Ÿ’ถ', + '๐Ÿ’ท', + '๐Ÿ’ธ', + '๐Ÿ’ณ', + '๐Ÿงพ', + '๐Ÿ’น', + 'โœ‰๏ธ', + '๐Ÿ“ง', + '๐Ÿ“จ', + '๐Ÿ“ฉ', + '๐Ÿ“ค', + '๐Ÿ“ฅ', + '๐Ÿ“ฆ', + '๐Ÿ“ซ', + '๐Ÿ“ช', + '๐Ÿ“ฌ', + '๐Ÿ“ญ', + '๐Ÿ“ฎ', + '๐Ÿ—ณ๏ธ', + 'โœ๏ธ', + 'โœ’๏ธ', + '๐Ÿ–‹๏ธ', + '๐Ÿ–Š๏ธ', + '๐Ÿ–Œ๏ธ', + '๐Ÿ–๏ธ', + '๐Ÿ“', + '๐Ÿ’ผ', + '๐Ÿ“', + '๐Ÿ“‚', + '๐Ÿ—‚๏ธ', + '๐Ÿ“…', + '๐Ÿ“†', + '๐Ÿ—’๏ธ', + '๐Ÿ—“๏ธ', + '๐Ÿ“‡', + '๐Ÿ“ˆ', + '๐Ÿ“‰', + '๐Ÿ“Š', + '๐Ÿ“‹', + '๐Ÿ“Œ', + '๐Ÿ“', + '๐Ÿ“Ž', + '๐Ÿ–‡๏ธ', + '๐Ÿ“', + '๐Ÿ“', + 'โœ‚๏ธ', + '๐Ÿ—ƒ๏ธ', + '๐Ÿ—„๏ธ', + '๐Ÿ—‘๏ธ', + '๐Ÿ”’', + '๐Ÿ”“', + '๐Ÿ”', + '๐Ÿ”', + '๐Ÿ”‘', + '๐Ÿ—๏ธ', + '๐Ÿ”จ', + '๐Ÿช“', + 'โ›๏ธ', + 'โš’๏ธ', + '๐Ÿ› ๏ธ', + '๐Ÿ—ก๏ธ', + 'โš”๏ธ', + '๐Ÿ’ฃ', + '๐Ÿชƒ', + '๐Ÿน', + '๐Ÿ›ก๏ธ', + '๐Ÿชš', + '๐Ÿ”ง', + '๐Ÿช›', + '๐Ÿ”ฉ', + 'โš™๏ธ', + '๐Ÿ—œ๏ธ', + 'โš–๏ธ', + '๐Ÿฆฏ', + '๐Ÿ”—', + 'โ›“๏ธโ€๐Ÿ’ฅ', + 'โ›“๏ธ', + '๐Ÿช', + '๐Ÿงฐ', + '๐Ÿงฒ', + '๐Ÿชœ', + 'โš—๏ธ', + '๐Ÿงช', + '๐Ÿงซ', + '๐Ÿงฌ', + '๐Ÿ”ฌ', + '๐Ÿ”ญ', + '๐Ÿ“ก', + '๐Ÿ’‰', + '๐Ÿฉธ', + '๐Ÿ’Š', + '๐Ÿฉน', + '๐Ÿฉผ', + '๐Ÿฉบ', + '๐Ÿฉป', + '๐Ÿšช', + '๐Ÿ›—', + '๐Ÿชž', + '๐ŸชŸ', + '๐Ÿ›๏ธ', + '๐Ÿ›‹๏ธ', + '๐Ÿช‘', + '๐Ÿšฝ', + '๐Ÿช ', + '๐Ÿšฟ', + '๐Ÿ›', + '๐Ÿชค', + '๐Ÿช’', + '๐Ÿงด', + '๐Ÿงท', + '๐Ÿงน', + '๐Ÿงบ', + '๐Ÿงป', + '๐Ÿชฃ', + '๐Ÿงผ', + '๐Ÿซง', + '๐Ÿชฅ', + '๐Ÿงฝ', + '๐Ÿงฏ', + '๐Ÿ›’', + '๐Ÿšฌ', + 'โšฐ๏ธ', + '๐Ÿชฆ', + 'โšฑ๏ธ', + '๐Ÿงฟ', + '๐Ÿชฌ', + '๐Ÿ—ฟ', + '๐Ÿชง', + '๐Ÿชช', + ], + symbol: [ + '๐Ÿง', + '๐Ÿšฎ', + '๐Ÿšฐ', + 'โ™ฟ', + '๐Ÿšน', + '๐Ÿšบ', + '๐Ÿšป', + '๐Ÿšผ', + '๐Ÿšพ', + '๐Ÿ›‚', + '๐Ÿ›ƒ', + '๐Ÿ›„', + '๐Ÿ›…', + 'โš ๏ธ', + '๐Ÿšธ', + 'โ›”', + '๐Ÿšซ', + '๐Ÿšณ', + '๐Ÿšญ', + '๐Ÿšฏ', + '๐Ÿšฑ', + '๐Ÿšท', + '๐Ÿ“ต', + '๐Ÿ”ž', + 'โ˜ข๏ธ', + 'โ˜ฃ๏ธ', + 'โฌ†๏ธ', + 'โ†—๏ธ', + 'โžก๏ธ', + 'โ†˜๏ธ', + 'โฌ‡๏ธ', + 'โ†™๏ธ', + 'โฌ…๏ธ', + 'โ†–๏ธ', + 'โ†•๏ธ', + 'โ†”๏ธ', + 'โ†ฉ๏ธ', + 'โ†ช๏ธ', + 'โคด๏ธ', + 'โคต๏ธ', + '๐Ÿ”ƒ', + '๐Ÿ”„', + '๐Ÿ”™', + '๐Ÿ”š', + '๐Ÿ”›', + '๐Ÿ”œ', + '๐Ÿ”', + '๐Ÿ›', + 'โš›๏ธ', + '๐Ÿ•‰๏ธ', + 'โœก๏ธ', + 'โ˜ธ๏ธ', + 'โ˜ฏ๏ธ', + 'โœ๏ธ', + 'โ˜ฆ๏ธ', + 'โ˜ช๏ธ', + 'โ˜ฎ๏ธ', + '๐Ÿ•Ž', + '๐Ÿ”ฏ', + '๐Ÿชฏ', + 'โ™ˆ', + 'โ™‰', + 'โ™Š', + 'โ™‹', + 'โ™Œ', + 'โ™', + 'โ™Ž', + 'โ™', + 'โ™', + 'โ™‘', + 'โ™’', + 'โ™“', + 'โ›Ž', + '๐Ÿ”€', + '๐Ÿ”', + '๐Ÿ”‚', + 'โ–ถ๏ธ', + 'โฉ', + 'โญ๏ธ', + 'โฏ๏ธ', + 'โ—€๏ธ', + 'โช', + 'โฎ๏ธ', + '๐Ÿ”ผ', + 'โซ', + '๐Ÿ”ฝ', + 'โฌ', + 'โธ๏ธ', + 'โน๏ธ', + 'โบ๏ธ', + 'โ๏ธ', + '๐ŸŽฆ', + '๐Ÿ”…', + '๐Ÿ”†', + '๐Ÿ“ถ', + '๐Ÿ›œ', + '๐Ÿ“ณ', + '๐Ÿ“ด', + 'โšง๏ธ', + 'โœ–๏ธ', + 'โž•', + 'โž–', + 'โž—', + '๐ŸŸฐ', + 'โ™พ๏ธ', + 'โ€ผ๏ธ', + 'โ‰๏ธ', + 'โ“', + 'โ”', + 'โ•', + 'โ—', + 'ใ€ฐ๏ธ', + '๐Ÿ’ฑ', + '๐Ÿ’ฒ', + 'โ™ป๏ธ', + 'โšœ๏ธ', + '๐Ÿ”ฑ', + '๐Ÿ“›', + '๐Ÿ”ฐ', + 'โญ•', + 'โœ…', + 'โ˜‘๏ธ', + 'โœ”๏ธ', + 'โŒ', + 'โŽ', + 'โžฐ', + 'โžฟ', + 'ใ€ฝ๏ธ', + 'โœณ๏ธ', + 'โœด๏ธ', + 'โ‡๏ธ', + 'ยฉ๏ธ', + 'ยฎ๏ธ', + 'โ„ข๏ธ', + '#๏ธโƒฃ', + '*๏ธโƒฃ', + '0๏ธโƒฃ', + '1๏ธโƒฃ', + '2๏ธโƒฃ', + '3๏ธโƒฃ', + '4๏ธโƒฃ', + '5๏ธโƒฃ', + '6๏ธโƒฃ', + '7๏ธโƒฃ', + '8๏ธโƒฃ', + '9๏ธโƒฃ', + '๐Ÿ”Ÿ', + '๐Ÿ” ', + '๐Ÿ”ก', + '๐Ÿ”ข', + '๐Ÿ”ฃ', + '๐Ÿ”ค', + '๐Ÿ…ฐ๏ธ', + '๐Ÿ†Ž', + '๐Ÿ…ฑ๏ธ', + '๐Ÿ†‘', + '๐Ÿ†’', + '๐Ÿ†“', + 'โ„น๏ธ', + '๐Ÿ†”', + 'โ“‚๏ธ', + '๐Ÿ†•', + '๐Ÿ†–', + '๐Ÿ…พ๏ธ', + '๐Ÿ†—', + '๐Ÿ…ฟ๏ธ', + '๐Ÿ†˜', + '๐Ÿ†™', + '๐Ÿ†š', + '๐Ÿˆ', + '๐Ÿˆ‚๏ธ', + '๐Ÿˆท๏ธ', + '๐Ÿˆถ', + '๐Ÿˆฏ', + '๐Ÿ‰', + '๐Ÿˆน', + '๐Ÿˆš', + '๐Ÿˆฒ', + '๐Ÿ‰‘', + '๐Ÿˆธ', + '๐Ÿˆด', + '๐Ÿˆณ', + 'ใŠ—๏ธ', + 'ใŠ™๏ธ', + '๐Ÿˆบ', + '๐Ÿˆต', + '๐Ÿ”ด', + '๐ŸŸ ', + '๐ŸŸก', + '๐ŸŸข', + '๐Ÿ”ต', + '๐ŸŸฃ', + '๐ŸŸค', + 'โšซ', + 'โšช', + '๐ŸŸฅ', + '๐ŸŸง', + '๐ŸŸจ', + '๐ŸŸฉ', + '๐ŸŸฆ', + '๐ŸŸช', + '๐ŸŸซ', + 'โฌ›', + 'โฌœ', + 'โ—ผ๏ธ', + 'โ—ป๏ธ', + 'โ—พ', + 'โ—ฝ', + 'โ–ช๏ธ', + 'โ–ซ๏ธ', + '๐Ÿ”ถ', + '๐Ÿ”ท', + '๐Ÿ”ธ', + '๐Ÿ”น', + '๐Ÿ”บ', + '๐Ÿ”ป', + '๐Ÿ’ ', + '๐Ÿ”˜', + '๐Ÿ”ณ', + '๐Ÿ”ฒ', + ], + flag: [ + '๐Ÿ', + '๐Ÿšฉ', + '๐ŸŽŒ', + '๐Ÿด', + '๐Ÿณ๏ธ', + '๐Ÿณ๏ธโ€๐ŸŒˆ', + '๐Ÿณ๏ธโ€โšง๏ธ', + '๐Ÿดโ€โ˜ ๏ธ', + '๐Ÿ‡ฆ๐Ÿ‡จ', + '๐Ÿ‡ฆ๐Ÿ‡ฉ', + '๐Ÿ‡ฆ๐Ÿ‡ช', + '๐Ÿ‡ฆ๐Ÿ‡ซ', + '๐Ÿ‡ฆ๐Ÿ‡ฌ', + '๐Ÿ‡ฆ๐Ÿ‡ฎ', + '๐Ÿ‡ฆ๐Ÿ‡ฑ', + '๐Ÿ‡ฆ๐Ÿ‡ฒ', + '๐Ÿ‡ฆ๐Ÿ‡ด', + '๐Ÿ‡ฆ๐Ÿ‡ถ', + '๐Ÿ‡ฆ๐Ÿ‡ท', + '๐Ÿ‡ฆ๐Ÿ‡ธ', + '๐Ÿ‡ฆ๐Ÿ‡น', + '๐Ÿ‡ฆ๐Ÿ‡บ', + '๐Ÿ‡ฆ๐Ÿ‡ผ', + '๐Ÿ‡ฆ๐Ÿ‡ฝ', + '๐Ÿ‡ฆ๐Ÿ‡ฟ', + '๐Ÿ‡ง๐Ÿ‡ฆ', + '๐Ÿ‡ง๐Ÿ‡ง', + '๐Ÿ‡ง๐Ÿ‡ฉ', + '๐Ÿ‡ง๐Ÿ‡ช', + '๐Ÿ‡ง๐Ÿ‡ซ', + '๐Ÿ‡ง๐Ÿ‡ฌ', + '๐Ÿ‡ง๐Ÿ‡ญ', + '๐Ÿ‡ง๐Ÿ‡ฎ', + '๐Ÿ‡ง๐Ÿ‡ฏ', + '๐Ÿ‡ง๐Ÿ‡ฑ', + '๐Ÿ‡ง๐Ÿ‡ฒ', + '๐Ÿ‡ง๐Ÿ‡ณ', + '๐Ÿ‡ง๐Ÿ‡ด', + '๐Ÿ‡ง๐Ÿ‡ถ', + '๐Ÿ‡ง๐Ÿ‡ท', + '๐Ÿ‡ง๐Ÿ‡ธ', + '๐Ÿ‡ง๐Ÿ‡น', + '๐Ÿ‡ง๐Ÿ‡ป', + '๐Ÿ‡ง๐Ÿ‡ผ', + '๐Ÿ‡ง๐Ÿ‡พ', + '๐Ÿ‡ง๐Ÿ‡ฟ', + '๐Ÿ‡จ๐Ÿ‡ฆ', + '๐Ÿ‡จ๐Ÿ‡จ', + '๐Ÿ‡จ๐Ÿ‡ฉ', + '๐Ÿ‡จ๐Ÿ‡ซ', + '๐Ÿ‡จ๐Ÿ‡ฌ', + '๐Ÿ‡จ๐Ÿ‡ญ', + '๐Ÿ‡จ๐Ÿ‡ฎ', + '๐Ÿ‡จ๐Ÿ‡ฐ', + '๐Ÿ‡จ๐Ÿ‡ฑ', + '๐Ÿ‡จ๐Ÿ‡ฒ', + '๐Ÿ‡จ๐Ÿ‡ณ', + '๐Ÿ‡จ๐Ÿ‡ด', + '๐Ÿ‡จ๐Ÿ‡ต', + '๐Ÿ‡จ๐Ÿ‡ท', + '๐Ÿ‡จ๐Ÿ‡บ', + '๐Ÿ‡จ๐Ÿ‡ป', + '๐Ÿ‡จ๐Ÿ‡ผ', + '๐Ÿ‡จ๐Ÿ‡ฝ', + '๐Ÿ‡จ๐Ÿ‡พ', + '๐Ÿ‡จ๐Ÿ‡ฟ', + '๐Ÿ‡ฉ๐Ÿ‡ช', + '๐Ÿ‡ฉ๐Ÿ‡ฌ', + '๐Ÿ‡ฉ๐Ÿ‡ฏ', + '๐Ÿ‡ฉ๐Ÿ‡ฐ', + '๐Ÿ‡ฉ๐Ÿ‡ฒ', + '๐Ÿ‡ฉ๐Ÿ‡ด', + '๐Ÿ‡ฉ๐Ÿ‡ฟ', + '๐Ÿ‡ช๐Ÿ‡ฆ', + '๐Ÿ‡ช๐Ÿ‡จ', + '๐Ÿ‡ช๐Ÿ‡ช', + '๐Ÿ‡ช๐Ÿ‡ฌ', + '๐Ÿ‡ช๐Ÿ‡ญ', + '๐Ÿ‡ช๐Ÿ‡ท', + '๐Ÿ‡ช๐Ÿ‡ธ', + '๐Ÿ‡ช๐Ÿ‡น', + '๐Ÿ‡ช๐Ÿ‡บ', + '๐Ÿ‡ซ๐Ÿ‡ฎ', + '๐Ÿ‡ซ๐Ÿ‡ฏ', + '๐Ÿ‡ซ๐Ÿ‡ฐ', + '๐Ÿ‡ซ๐Ÿ‡ฒ', + '๐Ÿ‡ซ๐Ÿ‡ด', + '๐Ÿ‡ซ๐Ÿ‡ท', + '๐Ÿ‡ฌ๐Ÿ‡ฆ', + '๐Ÿ‡ฌ๐Ÿ‡ง', + '๐Ÿ‡ฌ๐Ÿ‡ฉ', + '๐Ÿ‡ฌ๐Ÿ‡ช', + '๐Ÿ‡ฌ๐Ÿ‡ซ', + '๐Ÿ‡ฌ๐Ÿ‡ฌ', + '๐Ÿ‡ฌ๐Ÿ‡ญ', + '๐Ÿ‡ฌ๐Ÿ‡ฎ', + '๐Ÿ‡ฌ๐Ÿ‡ฑ', + '๐Ÿ‡ฌ๐Ÿ‡ฒ', + '๐Ÿ‡ฌ๐Ÿ‡ณ', + '๐Ÿ‡ฌ๐Ÿ‡ต', + '๐Ÿ‡ฌ๐Ÿ‡ถ', + '๐Ÿ‡ฌ๐Ÿ‡ท', + '๐Ÿ‡ฌ๐Ÿ‡ธ', + '๐Ÿ‡ฌ๐Ÿ‡น', + '๐Ÿ‡ฌ๐Ÿ‡บ', + '๐Ÿ‡ฌ๐Ÿ‡ผ', + '๐Ÿ‡ฌ๐Ÿ‡พ', + '๐Ÿ‡ญ๐Ÿ‡ฐ', + '๐Ÿ‡ญ๐Ÿ‡ฒ', + '๐Ÿ‡ญ๐Ÿ‡ณ', + '๐Ÿ‡ญ๐Ÿ‡ท', + '๐Ÿ‡ญ๐Ÿ‡น', + '๐Ÿ‡ญ๐Ÿ‡บ', + '๐Ÿ‡ฎ๐Ÿ‡จ', + '๐Ÿ‡ฎ๐Ÿ‡ฉ', + '๐Ÿ‡ฎ๐Ÿ‡ช', + '๐Ÿ‡ฎ๐Ÿ‡ฑ', + '๐Ÿ‡ฎ๐Ÿ‡ฒ', + '๐Ÿ‡ฎ๐Ÿ‡ณ', + '๐Ÿ‡ฎ๐Ÿ‡ด', + '๐Ÿ‡ฎ๐Ÿ‡ถ', + '๐Ÿ‡ฎ๐Ÿ‡ท', + '๐Ÿ‡ฎ๐Ÿ‡ธ', + '๐Ÿ‡ฎ๐Ÿ‡น', + '๐Ÿ‡ฏ๐Ÿ‡ช', + '๐Ÿ‡ฏ๐Ÿ‡ฒ', + '๐Ÿ‡ฏ๐Ÿ‡ด', + '๐Ÿ‡ฏ๐Ÿ‡ต', + '๐Ÿ‡ฐ๐Ÿ‡ช', + '๐Ÿ‡ฐ๐Ÿ‡ฌ', + '๐Ÿ‡ฐ๐Ÿ‡ญ', + '๐Ÿ‡ฐ๐Ÿ‡ฎ', + '๐Ÿ‡ฐ๐Ÿ‡ฒ', + '๐Ÿ‡ฐ๐Ÿ‡ณ', + '๐Ÿ‡ฐ๐Ÿ‡ต', + '๐Ÿ‡ฐ๐Ÿ‡ท', + '๐Ÿ‡ฐ๐Ÿ‡ผ', + '๐Ÿ‡ฐ๐Ÿ‡พ', + '๐Ÿ‡ฐ๐Ÿ‡ฟ', + '๐Ÿ‡ฑ๐Ÿ‡ฆ', + '๐Ÿ‡ฑ๐Ÿ‡ง', + '๐Ÿ‡ฑ๐Ÿ‡จ', + '๐Ÿ‡ฑ๐Ÿ‡ฎ', + '๐Ÿ‡ฑ๐Ÿ‡ฐ', + '๐Ÿ‡ฑ๐Ÿ‡ท', + '๐Ÿ‡ฑ๐Ÿ‡ธ', + '๐Ÿ‡ฑ๐Ÿ‡น', + '๐Ÿ‡ฑ๐Ÿ‡บ', + '๐Ÿ‡ฑ๐Ÿ‡ป', + '๐Ÿ‡ฑ๐Ÿ‡พ', + '๐Ÿ‡ฒ๐Ÿ‡ฆ', + '๐Ÿ‡ฒ๐Ÿ‡จ', + '๐Ÿ‡ฒ๐Ÿ‡ฉ', + '๐Ÿ‡ฒ๐Ÿ‡ช', + '๐Ÿ‡ฒ๐Ÿ‡ซ', + '๐Ÿ‡ฒ๐Ÿ‡ฌ', + '๐Ÿ‡ฒ๐Ÿ‡ญ', + '๐Ÿ‡ฒ๐Ÿ‡ฐ', + '๐Ÿ‡ฒ๐Ÿ‡ฑ', + '๐Ÿ‡ฒ๐Ÿ‡ฒ', + '๐Ÿ‡ฒ๐Ÿ‡ณ', + '๐Ÿ‡ฒ๐Ÿ‡ด', + '๐Ÿ‡ฒ๐Ÿ‡ต', + '๐Ÿ‡ฒ๐Ÿ‡ถ', + '๐Ÿ‡ฒ๐Ÿ‡ท', + '๐Ÿ‡ฒ๐Ÿ‡ธ', + '๐Ÿ‡ฒ๐Ÿ‡น', + '๐Ÿ‡ฒ๐Ÿ‡บ', + '๐Ÿ‡ฒ๐Ÿ‡ป', + '๐Ÿ‡ฒ๐Ÿ‡ผ', + '๐Ÿ‡ฒ๐Ÿ‡ฝ', + '๐Ÿ‡ฒ๐Ÿ‡พ', + '๐Ÿ‡ฒ๐Ÿ‡ฟ', + '๐Ÿ‡ณ๐Ÿ‡ฆ', + '๐Ÿ‡ณ๐Ÿ‡จ', + '๐Ÿ‡ณ๐Ÿ‡ช', + '๐Ÿ‡ณ๐Ÿ‡ซ', + '๐Ÿ‡ณ๐Ÿ‡ฌ', + '๐Ÿ‡ณ๐Ÿ‡ฎ', + '๐Ÿ‡ณ๐Ÿ‡ฑ', + '๐Ÿ‡ณ๐Ÿ‡ด', + '๐Ÿ‡ณ๐Ÿ‡ต', + '๐Ÿ‡ณ๐Ÿ‡ท', + '๐Ÿ‡ณ๐Ÿ‡บ', + '๐Ÿ‡ณ๐Ÿ‡ฟ', + '๐Ÿ‡ด๐Ÿ‡ฒ', + '๐Ÿ‡ต๐Ÿ‡ฆ', + '๐Ÿ‡ต๐Ÿ‡ช', + '๐Ÿ‡ต๐Ÿ‡ซ', + '๐Ÿ‡ต๐Ÿ‡ฌ', + '๐Ÿ‡ต๐Ÿ‡ญ', + '๐Ÿ‡ต๐Ÿ‡ฐ', + '๐Ÿ‡ต๐Ÿ‡ฑ', + '๐Ÿ‡ต๐Ÿ‡ฒ', + '๐Ÿ‡ต๐Ÿ‡ณ', + '๐Ÿ‡ต๐Ÿ‡ท', + '๐Ÿ‡ต๐Ÿ‡ธ', + '๐Ÿ‡ต๐Ÿ‡น', + '๐Ÿ‡ต๐Ÿ‡ผ', + '๐Ÿ‡ต๐Ÿ‡พ', + '๐Ÿ‡ถ๐Ÿ‡ฆ', + '๐Ÿ‡ท๐Ÿ‡ช', + '๐Ÿ‡ท๐Ÿ‡ด', + '๐Ÿ‡ท๐Ÿ‡ธ', + '๐Ÿ‡ท๐Ÿ‡บ', + '๐Ÿ‡ท๐Ÿ‡ผ', + '๐Ÿ‡ธ๐Ÿ‡ฆ', + '๐Ÿ‡ธ๐Ÿ‡ง', + '๐Ÿ‡ธ๐Ÿ‡จ', + '๐Ÿ‡ธ๐Ÿ‡ฉ', + '๐Ÿ‡ธ๐Ÿ‡ช', + '๐Ÿ‡ธ๐Ÿ‡ฌ', + '๐Ÿ‡ธ๐Ÿ‡ญ', + '๐Ÿ‡ธ๐Ÿ‡ฎ', + '๐Ÿ‡ธ๐Ÿ‡ฏ', + '๐Ÿ‡ธ๐Ÿ‡ฐ', + '๐Ÿ‡ธ๐Ÿ‡ฑ', + '๐Ÿ‡ธ๐Ÿ‡ฒ', + '๐Ÿ‡ธ๐Ÿ‡ณ', + '๐Ÿ‡ธ๐Ÿ‡ด', + '๐Ÿ‡ธ๐Ÿ‡ท', + '๐Ÿ‡ธ๐Ÿ‡ธ', + '๐Ÿ‡ธ๐Ÿ‡น', + '๐Ÿ‡ธ๐Ÿ‡ป', + '๐Ÿ‡ธ๐Ÿ‡ฝ', + '๐Ÿ‡ธ๐Ÿ‡พ', + '๐Ÿ‡ธ๐Ÿ‡ฟ', + '๐Ÿ‡น๐Ÿ‡ฆ', + '๐Ÿ‡น๐Ÿ‡จ', + '๐Ÿ‡น๐Ÿ‡ฉ', + '๐Ÿ‡น๐Ÿ‡ซ', + '๐Ÿ‡น๐Ÿ‡ฌ', + '๐Ÿ‡น๐Ÿ‡ญ', + '๐Ÿ‡น๐Ÿ‡ฏ', + '๐Ÿ‡น๐Ÿ‡ฐ', + '๐Ÿ‡น๐Ÿ‡ฑ', + '๐Ÿ‡น๐Ÿ‡ฒ', + '๐Ÿ‡น๐Ÿ‡ณ', + '๐Ÿ‡น๐Ÿ‡ด', + '๐Ÿ‡น๐Ÿ‡ท', + '๐Ÿ‡น๐Ÿ‡น', + '๐Ÿ‡น๐Ÿ‡ป', + '๐Ÿ‡น๐Ÿ‡ผ', + '๐Ÿ‡น๐Ÿ‡ฟ', + '๐Ÿ‡บ๐Ÿ‡ฆ', + '๐Ÿ‡บ๐Ÿ‡ฌ', + '๐Ÿ‡บ๐Ÿ‡ฒ', + '๐Ÿ‡บ๐Ÿ‡ณ', + '๐Ÿ‡บ๐Ÿ‡ธ', + '๐Ÿ‡บ๐Ÿ‡พ', + '๐Ÿ‡บ๐Ÿ‡ฟ', + '๐Ÿ‡ป๐Ÿ‡ฆ', + '๐Ÿ‡ป๐Ÿ‡จ', + '๐Ÿ‡ป๐Ÿ‡ช', + '๐Ÿ‡ป๐Ÿ‡ฌ', + '๐Ÿ‡ป๐Ÿ‡ฎ', + '๐Ÿ‡ป๐Ÿ‡ณ', + '๐Ÿ‡ป๐Ÿ‡บ', + '๐Ÿ‡ผ๐Ÿ‡ซ', + '๐Ÿ‡ผ๐Ÿ‡ธ', + '๐Ÿ‡ฝ๐Ÿ‡ฐ', + '๐Ÿ‡พ๐Ÿ‡ช', + '๐Ÿ‡พ๐Ÿ‡น', + '๐Ÿ‡ฟ๐Ÿ‡ฆ', + '๐Ÿ‡ฟ๐Ÿ‡ฒ', + '๐Ÿ‡ฟ๐Ÿ‡ผ', + '๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ', + '๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ', + '๐Ÿด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ', + ], + }; + + function emoji_tab_click(event) { + var tab = event.target; + + var pages = document.getElementsByClassName('emoji_page'); + for (var i = 0; i < pages.length; i++) { + pages[i].style.display = 'none'; + } + + var tabs = document.getElementsByClassName('emoji_tab'); + for (var i = 0; i < tabs.length; i++) { + tabs[i].classList.remove('selected'); + } + + var page = document.getElementById(tab.emoji_page); + page.style.display = 'inline-block'; + tab.classList.add('selected'); + } + + function emoji_insert(event) { + var node = event.target; + var blocker = document.getElementById('emoji_blocker'); + blocker.style.display = 'none'; + var e = node.innerText; + emoji_recently_used(e); + var ts = document.getElementsByClassName('emoji_target'); + for (var i = 0; i < ts.length; i++) { + var tt = ts[i]; + if (tt.tagName == 'INPUT' || tt.tagName == 'TEXTAREA') { + tt.focus(); + var start = tt.selectionStart || 0; + var end = tt.selectionEnd || 0; + tt.value = + tt.value.substring(0, start) + + e + + tt.value.substring(end, tt.value.length); + tt.focus(); + tt.selectionStart = start + e.length; + tt.selectionEnd = start + e.length; + } + } + } + + function emoji_menu_dismiss(event) { + if (event.type == 'resize' || event.target.id == 'emoji_blocker') { + var blocker = document.getElementById('emoji_blocker'); + blocker.style.display = 'none'; + } + } + + var emoji_recent = []; + + function emoji_recently_used(e) { + while (true) { + var i = emoji_recent.indexOf(e); + if (i < 0) break; + emoji_recent.splice(i, 1); + } + emoji_recent.unshift(e); + if (emoji_recent.length > 100) emoji_recent = emoji_recent.slice(0, 100); + + var page = document.getElementById('emoji_recent'); + var old = page.getElementsByTagName('a'); + for (var i = old.length - 1; i >= 0; i--) { + old[i].parentNode.removeChild(old[i]); + } + + for (var j = 0; j < emoji_recent.length; j++) { + var a = document.createElement('a'); + a.innerText = emoji_recent[j]; + a.className = 'emoji_square'; + a.onclick = emoji_insert; + page.appendChild(a); + } + + try { + localStorage.setItem('emoji_recent', emoji_recent.join(',')); + } catch (e) {} + } + + function build_emoji_menu() { + try { + emoji_recent = localStorage.getItem('emoji_recent'); + if (emoji_recent) emoji_recent = emoji_recent.split(','); + } catch (e) {} + if (!emoji_recent) emoji_recent = []; + + var menu = document.createElement('div'); + menu.className = 'emoji_menu'; + + var tab_bar = document.createElement('div'); + tab_bar.className = 'emoji_tab_bar'; + menu.appendChild(tab_bar); + + var page_box = document.createElement('div'); + page_box.className = 'emoji_page_box'; + menu.appendChild(page_box); + + var selected_tab = null; + var n = emoji_categories.length; + for (var i = 0; i < n; i++) { + var cat = emoji_categories[i].name; + var label = emoji_categories[i].label; + var icon = emoji_categories[i].icon; + var em = emoji[cat]; + + if (cat == 'recent') em = emoji_recent; + + var m = em ? em.length : 0; + + var tab = document.createElement('div'); + tab.className = 'emoji_tab'; + tab.innerText = icon; + tab.onclick = emoji_tab_click; + tab_bar.appendChild(tab); + + var page = document.createElement('div'); + page.className = 'emoji_page'; + page.id = 'emoji_' + cat; + tab.emoji_page = page.id; + page_box.appendChild(page); + + var head = document.createElement('b'); + head.innerText = label; + page.appendChild(head); + + for (var j = 0; j < m; j++) { + var a = document.createElement('a'); + a.innerText = em[j]; + a.className = 'emoji_square'; + a.onclick = emoji_insert; + page.appendChild(a); + } + + if (!selected_tab && m) selected_tab = tab; + } + + var blocker = document.createElement('div'); + blocker.id = 'emoji_blocker'; + blocker.style.display = 'none'; + blocker.appendChild(menu); + blocker.onclick = emoji_menu_dismiss; + window.addEventListener('resize', emoji_menu_dismiss); + + document.body.appendChild(blocker); + + if (selected_tab) emoji_tab_click({ target: selected_tab }); + } + + function emoji_menu_popup(event) { + var blocker = document.getElementById('emoji_blocker'); + if (!blocker) { + build_emoji_menu(); + blocker = document.getElementById('emoji_blocker'); + } + blocker.style.display = 'block'; + + var rect = event.target.getBoundingClientRect(); + var menu = blocker.getElementsByClassName('emoji_menu')[0]; + var x = rect.x - 8; + var y = rect.y - 8; + var w = menu.offsetWidth; + var h = menu.offsetHeight; + + var maxw = blocker.clientWidth - 8; + var maxh = blocker.clientHeight - 8; + if (x + w >= maxw) x = maxw - w; + if (y + h >= maxh) y = maxh - h; + if (x < 0) x = 0; + if (y < 0) y = 0; + + menu.style.left = x + 'px'; + menu.style.top = y + 'px'; + + return false; + } + + function emoji_init() { + var ts = document.getElementsByClassName('emoji_target'); + for (var i = 0; i < ts.length; i++) { + var tt = ts[i]; + var button = document.createElement('a'); + button.className = 'emoji_button'; + button.innerText = '\u{1F600}'; + button.onclick = emoji_menu_popup; + tt.parentNode.insertBefore(button, tt.nextSibling); + + tt.style.boxSizing = 'border-box'; + tt.style.paddingRight = '1.5em'; + } + } + + emoji_init(); +})(); +// @license-end diff --git a/dist/src/emojiButton/index.d.ts b/dist/src/emojiButton/index.d.ts new file mode 100644 index 0000000..77bfd60 --- /dev/null +++ b/dist/src/emojiButton/index.d.ts @@ -0,0 +1 @@ +export { default } from './plugin.js'; diff --git a/dist/src/emojiButton/index.js b/dist/src/emojiButton/index.js new file mode 100644 index 0000000..7de5de3 --- /dev/null +++ b/dist/src/emojiButton/index.js @@ -0,0 +1,2 @@ +export { default } from './plugin.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/src/emojiButton/index.js.map b/dist/src/emojiButton/index.js.map new file mode 100644 index 0000000..f4a6e0b --- /dev/null +++ b/dist/src/emojiButton/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/emojiButton/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file diff --git a/dist/src/emojiButton/plugin.d.ts b/dist/src/emojiButton/plugin.d.ts new file mode 100644 index 0000000..9777f6f --- /dev/null +++ b/dist/src/emojiButton/plugin.d.ts @@ -0,0 +1,3 @@ +import type { TwtKprPluginConfiguration } from 'express-twtkpr'; +declare const _default: () => TwtKprPluginConfiguration; +export default _default; diff --git a/dist/src/emojiButton/plugin.js b/dist/src/emojiButton/plugin.js new file mode 100644 index 0000000..0f97842 --- /dev/null +++ b/dist/src/emojiButton/plugin.js @@ -0,0 +1,32 @@ +import fs from 'node:fs'; +import { join } from 'node:path'; +import { getReadStream } from 'express-twtkpr'; +import { __dirname } from '../constants.js'; +console.log({ __dirname }); +const PLUGIN_NAME = 'emojiButton'; +export default () => ({ + clientCSS: () => { + const cssStream = fs.createReadStream(join(__dirname, 'src', PLUGIN_NAME, 'client', 'emoji.css')); + cssStream.on('error', (err) => { + console.error(err); + cssStream.close(); + cssStream.push(null); + }); + return cssStream; + }, + clientJS: () => { + const jsFileStream = getReadStream(join(__dirname, 'src', PLUGIN_NAME, 'client', 'emoji.js')); + /* + const jsStream = Readable.from(` + const twtSubmitButton = document.querySelector('.twtControls-submitButton'); + const emojiTarget = document.querySelector('.emoji_target'); + emojiTarget.addEventListener('change', () => { + if (twtSubmitButton) twtSubmitButton.removeAttribute('disabled'); + }); + `); + */ + return jsFileStream; + }, + name: PLUGIN_NAME, +}); +//# sourceMappingURL=plugin.js.map \ No newline at end of file diff --git a/dist/src/emojiButton/plugin.js.map b/dist/src/emojiButton/plugin.js.map new file mode 100644 index 0000000..fad40b4 --- /dev/null +++ b/dist/src/emojiButton/plugin.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/emojiButton/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAIjC,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,CAAC,GAAG,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC;AAE3B,MAAM,WAAW,GAAG,aAAa,CAAC;AAElC,eAAe,GAA8B,EAAE,CAAC,CAAC;IAChD,SAAS,EAAE,GAAG,EAAE;QACf,MAAM,SAAS,GAAG,EAAE,CAAC,gBAAgB,CACpC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAC1D,CAAC;QAEF,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC7B,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACnB,SAAS,CAAC,KAAK,EAAE,CAAC;YAClB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACtB,CAAC,CAAC,CAAC;QAEH,OAAO,SAAS,CAAC;IAClB,CAAC;IAED,QAAQ,EAAE,GAAG,EAAE;QACd,MAAM,YAAY,GAAG,aAAa,CACjC,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,UAAU,CAAC,CACzD,CAAC;QACF;;;;;;;;UAQE;QAEF,OAAO,YAAY,CAAC;IACrB,CAAC;IAED,IAAI,EAAE,WAAW;CACjB,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/src/index.d.ts b/dist/src/index.d.ts new file mode 100644 index 0000000..020e20d --- /dev/null +++ b/dist/src/index.d.ts @@ -0,0 +1,3 @@ +export { default as emojiButton } from './emojiButton/index.js'; +export { default as postToMastodon } from './postToMastodon/index.js'; +export { default as uploadButton } from './uploadButton/index.js'; diff --git a/dist/src/index.js b/dist/src/index.js new file mode 100644 index 0000000..ed1daa2 --- /dev/null +++ b/dist/src/index.js @@ -0,0 +1,4 @@ +export { default as emojiButton } from './emojiButton/index.js'; +export { default as postToMastodon } from './postToMastodon/index.js'; +export { default as uploadButton } from './uploadButton/index.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/src/index.js.map b/dist/src/index.js.map new file mode 100644 index 0000000..c35d245 --- /dev/null +++ b/dist/src/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,2BAA2B,CAAC;AACtE,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,yBAAyB,CAAC"} \ No newline at end of file diff --git a/dist/src/postToMastodon/client/script.js b/dist/src/postToMastodon/client/script.js new file mode 100644 index 0000000..5651d9a --- /dev/null +++ b/dist/src/postToMastodon/client/script.js @@ -0,0 +1,34 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT + +(() => { + const twtForm = document.getElementById('twtForm'); + + /* + document + .querySelector('.twtControls-contentLabel') + ?.insertAdjacentHTML('beforebegin', renderUploadButton()); + + document + .querySelector('#twtControlsEditButton') + ?.insertAdjacentHTML('beforebegin', renderUploadButton('small')); + + const twtControlsContentInput = document.getElementById( + 'twtControlsContentInput' + ); + + twtControlsContentInput.addEventListener('drop', dropHandler); + + twtControlsContentInput.addEventListener('dragover', dragOverHandler); + + window.addEventListener('dragover', dragOverWindowHandler); + + window.addEventListener('drop', dropWindowHandler); + + Array.from(document.querySelectorAll('.twtControls-uploadInput')).forEach( + (uploadInput) => { + uploadInput.addEventListener('change', uploadChangeHandler); + } + ); + */ +})(); +// @license-end diff --git a/dist/src/postToMastodon/index.d.ts b/dist/src/postToMastodon/index.d.ts new file mode 100644 index 0000000..77bfd60 --- /dev/null +++ b/dist/src/postToMastodon/index.d.ts @@ -0,0 +1 @@ +export { default } from './plugin.js'; diff --git a/dist/src/postToMastodon/index.js b/dist/src/postToMastodon/index.js new file mode 100644 index 0000000..7de5de3 --- /dev/null +++ b/dist/src/postToMastodon/index.js @@ -0,0 +1,2 @@ +export { default } from './plugin.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/src/postToMastodon/index.js.map b/dist/src/postToMastodon/index.js.map new file mode 100644 index 0000000..74e9add --- /dev/null +++ b/dist/src/postToMastodon/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/postToMastodon/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file diff --git a/dist/src/postToMastodon/plugin.d.ts b/dist/src/postToMastodon/plugin.d.ts new file mode 100644 index 0000000..14650e4 --- /dev/null +++ b/dist/src/postToMastodon/plugin.d.ts @@ -0,0 +1,3 @@ +import type { TwtKprConfiguration, TwtKprPluginConfiguration } from 'express-twtkpr'; +declare const _default: (config: TwtKprConfiguration) => TwtKprPluginConfiguration; +export default _default; diff --git a/dist/src/postToMastodon/plugin.js b/dist/src/postToMastodon/plugin.js new file mode 100644 index 0000000..61d7fdb --- /dev/null +++ b/dist/src/postToMastodon/plugin.js @@ -0,0 +1,59 @@ +import Debug from 'debug'; +const PLUGIN_NAME = 'postToMastodon'; +// curl https://toot.cafe/api/v1/statuses -H 'Authorization: Bearer A0k6vbobTQvG-n9DStsfGV03BKxKkZHL-IhljR3Lvik' -F 'status=Test posting from cURL via the API. Hello from the command line!' +export default (config) => { + const debug = Debug(`twtkprPlugin:${PLUGIN_NAME}`); + const { application_token, server_url } = config?.plugins?.[PLUGIN_NAME] ?? {}; + if (!application_token || !server_url) + return {}; + return { + onAfterTwt: async (twt) => { + // TODO: add some console.log / error to output things that we can't return a message for + // That way, it shows up _somewhere_ + // Don't do anything if the twt is a reply (starts with a hash) + const [, content] = twt.split(/\t/); + if (content.match(/^\(#(\w+)\)/)) { + // it's a reply, skip + return; + } + const formData = new FormData(); + formData.append('status', content.replace(/\s*\u2028/g, '\n')); + debug(`Sending message to Mastodon instance at ${server_url}`); + const res = await fetch(`${server_url}${server_url.endsWith('/') ? '' : '/'}api/v1/statuses`, { + method: 'POST', + body: formData, + headers: { + Authorization: `Bearer ${application_token}`, + }, + }); + if (!res.ok) { + console.error(`Bad response (${res.status}) from Mastodon server ${server_url}: ${res.statusText}`); + return; + } + const result = await res.text(); + console.log(`Twt sent to Mastodon server ${server_url}, response:`, { + result, + }); + }, + // use JS to add a checkbox to the form + // update the Twt post function to send the whole form - that will + // allow you to add new things to it and they will be sent + /* + clientJS: () => { + const jsStream = fs.createReadStream( + path.join(__dirname, 'plugins', PLUGIN_NAME, 'script.js') + ); + + jsStream.on('error', (err) => { + console.error(err); + jsStream.close(); + jsStream.push(null); + }); + + return jsStream; + }, + */ + name: PLUGIN_NAME, + }; +}; +//# sourceMappingURL=plugin.js.map \ No newline at end of file diff --git a/dist/src/postToMastodon/plugin.js.map b/dist/src/postToMastodon/plugin.js.map new file mode 100644 index 0000000..74b0e13 --- /dev/null +++ b/dist/src/postToMastodon/plugin.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/postToMastodon/plugin.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAErC,6LAA6L;AAE7L,eAAe,CAAC,MAA2B,EAA6B,EAAE;IACzE,MAAM,KAAK,GAAG,KAAK,CAAC,gBAAgB,WAAW,EAAE,CAAC,CAAC;IAEnD,MAAM,EAAE,iBAAiB,EAAE,UAAU,EAAE,GACtC,MAAM,EAAE,OAAO,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAEtC,IAAI,CAAC,iBAAiB,IAAI,CAAC,UAAU;QAAE,OAAO,EAAE,CAAC;IAEjD,OAAO;QACN,UAAU,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;YACzB,yFAAyF;YACzF,oCAAoC;YAEpC,+DAA+D;YAC/D,MAAM,CAAC,EAAE,OAAO,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YACpC,IAAI,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,EAAE,CAAC;gBAClC,qBAAqB;gBACrB,OAAO;YACR,CAAC;YAED,MAAM,QAAQ,GAAG,IAAI,QAAQ,EAAE,CAAC;YAChC,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC,CAAC;YAE/D,KAAK,CAAC,2CAA2C,UAAU,EAAE,CAAC,CAAC;YAE/D,MAAM,GAAG,GAAG,MAAM,KAAK,CACtB,GAAG,UAAU,GAAG,UAAU,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,iBAAiB,EACpE;gBACC,MAAM,EAAE,MAAM;gBACd,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE;oBACR,aAAa,EAAE,UAAU,iBAAiB,EAAE;iBAC5C;aACD,CACD,CAAC;YAEF,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;gBACb,OAAO,CAAC,KAAK,CACZ,iBAAiB,GAAG,CAAC,MAAM,0BAC1B,UACD,KAAK,GAAG,CAAC,UAAU,EAAE,CACrB,CAAC;gBACF,OAAO;YACR,CAAC;YAED,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;YAEhC,OAAO,CAAC,GAAG,CAAC,+BAA+B,UAAU,aAAa,EAAE;gBACnE,MAAM;aACN,CAAC,CAAC;QACJ,CAAC;QAED,uCAAuC;QACvC,kEAAkE;QAClE,0DAA0D;QAE1D;;;;;;;;;;;;;;UAcQ;QAER,IAAI,EAAE,WAAW;KACjB,CAAC;AACH,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/src/uploadButton/client/script.js b/dist/src/uploadButton/client/script.js new file mode 100644 index 0000000..ac44401 --- /dev/null +++ b/dist/src/uploadButton/client/script.js @@ -0,0 +1,154 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT +const injectUploadButton = (route) => { + // const route = '/files'; + + /** + * + * @param uploadConfiguration + * @param variant + * @returns + */ + const renderUploadButton = (variant = 'normal') => ` + + `; + + const uploadFiles = async (files, uploadRoute, secondAttempt = false) => { + if (!uploadRoute || !window.token || !window.refreshToken) return; + + debug('uploadFiles', token, files, uploadRoute, secondAttempt); + + const formData = new FormData(); + for (let i = 0; i < files.length; i++) { + formData.append('files', files[i]); + } + + try { + const res = await fetch(uploadRoute, { + method: 'POST', + type: 'upload', + body: formData, + headers: { + Authorization: `Bearer ${token}`, + }, + credentials: 'include', + }); + + if (res.ok) { + showToast(`File${files.length !== 1 ? 's' : ''} uploaded`); + + const filePath = await res.text(); + twtControlsContentInput.value += filePath + .split('\n') + .map((currFilePath) => + [ + ' ', + location.protocol, + '//', + location.hostname, + location.protocol !== 'https:' && location.port !== 80 + ? ':' + location.port + : '', + currFilePath, + ].join('') + ) + .join(''); + + return; + } + + if (!secondAttempt) { + await refreshToken(); + return uploadFiles(files, uploadRoute, true); + } + + showToast( + `Unable to upload image${files.length !== 1 ? 's' : ''} refresh token, please try again later.`, + 'error' + ); + } catch (err) { + console.error(err); + } + }; + + /* Handlers */ + + const dragOverHandler = (ev) => { + const files = [...ev.dataTransfer.items].filter( + (item) => item.kind === 'file' + ); + + if (files.length > 0) { + ev.preventDefault(); + ev.dataTransfer.dropEffect = 'copy'; + } + }; + + const dragOverWindowHandler = (ev) => { + const files = [...ev.dataTransfer.items].filter( + (item) => item.kind === 'file' + ); + + if (files.length > 0) { + ev.preventDefault(); + + if (!twtControlsContentInput.contains(ev.target)) { + ev.dataTransfer.dropEffect = 'none'; + } + } + }; + + const dropHandler = (ev) => { + ev.preventDefault(); + + const files = [...ev.dataTransfer.items] + .map((item) => item.getAsFile()) + .filter((file) => file); + + debug('dropHandler', files); + uploadFiles(files, route); + }; + + const dropWindowHandler = (ev) => { + if ([...ev.dataTransfer.items].some((item) => item.kind === 'file')) { + ev.preventDefault(); + } + }; + + const uploadChangeHandler = (ev) => { + uploadFiles(ev.target.files, route); + }; + + document + .querySelector('.twtControls-contentLabel') + ?.insertAdjacentHTML('beforebegin', renderUploadButton()); + + document + .querySelector('#twtControlsEditButton') + ?.insertAdjacentHTML('beforebegin', renderUploadButton('small')); + + const twtControlsContentInput = document.getElementById( + 'twtControlsContentInput' + ); + + twtControlsContentInput.addEventListener('drop', dropHandler); + + twtControlsContentInput.addEventListener('dragover', dragOverHandler); + + window.addEventListener('dragover', dragOverWindowHandler); + + window.addEventListener('drop', dropWindowHandler); + + Array.from(document.querySelectorAll('.twtControls-uploadInput')).forEach( + (uploadInput) => { + uploadInput.addEventListener('change', uploadChangeHandler); + } + ); +}; +// @license-end diff --git a/dist/src/uploadButton/client/styles.css b/dist/src/uploadButton/client/styles.css new file mode 100644 index 0000000..eda28a7 --- /dev/null +++ b/dist/src/uploadButton/client/styles.css @@ -0,0 +1,37 @@ +/** + * Begin TwtKpr UploadPlugin CSS + */ +.twtControls-uploadInputLabel { + align-items: center; + cursor: pointer; + display: flex; + justify-content: center; + max-width: 100%; + text-align: center; + transition: all 0.5s; +} + +.twtControls-uploadInputLabel input { + display: none; +} + +/* +.twtControls-uploadInputLabel-normal { + display: none; +} +*/ + +.twtControls-uploadInputLabel-small { + font-size: small; +} + +.twtControls-uploadInputLabel:hover { + background-color: var(--bg-hl); + color: var(--fg-hl); +} + +/* +.twtControls-uploadInput { + display: none; +} +*/ diff --git a/dist/src/uploadButton/defaults.d.ts b/dist/src/uploadButton/defaults.d.ts new file mode 100644 index 0000000..83f86c5 --- /dev/null +++ b/dist/src/uploadButton/defaults.d.ts @@ -0,0 +1,12 @@ +declare const _default: { + allowedMimeTypes: string; + directory: string; + imageFit: string; + imageHeight: number; + imageWidth: number; + route: string; + hashAlgorithm: string; + keepExtensions: boolean; + maxFiles: number; +}; +export default _default; diff --git a/dist/src/uploadButton/defaults.js b/dist/src/uploadButton/defaults.js new file mode 100644 index 0000000..23428cd --- /dev/null +++ b/dist/src/uploadButton/defaults.js @@ -0,0 +1,39 @@ +/* + uploadConfiguration: { + ...uploadConfiguration, + active: uploadActive, + allowEmptyFiles, + allowedMimeTypes: getDestinationByMimeTypeConfiguration(allowedMimeTypes), + createDirsFromUploads, + directory, + encoding, + fileWriteStreamHandler, + filter, + hashAlgorithm: hashAlgorithm as string | false | undefined, + keepExtensions, + maxFields, + maxFileSize, + maxFiles, + maxTotalFileSize, + minFileSize, + route, + }, +*/ +// falls back to formidable defaults where it can +export default { + // local values + allowedMimeTypes: '', + directory: 'public', + imageFit: 'inside', + imageHeight: 1024, + imageWidth: 1024, + route: 'files', + // uploadEncoding: 'utf-8', + // defaults for formidable + // allowEmptyFiles: false, // same as formidable + // encoding: 'utf-8', // same as formidable + hashAlgorithm: 'sha256', + keepExtensions: true, // TODO: verify this is necessary + maxFiles: 10, +}; +//# sourceMappingURL=defaults.js.map \ No newline at end of file diff --git a/dist/src/uploadButton/defaults.js.map b/dist/src/uploadButton/defaults.js.map new file mode 100644 index 0000000..d0a5a02 --- /dev/null +++ b/dist/src/uploadButton/defaults.js.map @@ -0,0 +1 @@ +{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../../src/uploadButton/defaults.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;EAoBE;AAEF,iDAAiD;AACjD,eAAe;IACd,eAAe;IACf,gBAAgB,EAAE,EAAE;IACpB,SAAS,EAAE,QAAQ;IACnB,QAAQ,EAAE,QAAQ;IAClB,WAAW,EAAE,IAAI;IACjB,UAAU,EAAE,IAAI;IAChB,KAAK,EAAE,OAAO;IACd,2BAA2B;IAE3B,0BAA0B;IAC1B,iDAAiD;IACjD,4CAA4C;IAC5C,aAAa,EAAE,QAAQ;IACvB,cAAc,EAAE,IAAI,EAAE,iCAAiC;IACvD,QAAQ,EAAE,EAAE;CACZ,CAAC"} \ No newline at end of file diff --git a/dist/src/uploadButton/index.d.ts b/dist/src/uploadButton/index.d.ts new file mode 100644 index 0000000..77bfd60 --- /dev/null +++ b/dist/src/uploadButton/index.d.ts @@ -0,0 +1 @@ +export { default } from './plugin.js'; diff --git a/dist/src/uploadButton/index.js b/dist/src/uploadButton/index.js new file mode 100644 index 0000000..7de5de3 --- /dev/null +++ b/dist/src/uploadButton/index.js @@ -0,0 +1,2 @@ +export { default } from './plugin.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/src/uploadButton/index.js.map b/dist/src/uploadButton/index.js.map new file mode 100644 index 0000000..077bb2b --- /dev/null +++ b/dist/src/uploadButton/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/uploadButton/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC"} \ No newline at end of file diff --git a/dist/src/uploadButton/plugin.d.ts b/dist/src/uploadButton/plugin.d.ts new file mode 100644 index 0000000..14650e4 --- /dev/null +++ b/dist/src/uploadButton/plugin.d.ts @@ -0,0 +1,3 @@ +import type { TwtKprConfiguration, TwtKprPluginConfiguration } from 'express-twtkpr'; +declare const _default: (config: TwtKprConfiguration) => TwtKprPluginConfiguration; +export default _default; diff --git a/dist/src/uploadButton/plugin.js b/dist/src/uploadButton/plugin.js new file mode 100644 index 0000000..0100086 --- /dev/null +++ b/dist/src/uploadButton/plugin.js @@ -0,0 +1,167 @@ +import { promises as fsp } from 'node:fs'; +import { extname, join } from 'node:path'; +import { Readable } from 'node:stream'; +import Debug from 'debug'; +import { combineStreams, getReadStream } from 'express-twtkpr'; +import formidable from 'formidable'; +import sharp from 'sharp'; +import { __dirname } from '../constants.js'; +import defaults from './defaults.js'; +import { getDestinationByMimeTypeConfiguration } from './utils.js'; +const PLUGIN_NAME = 'uploadButton'; +export default (config) => { + const debug = Debug(`twtkprPlugin:${PLUGIN_NAME}}`); + const { route = '/files' } = config?.plugins?.[PLUGIN_NAME] ?? {}; + return { + clientCSS: () => { + const stream = getReadStream(join(__dirname, 'src', PLUGIN_NAME, 'client', 'styles.css')); + return stream; + }, + clientJS: () => { + const jsStream = getReadStream(join(__dirname, 'src', PLUGIN_NAME, 'client', 'script.js')); + const jsCallerStream = Readable.from(`injectUploadButton('${route}');`); + return combineStreams([jsStream, jsCallerStream]); + }, + name: PLUGIN_NAME, + postRoutes: [ + { + path: route, + handler: async (req, res, next) => { + const { allowedMimeTypes, directory, imageFit, imageHeight, imageWidth, route, ...otherProps } = Object.assign({}, defaults, config?.plugins?.uploadConfiguration ?? {}); + if (Array.isArray(allowedMimeTypes) && !allowedMimeTypes.length) { + next(); + return; + } + debug('using configuration: ', { + uploadConfiguration: config?.plugins?.uploadConfiguration, + }); + const form = formidable({ + uploadDir: directory, + ...otherProps, + }); + form.parse(req, async (err, fields, files) => { + if (err) { + next(err); + return; + } + const uploadsDir = (route ?? '').replaceAll('/', ''); + let hadFileError = false; + const processedFiles = []; + const destinationByMimeType = getDestinationByMimeTypeConfiguration(allowedMimeTypes); + debug(`processing ${(files?.files ?? []).length} files`); + for (const file of files?.files ?? []) { + const { filepath, hash, mimetype, newFilename, originalFilename, } = file ?? {}; + if (!(filepath && newFilename && originalFilename)) + return; + debug({ file }); + let ext = extname(originalFilename).toLocaleLowerCase(); + if (ext === '.jpeg') + ext = '.jpg'; + let destinationDir = ''; + Object.keys(destinationByMimeType).forEach((mimeType) => { + if (file.mimetype?.split('/')?.[0] === + mimeType.toLocaleLowerCase()) + destinationDir = + destinationByMimeType[mimeType].directory ?? ''; + }); + if (destinationDir === '') + destinationDir = + destinationByMimeType['*']?.directory ?? uploadsDir; + const finalPath = join(process.cwd(), 'public', destinationDir); + const useOriginalName = !(mimetype?.includes('image') || mimetype?.includes('video')); + let hashNameLength = 8; + let finalFilename; + let fileExists; + do { + finalFilename = (!useOriginalName && hash + ? `${hash.substring(0, hashNameLength)}${ext}` + : originalFilename) + .replace(/[^\w\.]+/g, '_') + .replace(/_+/g, '_') + .toLocaleLowerCase(); + if (!useOriginalName) { + try { + await fsp.stat(join(finalPath, finalFilename)); + fileExists = true; + hashNameLength++; + } + catch { + fileExists = false; + } + } + } while (!useOriginalName && fileExists); + debug(`creating '${finalPath}'`); + fsp.mkdir(finalPath, { recursive: true }); + const pathToOutputFile = join(finalPath, finalFilename); + let wasRelocated = false; + if (mimetype?.includes('image')) { + // use sharp to shrink + debug(`converting '${filepath}' to '/${pathToOutputFile}'`); + try { + await sharp(filepath) + .autoOrient() + // shrink to 1024 on biggest edge, do not enlarge + .resize({ + fit: imageFit, + height: imageHeight, + width: imageWidth, + withoutEnlargement: true, + }) + .toFile(pathToOutputFile); + /* + await sharp(filepath) + .metadata() + .then(({ height, width }) => + sharp(filepath) + // shrink to 1024 on biggest edge, do not enlarge + .resize({ + height: height >= width ? 1024 : undefined, + width: width >= height ? 1024 : undefined, + withoutEnlargement: true, + }) + .toFile(pathToOutputFile) + ); + */ + wasRelocated = true; + } + catch { + // at least we tried + } + } + try { + if (!wasRelocated) { + debug(`copying '${filepath}' to '/${pathToOutputFile}'`); + await fsp.copyFile(filepath, pathToOutputFile); + } + debug(`cleaning up '${filepath}'`); + await fsp.rm(filepath); + debug(`processed successfully`); + processedFiles.push(`/${destinationDir}/${finalFilename}`); + } + catch (err) { + debug(`error!`); + hadFileError = true; + console.error(err); + } + } + debug('generating reply...'); + if (hadFileError && processedFiles.length) { + res + .type('text/plain') + .status(206) + .send(processedFiles.join('\n')); + return; + } + if (!processedFiles.length) { + res.type('text/plain').status(500).send('No files processed'); + return; + } + res.type('text/plain').status(201).send(processedFiles.join('\n')); + }); + }, + requiresAuth: true, + }, + ], + }; +}; +//# sourceMappingURL=plugin.js.map \ No newline at end of file diff --git a/dist/src/uploadButton/plugin.js.map b/dist/src/uploadButton/plugin.js.map new file mode 100644 index 0000000..473eb1b --- /dev/null +++ b/dist/src/uploadButton/plugin.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plugin.js","sourceRoot":"","sources":["../../../src/uploadButton/plugin.ts"],"names":[],"mappings":"AAOA,OAAW,EAAE,QAAQ,IAAI,GAAG,EAAS,MAAM,SAAS,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAEvC,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAC/D,OAAO,UAAU,MAAM,YAAY,CAAC;AACpC,OAAO,KAAkB,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,QAAQ,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,qCAAqC,EAAE,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,GAAG,cAAc,CAAC;AAEnC,eAAe,CAAC,MAA2B,EAA6B,EAAE;IACzE,MAAM,KAAK,GAAG,KAAK,CAAC,gBAAgB,WAAW,GAAG,CAAC,CAAC;IACpD,MAAM,EAAE,KAAK,GAAG,QAAQ,EAAE,GAAG,MAAM,EAAE,OAAO,EAAE,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;IAElE,OAAO;QACN,SAAS,EAAE,GAAG,EAAE;YACf,MAAM,MAAM,GAAG,aAAa,CAC3B,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,YAAY,CAAC,CAC3D,CAAC;YACF,OAAO,MAAM,CAAC;QACf,CAAC;QACD,QAAQ,EAAE,GAAG,EAAE;YACd,MAAM,QAAQ,GAAG,aAAa,CAC7B,IAAI,CAAC,SAAS,EAAE,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,WAAW,CAAC,CAC1D,CAAC;YACF,MAAM,cAAc,GAAG,QAAQ,CAAC,IAAI,CAAC,uBAAuB,KAAK,KAAK,CAAC,CAAC;YAExE,OAAO,cAAc,CAAC,CAAC,QAAQ,EAAE,cAAc,CAAC,CAAC,CAAC;QACnD,CAAC;QAED,IAAI,EAAE,WAAW;QAEjB,UAAU,EAAE;YACX;gBACC,IAAI,EAAE,KAAK;gBACX,OAAO,EAAE,KAAK,EAAE,GAAY,EAAE,GAAa,EAAE,IAAkB,EAAE,EAAE;oBAClE,MAAM,EACL,gBAAgB,EAChB,SAAS,EACT,QAAQ,EACR,WAAW,EACX,UAAU,EACV,KAAK,EACL,GAAG,UAAU,EACb,GAAG,MAAM,CAAC,MAAM,CAChB,EAAE,EACF,QAAQ,EACR,MAAM,EAAE,OAAO,EAAE,mBAAmB,IAAI,EAAE,CAC1C,CAAC;oBAEF,IAAI,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,CAAC,gBAAgB,CAAC,MAAM,EAAE,CAAC;wBACjE,IAAI,EAAE,CAAC;wBACP,OAAO;oBACR,CAAC;oBAED,KAAK,CAAC,uBAAuB,EAAE;wBAC9B,mBAAmB,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB;qBACzD,CAAC,CAAC;oBAEH,MAAM,IAAI,GAAG,UAAU,CAAC;wBACvB,SAAS,EAAE,SAAS;wBACpB,GAAG,UAAU;qBACb,CAAC,CAAC;oBAEH,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;wBAC5C,IAAI,GAAG,EAAE,CAAC;4BACT,IAAI,CAAC,GAAG,CAAC,CAAC;4BACV,OAAO;wBACR,CAAC;wBACD,MAAM,UAAU,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;wBAErD,IAAI,YAAY,GAAG,KAAK,CAAC;wBACzB,MAAM,cAAc,GAAa,EAAE,CAAC;wBACpC,MAAM,qBAAqB,GAC1B,qCAAqC,CAAC,gBAAgB,CAAC,CAAC;wBAEzD,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,QAAQ,CAAC,CAAC;wBAEzD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;4BACvC,MAAM,EACL,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,WAAW,EACX,gBAAgB,GAChB,GAAG,IAAI,IAAI,EAAE,CAAC;4BACf,IAAI,CAAC,CAAC,QAAQ,IAAI,WAAW,IAAI,gBAAgB,CAAC;gCAAE,OAAO;4BAE3D,KAAK,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;4BAEhB,IAAI,GAAG,GAAG,OAAO,CAAC,gBAAgB,CAAC,CAAC,iBAAiB,EAAE,CAAC;4BACxD,IAAI,GAAG,KAAK,OAAO;gCAAE,GAAG,GAAG,MAAM,CAAC;4BAElC,IAAI,cAAc,GAAG,EAAE,CAAC;4BACxB,MAAM,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,EAAE,EAAE;gCACvD,IACC,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC;oCAC9B,QAAQ,CAAC,iBAAiB,EAAE;oCAE5B,cAAc;wCAEZ,qBAAqB,CACpB,QAA8C,CAE/C,CAAC,SAAS,IAAI,EAAE,CAAC;4BACrB,CAAC,CAAC,CAAC;4BACH,IAAI,cAAc,KAAK,EAAE;gCACxB,cAAc;oCAEZ,qBAAqB,CACpB,GAAyC,CAE1C,EAAE,SAAS,IAAI,UAAU,CAAC;4BAE7B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;4BAEhE,MAAM,eAAe,GAAG,CAAC,CACxB,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,IAAI,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,CAC1D,CAAC;4BACF,IAAI,cAAc,GAAG,CAAC,CAAC;4BACvB,IAAI,aAAa,CAAC;4BAClB,IAAI,UAAU,CAAC;4BACf,GAAG,CAAC;gCACH,aAAa,GAAG,CACf,CAAC,eAAe,IAAI,IAAI;oCACvB,CAAC,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,cAAc,CAAC,GAAG,GAAG,EAAE;oCAC9C,CAAC,CAAC,gBAAgB,CACnB;qCACC,OAAO,CAAC,WAAW,EAAE,GAAG,CAAC;qCACzB,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC;qCACnB,iBAAiB,EAAE,CAAC;gCAEtB,IAAI,CAAC,eAAe,EAAE,CAAC;oCACtB,IAAI,CAAC;wCACJ,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,CAAC;wCAC/C,UAAU,GAAG,IAAI,CAAC;wCAClB,cAAc,EAAE,CAAC;oCAClB,CAAC;oCAAC,MAAM,CAAC;wCACR,UAAU,GAAG,KAAK,CAAC;oCACpB,CAAC;gCACF,CAAC;4BACF,CAAC,QAAQ,CAAC,eAAe,IAAI,UAAU,EAAE;4BAEzC,KAAK,CAAC,aAAa,SAAS,GAAG,CAAC,CAAC;4BACjC,GAAG,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;4BAE1C,MAAM,gBAAgB,GAAG,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;4BACxD,IAAI,YAAY,GAAG,KAAK,CAAC;4BAEzB,IAAI,QAAQ,EAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gCACjC,sBAAsB;gCACtB,KAAK,CAAC,eAAe,QAAQ,UAAU,gBAAgB,GAAG,CAAC,CAAC;gCAE5D,IAAI,CAAC;oCACJ,MAAM,KAAK,CAAC,QAAQ,CAAC;yCACnB,UAAU,EAAE;wCACb,iDAAiD;yCAChD,MAAM,CAAC;wCACP,GAAG,EAAE,QAAqC;wCAC1C,MAAM,EAAE,WAAW;wCACnB,KAAK,EAAE,UAAU;wCACjB,kBAAkB,EAAE,IAAI;qCACxB,CAAC;yCACD,MAAM,CAAC,gBAAgB,CAAC,CAAC;oCAC3B;;;;;;;;;;;;;sCAaE;oCACF,YAAY,GAAG,IAAI,CAAC;gCACrB,CAAC;gCAAC,MAAM,CAAC;oCACR,oBAAoB;gCACrB,CAAC;4BACF,CAAC;4BAED,IAAI,CAAC;gCACJ,IAAI,CAAC,YAAY,EAAE,CAAC;oCACnB,KAAK,CAAC,YAAY,QAAQ,UAAU,gBAAgB,GAAG,CAAC,CAAC;oCAEzD,MAAM,GAAG,CAAC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC;gCAChD,CAAC;gCAED,KAAK,CAAC,gBAAgB,QAAQ,GAAG,CAAC,CAAC;gCACnC,MAAM,GAAG,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;gCAEvB,KAAK,CAAC,wBAAwB,CAAC,CAAC;gCAChC,cAAc,CAAC,IAAI,CAAC,IAAI,cAAc,IAAI,aAAa,EAAE,CAAC,CAAC;4BAC5D,CAAC;4BAAC,OAAO,GAAG,EAAE,CAAC;gCACd,KAAK,CAAC,QAAQ,CAAC,CAAC;gCAChB,YAAY,GAAG,IAAI,CAAC;gCACpB,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;4BACpB,CAAC;wBACF,CAAC;wBAED,KAAK,CAAC,qBAAqB,CAAC,CAAC;wBAC7B,IAAI,YAAY,IAAI,cAAc,CAAC,MAAM,EAAE,CAAC;4BAC3C,GAAG;iCACD,IAAI,CAAC,YAAY,CAAC;iCAClB,MAAM,CAAC,GAAG,CAAC;iCACX,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;4BAClC,OAAO;wBACR,CAAC;wBAED,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,CAAC;4BAC5B,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;4BAC9D,OAAO;wBACR,CAAC;wBAED,GAAG,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;oBACpE,CAAC,CAAC,CAAC;gBACJ,CAAC;gBACD,YAAY,EAAE,IAAI;aAClB;SACD;KACD,CAAC;AACH,CAAC,CAAC"} \ No newline at end of file diff --git a/dist/src/uploadButton/types.d.ts b/dist/src/uploadButton/types.d.ts new file mode 100644 index 0000000..73fbd47 --- /dev/null +++ b/dist/src/uploadButton/types.d.ts @@ -0,0 +1,13 @@ +import type { MimeOptions } from 'express-twtkpr'; +import formidable from 'formidable'; +export interface MimeImageOptions extends MimeOptions { + compression?: string; + maxHeight?: string; + maxWidth?: string; +} +export interface UploadConfiguration extends Partial> { + active: boolean; + directory: string; + allowedMimeTypes: string | string[] | Record; + route: string; +} diff --git a/dist/src/uploadButton/types.js b/dist/src/uploadButton/types.js new file mode 100644 index 0000000..718fd38 --- /dev/null +++ b/dist/src/uploadButton/types.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/dist/src/uploadButton/types.js.map b/dist/src/uploadButton/types.js.map new file mode 100644 index 0000000..a1d5790 --- /dev/null +++ b/dist/src/uploadButton/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/uploadButton/types.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/src/uploadButton/utils.d.ts b/dist/src/uploadButton/utils.d.ts new file mode 100644 index 0000000..0bdb599 --- /dev/null +++ b/dist/src/uploadButton/utils.d.ts @@ -0,0 +1,7 @@ +import type { MimeOptions } from 'express-twtkpr'; +/** + * + * @param allowedMimeTypes + * @returns + */ +export declare const getDestinationByMimeTypeConfiguration: (allowedMimeTypes?: string | string[] | Record) => Record; diff --git a/dist/src/uploadButton/utils.js b/dist/src/uploadButton/utils.js new file mode 100644 index 0000000..6970051 --- /dev/null +++ b/dist/src/uploadButton/utils.js @@ -0,0 +1,48 @@ +/** + * + * @param allowedMimeTypes + * @returns + */ +export const getDestinationByMimeTypeConfiguration = (allowedMimeTypes) => { + const fallback = { + audio: { + directory: 'audio', + rename: false, + }, + image: { + directory: 'images', + rename: true, + }, + video: { + directory: 'videos', + rename: true, + }, + '*': { + directory: 'files', + rename: false, + }, + }; + const mimeTypeArrayReducer = (acc, curr) => { + if (fallback[curr]) + acc[curr] = fallback[curr]; + else + acc[curr] = { + directory: `${curr}s`, + rename: false, + }; + return acc; + }; + if (!allowedMimeTypes) + return fallback; + if (typeof allowedMimeTypes === 'string') + return allowedMimeTypes + .split(',') + .map((val) => val.trim()) + .reduce(mimeTypeArrayReducer, {}); + if (Array.isArray(allowedMimeTypes)) + return allowedMimeTypes.reduce(mimeTypeArrayReducer, {}); + if (typeof allowedMimeTypes === 'object') + return allowedMimeTypes; + return fallback; +}; +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/dist/src/uploadButton/utils.js.map b/dist/src/uploadButton/utils.js.map new file mode 100644 index 0000000..d3c1e9a --- /dev/null +++ b/dist/src/uploadButton/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/uploadButton/utils.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,MAAM,CAAC,MAAM,qCAAqC,GAAG,CACpD,gBAAkE,EACjE,EAAE;IACH,MAAM,QAAQ,GAAgC;QAC7C,KAAK,EAAE;YACN,SAAS,EAAE,OAAO;YAClB,MAAM,EAAE,KAAK;SACb;QACD,KAAK,EAAE;YACN,SAAS,EAAE,QAAQ;YACnB,MAAM,EAAE,IAAI;SACZ;QACD,KAAK,EAAE;YACN,SAAS,EAAE,QAAQ;YACnB,MAAM,EAAE,IAAI;SACZ;QACD,GAAG,EAAE;YACJ,SAAS,EAAE,OAAO;YAClB,MAAM,EAAE,KAAK;SACb;KACD,CAAC;IAEF,MAAM,oBAAoB,GAAG,CAC5B,GAAgC,EAChC,IAAY,EACX,EAAE;QACH,IAAI,QAAQ,CAAC,IAAI,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC;;YAE9C,GAAG,CAAC,IAAI,CAAC,GAAG;gBACX,SAAS,EAAE,GAAG,IAAI,GAAG;gBACrB,MAAM,EAAE,KAAK;aACb,CAAC;QAEH,OAAO,GAAG,CAAC;IACZ,CAAC,CAAC;IAEF,IAAI,CAAC,gBAAgB;QAAE,OAAO,QAAQ,CAAC;IAEvC,IAAI,OAAO,gBAAgB,KAAK,QAAQ;QACvC,OAAO,gBAAgB;aACrB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC;aACxB,MAAM,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;IAEpC,IAAI,KAAK,CAAC,OAAO,CAAC,gBAAgB,CAAC;QAClC,OAAQ,gBAA6B,CAAC,MAAM,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;IAExE,IAAI,OAAO,gBAAgB,KAAK,QAAQ;QAAE,OAAO,gBAAgB,CAAC;IAElE,OAAO,QAAQ,CAAC;AACjB,CAAC,CAAC"} \ No newline at end of file diff --git a/eslint.config.js b/eslint.config.js new file mode 100644 index 0000000..57dc71c --- /dev/null +++ b/eslint.config.js @@ -0,0 +1,42 @@ +export default [ + { + // Basic settings + files: ['**/*.js', '**/*.ts'], + ignores: ['dist/**', 'node_modules/**'], + languageOptions: { + ecmaVersion: 2025, + sourceType: 'module', + }, + + // Core rules + rules: { + 'no-unused-vars': 'error', + 'no-undef': 'error', + 'no-console': 'warn', + + 'node/no-deprecated-api': 'error', + 'node/no-missing-import': 'error', + 'performance/no-costly-loop': 'warn', + 'promise/prefer-await-to-then': 'error', + 'security/detect-eval-with-expression': 'error', + 'security/detect-non-literal-fs-filename': 'error', + 'security/detect-non-literal-regexp': 'error', + 'security/detect-object-injection': 'warn', + 'security/detect-possible-timing-attacks': 'warn', + }, + + // Use recommended presets + extends: [ + 'eslint:recommended', + 'plugin:node/recommended', + 'plugin:security/recommended', + ], + }, + { + files: ['**/*.js', '**/*.ts'], + plugins: ['prettier'], + rules: { + 'prettier/prettier': 'error', + }, + }, +]; diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..f64f6b2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,30 @@ +{ + "name": "express-twtkpr-upload-button", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "express-twtkpr-upload-button", + "devDependencies": { + "@types/node": "^25.6.0" + } + }, + "node_modules/@types/node": { + "version": "25.6.0", + "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz", + "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~7.19.0" + } + }, + "node_modules/undici-types": { + "version": "7.19.2", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz", + "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==", + "dev": true, + "license": "MIT" + } + } +} diff --git a/package.json b/package.json index 7c87284..c2efc6e 100644 --- a/package.json +++ b/package.json @@ -1,4 +1,54 @@ { - "name": "express-twtkpr-upload-button", - "packageManager": "yarn@4.9.2" + "name": "express-twtkpr-core-plugins", + "version": "0.9.0", + "description": "A library of plugins that enhance TwtKpr installs (made with the `express-twtkpr` package).", + "license": "MIT", + "author": { + "name": "Eric Woodward", + "email": "hey@itsericwoodward.com", + "url": "https://www.itsericwoodward.com" + }, + "repository": { + "type": "git", + "url": "https://git.itsericwoodward.com/eric/express-twtkpr-core-plugins" + }, + "packageManager": "yarn@4.14.1", + "type": "module", + "main": "./dist/src/index.js", + "module": "./dist/src/index.js", + "types": "./dist/src/index.d.ts", + "exports": { + ".": { + "import": "./dist/src/index.js" + } + }, + "files": [ + "dist" + ], + "scripts": { + "build": "tsc && rsync -avm --include '*/' --include '*/client/*.*' --exclude '*' src/ dist/src", + "lint": "eslint --fix src test", + "prepublishOnly": "yarn build", + "test": "vitest", + "typecheck": "tsc --noEmit" + }, + "dependencies": { + "debug": "^4.4.3", + "express": "^5.2.1", + "express-twtkpr": "^0.9.0", + "formidable": "^3.5.4", + "sharp": "^0.34.5" + }, + "devDependencies": { + "@types/debug": "^4.1.13", + "@types/express": "^5.0.6", + "@types/formidable": "^3.5.1", + "eslint": "^10.3.0", + "eslint-config-prettier": "^10.1.8", + "eslint-plugin-prettier": "^5.5.5", + "eslint-plugin-security": "^4.0.0", + "prettier": "^3.8.3", + "typescript": "^6.0.3", + "vitest": "^4.1.5" + } } diff --git a/src/constants.ts b/src/constants.ts new file mode 100644 index 0000000..544136c --- /dev/null +++ b/src/constants.ts @@ -0,0 +1,4 @@ +import { dirname, resolve } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +export const __dirname = resolve(dirname(fileURLToPath(import.meta.url)), '..'); diff --git a/src/emojiButton/client/emoji.css b/src/emojiButton/client/emoji.css new file mode 100644 index 0000000..0153896 --- /dev/null +++ b/src/emojiButton/client/emoji.css @@ -0,0 +1,114 @@ +/* Copyright ยฉ 2020 Jamie Zawinski + + Permission to use, copy, modify, distribute, and sell this software + and its documentation for any purpose is hereby granted without + fee, provided that the above copyright notice appear in all copies + and that both that copyright notice and this permission notice + appear in supporting documentation. No representations are made + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + Emoji popup menu. There are many like it. This one is mine. + + Created: 24-May-2020 +*/ + +#emoji_blocker { + position: fixed; + top: 0; + left: 0; + right: 0; + bottom: 0; + background: none; + z-index: 1000; +} + +.emoji_menu { + position: fixed; + display: inline-block; + border: 1px solid; + width: 22em; + text-align: center; + z-index: 1001; + background: #000; +} + +.emoji_tab_bar { + display: block; + text-align: center; +} + +.emoji_tab { + display: inline-block; + text-align: center; + width: 1.8em; + height: 1.3em; + padding: 0px 2px 8px 2px; + cursor: pointer; +} + +.emoji_tab.selected { + background: #040; +} + +.emoji_page_box { + height: 16em; + overflow-y: auto; + background: #040; +} + +.emoji_page { + display: none; + text-align: center; + width: 100%; +} + +.emoji_page > b { + display: block; + font-size: smaller; + margin: 4px; +} + +.emoji_square { + display: inline-block; + text-align: center; + width: 1.3em; + height: 1.3em; + margin: 2px; + cursor: pointer; +} + +.emoji_button { + display: inline-block; + font-size: smaller; + padding: 0 4px 0 8px; + cursor: pointer; +} + +/* Light modifications by Eric Woodward */ + +.emoji_button { + position: absolute; + right: 0.5rem; + bottom: 0.5rem; +} + +.emoji_menu { + background: rgb(10, 10, 20, 0.6); +} + +.emoji_tab.selected { + background: rgb(27, 27, 39); +} + +.emoji_page_box { + background: rgb(27, 27, 39); +} + +.twtControls-contentInput { + padding-bottom: 2rem; +} + +.twtControls-contentLabel { + position: relative; +} diff --git a/src/emojiButton/client/emoji.js b/src/emojiButton/client/emoji.js new file mode 100644 index 0000000..14642b0 --- /dev/null +++ b/src/emojiButton/client/emoji.js @@ -0,0 +1,2160 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT +/* Copyright ยฉ 2020-2024 Jamie Zawinski + + Permission to use, copy, modify, distribute, and sell this software + and its documentation for any purpose is hereby granted without + fee, provided that the above copyright notice appear in all copies + and that both that copyright notice and this permission notice + appear in supporting documentation. No representations are made + about the suitability of this software for any purpose. It is + provided "as is" without express or implied warranty. + + Emoji popup menu. There are many like it. This one is mine. + + I would have just used one of the dozens that alread exist, but the + way people write Javascript modules and their dependencies today is + INSANE and I will have no part of it. + + To use it: + + - Add the class "emoji_target" to one or more INPUT or TEXTAREA fields. + + - Load "emoji.js" and "emoji.css". + + - It will add a smiley at the right of each of those fields, which, + when clicked, will pop up a tabbed dialog box. The selected emoji + will be inserted. + + - The "Recently Used" set is stored in LocalStorage. + + To update it with the new hotness from the latest Unicode drop: + https://www.dnalounge.com/webcast/emoji-build.pl + + Created: 24-May-2020 + Updated: 10-Jun-2024 + */ + +(function () { + var emoji_categories = [ + { name: 'recent', icon: '๐Ÿ•’', label: 'Recently Used' }, + { name: 'smilies', icon: '๐Ÿ˜€', label: 'Smileys & Emotion' }, + { name: 'people', icon: '๐Ÿง‘', label: 'People & Body' }, + { name: 'nature', icon: '๐Ÿฑ', label: 'Animals & Nature' }, + { name: 'food', icon: '๐Ÿ•', label: 'Food & Drink' }, + { name: 'activity', icon: '๐ŸŽณ', label: 'Activities' }, + { name: 'travel', icon: '๐ŸŒŽ', label: 'Travel & Places' }, + { name: 'object', icon: '๐Ÿ“€', label: 'Objects' }, + { name: 'symbol', icon: 'โš ๏ธ', label: 'Symbols' }, + { name: 'flag', icon: '๐Ÿณ๏ธโ€๐ŸŒˆ', label: 'Flags' }, + ]; + + var emoji = { + smilies: [ + '๐Ÿ˜€', + '๐Ÿ˜ƒ', + '๐Ÿ˜„', + '๐Ÿ˜', + '๐Ÿ˜†', + '๐Ÿ˜…', + '๐Ÿคฃ', + '๐Ÿ˜‚', + '๐Ÿ™‚', + '๐Ÿ™ƒ', + '๐Ÿซ ', + '๐Ÿ˜‰', + '๐Ÿ˜Š', + '๐Ÿ˜‡', + '๐Ÿฅฐ', + '๐Ÿ˜', + '๐Ÿคฉ', + '๐Ÿ˜˜', + '๐Ÿ˜—', + 'โ˜บ๏ธ', + '๐Ÿ˜š', + '๐Ÿ˜™', + '๐Ÿฅฒ', + '๐Ÿ˜‹', + '๐Ÿ˜›', + '๐Ÿ˜œ', + '๐Ÿคช', + '๐Ÿ˜', + '๐Ÿค‘', + '๐Ÿค—', + '๐Ÿคญ', + '๐Ÿซข', + '๐Ÿซฃ', + '๐Ÿคซ', + '๐Ÿค”', + '๐Ÿซก', + '๐Ÿค', + '๐Ÿคจ', + '๐Ÿ˜', + '๐Ÿ˜‘', + '๐Ÿ˜ถ', + '๐Ÿซฅ', + '๐Ÿ˜ถโ€๐ŸŒซ๏ธ', + '๐Ÿ˜', + '๐Ÿ˜’', + '๐Ÿ™„', + '๐Ÿ˜ฌ', + '๐Ÿ˜ฎโ€๐Ÿ’จ', + '๐Ÿคฅ', + '๐Ÿซจ', + '๐Ÿ™‚โ€โ†”๏ธ', + '๐Ÿ™‚โ€โ†•๏ธ', + '๐Ÿ˜Œ', + '๐Ÿ˜”', + '๐Ÿ˜ช', + '๐Ÿคค', + '๐Ÿ˜ด', + '๐Ÿ˜ท', + '๐Ÿค’', + '๐Ÿค•', + '๐Ÿคข', + '๐Ÿคฎ', + '๐Ÿคง', + '๐Ÿฅต', + '๐Ÿฅถ', + '๐Ÿฅด', + '๐Ÿ˜ต', + '๐Ÿ˜ตโ€๐Ÿ’ซ', + '๐Ÿคฏ', + '๐Ÿค ', + '๐Ÿฅณ', + '๐Ÿฅธ', + '๐Ÿ˜Ž', + '๐Ÿค“', + '๐Ÿง', + '๐Ÿ˜•', + '๐Ÿซค', + '๐Ÿ˜Ÿ', + '๐Ÿ™', + 'โ˜น๏ธ', + '๐Ÿ˜ฎ', + '๐Ÿ˜ฏ', + '๐Ÿ˜ฒ', + '๐Ÿ˜ณ', + '๐Ÿฅบ', + '๐Ÿฅน', + '๐Ÿ˜ฆ', + '๐Ÿ˜ง', + '๐Ÿ˜จ', + '๐Ÿ˜ฐ', + '๐Ÿ˜ฅ', + '๐Ÿ˜ข', + '๐Ÿ˜ญ', + '๐Ÿ˜ฑ', + '๐Ÿ˜–', + '๐Ÿ˜ฃ', + '๐Ÿ˜ž', + '๐Ÿ˜“', + '๐Ÿ˜ฉ', + '๐Ÿ˜ซ', + '๐Ÿฅฑ', + '๐Ÿ˜ค', + '๐Ÿ˜ก', + '๐Ÿ˜ ', + '๐Ÿคฌ', + '๐Ÿ˜ˆ', + '๐Ÿ‘ฟ', + '๐Ÿ’€', + 'โ˜ ๏ธ', + '๐Ÿ’ฉ', + '๐Ÿคก', + '๐Ÿ‘น', + '๐Ÿ‘บ', + '๐Ÿ‘ป', + '๐Ÿ‘ฝ', + '๐Ÿ‘พ', + '๐Ÿค–', + '๐Ÿ˜บ', + '๐Ÿ˜ธ', + '๐Ÿ˜น', + '๐Ÿ˜ป', + '๐Ÿ˜ผ', + '๐Ÿ˜ฝ', + '๐Ÿ™€', + '๐Ÿ˜ฟ', + '๐Ÿ˜พ', + '๐Ÿ™ˆ', + '๐Ÿ™‰', + '๐Ÿ™Š', + '๐Ÿ’Œ', + '๐Ÿ’˜', + '๐Ÿ’', + '๐Ÿ’–', + '๐Ÿ’—', + '๐Ÿ’“', + '๐Ÿ’ž', + '๐Ÿ’•', + '๐Ÿ’Ÿ', + 'โฃ๏ธ', + '๐Ÿ’”', + 'โค๏ธโ€๐Ÿ”ฅ', + 'โค๏ธโ€๐Ÿฉน', + 'โค๏ธ', + '๐Ÿฉท', + '๐Ÿงก', + '๐Ÿ’›', + '๐Ÿ’š', + '๐Ÿ’™', + '๐Ÿฉต', + '๐Ÿ’œ', + '๐ŸคŽ', + '๐Ÿ–ค', + '๐Ÿฉถ', + '๐Ÿค', + '๐Ÿ’‹', + '๐Ÿ’ฏ', + '๐Ÿ’ข', + '๐Ÿ’ฅ', + '๐Ÿ’ซ', + '๐Ÿ’ฆ', + '๐Ÿ’จ', + '๐Ÿ•ณ๏ธ', + '๐Ÿ’ฌ', + '๐Ÿ‘๏ธโ€๐Ÿ—จ๏ธ', + '๐Ÿ—จ๏ธ', + '๐Ÿ—ฏ๏ธ', + '๐Ÿ’ญ', + '๐Ÿ’ค', + ], + people: [ + '๐Ÿ‘‹', + '๐Ÿคš', + '๐Ÿ–๏ธ', + 'โœ‹', + '๐Ÿ––', + '๐Ÿซฑ', + '๐Ÿซฒ', + '๐Ÿซณ', + '๐Ÿซด', + '๐Ÿซท', + '๐Ÿซธ', + '๐Ÿ‘Œ', + '๐ŸคŒ', + '๐Ÿค', + 'โœŒ๏ธ', + '๐Ÿคž', + '๐Ÿซฐ', + '๐ŸคŸ', + '๐Ÿค˜', + '๐Ÿค™', + '๐Ÿ‘ˆ', + '๐Ÿ‘‰', + '๐Ÿ‘†', + '๐Ÿ–•', + '๐Ÿ‘‡', + 'โ˜๏ธ', + '๐Ÿซต', + '๐Ÿ‘', + '๐Ÿ‘Ž', + 'โœŠ', + '๐Ÿ‘Š', + '๐Ÿค›', + '๐Ÿคœ', + '๐Ÿ‘', + '๐Ÿ™Œ', + '๐Ÿซถ', + '๐Ÿ‘', + '๐Ÿคฒ', + '๐Ÿค', + '๐Ÿ™', + 'โœ๏ธ', + '๐Ÿ’…', + '๐Ÿคณ', + '๐Ÿ’ช', + '๐Ÿฆพ', + '๐Ÿฆฟ', + '๐Ÿฆต', + '๐Ÿฆถ', + '๐Ÿ‘‚', + '๐Ÿฆป', + '๐Ÿ‘ƒ', + '๐Ÿง ', + '๐Ÿซ€', + '๐Ÿซ', + '๐Ÿฆท', + '๐Ÿฆด', + '๐Ÿ‘€', + '๐Ÿ‘๏ธ', + '๐Ÿ‘…', + '๐Ÿ‘„', + '๐Ÿซฆ', + '๐Ÿ‘ถ', + '๐Ÿง’', + '๐Ÿ‘ฆ', + '๐Ÿ‘ง', + '๐Ÿง‘', + '๐Ÿ‘ฑ', + '๐Ÿ‘จ', + '๐Ÿง”', + '๐Ÿง”โ€โ™‚๏ธ', + '๐Ÿง”โ€โ™€๏ธ', + '๐Ÿ‘จโ€๐Ÿฆฐ', + '๐Ÿ‘จโ€๐Ÿฆฑ', + '๐Ÿ‘จโ€๐Ÿฆณ', + '๐Ÿ‘จโ€๐Ÿฆฒ', + '๐Ÿ‘ฉ', + '๐Ÿ‘ฉโ€๐Ÿฆฐ', + '๐Ÿง‘โ€๐Ÿฆฐ', + '๐Ÿ‘ฉโ€๐Ÿฆฑ', + '๐Ÿง‘โ€๐Ÿฆฑ', + '๐Ÿ‘ฉโ€๐Ÿฆณ', + '๐Ÿง‘โ€๐Ÿฆณ', + '๐Ÿ‘ฉโ€๐Ÿฆฒ', + '๐Ÿง‘โ€๐Ÿฆฒ', + '๐Ÿ‘ฑโ€โ™€๏ธ', + '๐Ÿ‘ฑโ€โ™‚๏ธ', + '๐Ÿง“', + '๐Ÿ‘ด', + '๐Ÿ‘ต', + '๐Ÿ™', + '๐Ÿ™โ€โ™‚๏ธ', + '๐Ÿ™โ€โ™€๏ธ', + '๐Ÿ™Ž', + '๐Ÿ™Žโ€โ™‚๏ธ', + '๐Ÿ™Žโ€โ™€๏ธ', + '๐Ÿ™…', + '๐Ÿ™…โ€โ™‚๏ธ', + '๐Ÿ™…โ€โ™€๏ธ', + '๐Ÿ™†', + '๐Ÿ™†โ€โ™‚๏ธ', + '๐Ÿ™†โ€โ™€๏ธ', + '๐Ÿ’', + '๐Ÿ’โ€โ™‚๏ธ', + '๐Ÿ’โ€โ™€๏ธ', + '๐Ÿ™‹', + '๐Ÿ™‹โ€โ™‚๏ธ', + '๐Ÿ™‹โ€โ™€๏ธ', + '๐Ÿง', + '๐Ÿงโ€โ™‚๏ธ', + '๐Ÿงโ€โ™€๏ธ', + '๐Ÿ™‡', + '๐Ÿ™‡โ€โ™‚๏ธ', + '๐Ÿ™‡โ€โ™€๏ธ', + '๐Ÿคฆ', + '๐Ÿคฆโ€โ™‚๏ธ', + '๐Ÿคฆโ€โ™€๏ธ', + '๐Ÿคท', + '๐Ÿคทโ€โ™‚๏ธ', + '๐Ÿคทโ€โ™€๏ธ', + '๐Ÿง‘โ€โš•๏ธ', + '๐Ÿ‘จโ€โš•๏ธ', + '๐Ÿ‘ฉโ€โš•๏ธ', + '๐Ÿง‘โ€๐ŸŽ“', + '๐Ÿ‘จโ€๐ŸŽ“', + '๐Ÿ‘ฉโ€๐ŸŽ“', + '๐Ÿง‘โ€๐Ÿซ', + '๐Ÿ‘จโ€๐Ÿซ', + '๐Ÿ‘ฉโ€๐Ÿซ', + '๐Ÿง‘โ€โš–๏ธ', + '๐Ÿ‘จโ€โš–๏ธ', + '๐Ÿ‘ฉโ€โš–๏ธ', + '๐Ÿง‘โ€๐ŸŒพ', + '๐Ÿ‘จโ€๐ŸŒพ', + '๐Ÿ‘ฉโ€๐ŸŒพ', + '๐Ÿง‘โ€๐Ÿณ', + '๐Ÿ‘จโ€๐Ÿณ', + '๐Ÿ‘ฉโ€๐Ÿณ', + '๐Ÿง‘โ€๐Ÿ”ง', + '๐Ÿ‘จโ€๐Ÿ”ง', + '๐Ÿ‘ฉโ€๐Ÿ”ง', + '๐Ÿง‘โ€๐Ÿญ', + '๐Ÿ‘จโ€๐Ÿญ', + '๐Ÿ‘ฉโ€๐Ÿญ', + '๐Ÿง‘โ€๐Ÿ’ผ', + '๐Ÿ‘จโ€๐Ÿ’ผ', + '๐Ÿ‘ฉโ€๐Ÿ’ผ', + '๐Ÿง‘โ€๐Ÿ”ฌ', + '๐Ÿ‘จโ€๐Ÿ”ฌ', + '๐Ÿ‘ฉโ€๐Ÿ”ฌ', + '๐Ÿง‘โ€๐Ÿ’ป', + '๐Ÿ‘จโ€๐Ÿ’ป', + '๐Ÿ‘ฉโ€๐Ÿ’ป', + '๐Ÿง‘โ€๐ŸŽค', + '๐Ÿ‘จโ€๐ŸŽค', + '๐Ÿ‘ฉโ€๐ŸŽค', + '๐Ÿง‘โ€๐ŸŽจ', + '๐Ÿ‘จโ€๐ŸŽจ', + '๐Ÿ‘ฉโ€๐ŸŽจ', + '๐Ÿง‘โ€โœˆ๏ธ', + '๐Ÿ‘จโ€โœˆ๏ธ', + '๐Ÿ‘ฉโ€โœˆ๏ธ', + '๐Ÿง‘โ€๐Ÿš€', + '๐Ÿ‘จโ€๐Ÿš€', + '๐Ÿ‘ฉโ€๐Ÿš€', + '๐Ÿง‘โ€๐Ÿš’', + '๐Ÿ‘จโ€๐Ÿš’', + '๐Ÿ‘ฉโ€๐Ÿš’', + '๐Ÿ‘ฎ', + '๐Ÿ‘ฎโ€โ™‚๏ธ', + '๐Ÿ‘ฎโ€โ™€๏ธ', + '๐Ÿ•ต๏ธ', + '๐Ÿ•ต๏ธโ€โ™‚๏ธ', + '๐Ÿ•ต๏ธโ€โ™€๏ธ', + '๐Ÿ’‚', + '๐Ÿ’‚โ€โ™‚๏ธ', + '๐Ÿ’‚โ€โ™€๏ธ', + '๐Ÿฅท', + '๐Ÿ‘ท', + '๐Ÿ‘ทโ€โ™‚๏ธ', + '๐Ÿ‘ทโ€โ™€๏ธ', + '๐Ÿซ…', + '๐Ÿคด', + '๐Ÿ‘ธ', + '๐Ÿ‘ณ', + '๐Ÿ‘ณโ€โ™‚๏ธ', + '๐Ÿ‘ณโ€โ™€๏ธ', + '๐Ÿ‘ฒ', + '๐Ÿง•', + '๐Ÿคต', + '๐Ÿคตโ€โ™‚๏ธ', + '๐Ÿคตโ€โ™€๏ธ', + '๐Ÿ‘ฐ', + '๐Ÿ‘ฐโ€โ™‚๏ธ', + '๐Ÿ‘ฐโ€โ™€๏ธ', + '๐Ÿคฐ', + '๐Ÿซƒ', + '๐Ÿซ„', + '๐Ÿคฑ', + '๐Ÿ‘ฉโ€๐Ÿผ', + '๐Ÿ‘จโ€๐Ÿผ', + '๐Ÿง‘โ€๐Ÿผ', + '๐Ÿ‘ผ', + '๐ŸŽ…', + '๐Ÿคถ', + '๐Ÿง‘โ€๐ŸŽ„', + '๐Ÿฆธ', + '๐Ÿฆธโ€โ™‚๏ธ', + '๐Ÿฆธโ€โ™€๏ธ', + '๐Ÿฆน', + '๐Ÿฆนโ€โ™‚๏ธ', + '๐Ÿฆนโ€โ™€๏ธ', + '๐Ÿง™', + '๐Ÿง™โ€โ™‚๏ธ', + '๐Ÿง™โ€โ™€๏ธ', + '๐Ÿงš', + '๐Ÿงšโ€โ™‚๏ธ', + '๐Ÿงšโ€โ™€๏ธ', + '๐Ÿง›', + '๐Ÿง›โ€โ™‚๏ธ', + '๐Ÿง›โ€โ™€๏ธ', + '๐Ÿงœ', + '๐Ÿงœโ€โ™‚๏ธ', + '๐Ÿงœโ€โ™€๏ธ', + '๐Ÿง', + '๐Ÿงโ€โ™‚๏ธ', + '๐Ÿงโ€โ™€๏ธ', + '๐Ÿงž', + '๐Ÿงžโ€โ™‚๏ธ', + '๐Ÿงžโ€โ™€๏ธ', + '๐ŸงŸ', + '๐ŸงŸโ€โ™‚๏ธ', + '๐ŸงŸโ€โ™€๏ธ', + '๐ŸงŒ', + '๐Ÿ’†', + '๐Ÿ’†โ€โ™‚๏ธ', + '๐Ÿ’†โ€โ™€๏ธ', + '๐Ÿ’‡', + '๐Ÿ’‡โ€โ™‚๏ธ', + '๐Ÿ’‡โ€โ™€๏ธ', + '๐Ÿšถ', + '๐Ÿšถโ€โ™‚๏ธ', + '๐Ÿšถโ€โ™€๏ธ', + '๐Ÿšถโ€โžก๏ธ', + '๐Ÿšถโ€โ™€๏ธโ€โžก๏ธ', + '๐Ÿšถโ€โ™‚๏ธโ€โžก๏ธ', + '๐Ÿง', + '๐Ÿงโ€โ™‚๏ธ', + '๐Ÿงโ€โ™€๏ธ', + '๐ŸงŽ', + '๐ŸงŽโ€โ™‚๏ธ', + '๐ŸงŽโ€โ™€๏ธ', + '๐ŸงŽโ€โžก๏ธ', + '๐ŸงŽโ€โ™€๏ธโ€โžก๏ธ', + '๐ŸงŽโ€โ™‚๏ธโ€โžก๏ธ', + '๐Ÿง‘โ€๐Ÿฆฏ', + '๐Ÿง‘โ€๐Ÿฆฏโ€โžก๏ธ', + '๐Ÿ‘จโ€๐Ÿฆฏ', + '๐Ÿ‘จโ€๐Ÿฆฏโ€โžก๏ธ', + '๐Ÿ‘ฉโ€๐Ÿฆฏ', + '๐Ÿ‘ฉโ€๐Ÿฆฏโ€โžก๏ธ', + '๐Ÿง‘โ€๐Ÿฆผ', + '๐Ÿง‘โ€๐Ÿฆผโ€โžก๏ธ', + '๐Ÿ‘จโ€๐Ÿฆผ', + '๐Ÿ‘จโ€๐Ÿฆผโ€โžก๏ธ', + '๐Ÿ‘ฉโ€๐Ÿฆผ', + '๐Ÿ‘ฉโ€๐Ÿฆผโ€โžก๏ธ', + '๐Ÿง‘โ€๐Ÿฆฝ', + '๐Ÿง‘โ€๐Ÿฆฝโ€โžก๏ธ', + '๐Ÿ‘จโ€๐Ÿฆฝ', + '๐Ÿ‘จโ€๐Ÿฆฝโ€โžก๏ธ', + '๐Ÿ‘ฉโ€๐Ÿฆฝ', + '๐Ÿ‘ฉโ€๐Ÿฆฝโ€โžก๏ธ', + '๐Ÿƒ', + '๐Ÿƒโ€โ™‚๏ธ', + '๐Ÿƒโ€โ™€๏ธ', + '๐Ÿƒโ€โžก๏ธ', + '๐Ÿƒโ€โ™€๏ธโ€โžก๏ธ', + '๐Ÿƒโ€โ™‚๏ธโ€โžก๏ธ', + '๐Ÿ’ƒ', + '๐Ÿ•บ', + '๐Ÿ•ด๏ธ', + '๐Ÿ‘ฏ', + '๐Ÿ‘ฏโ€โ™‚๏ธ', + '๐Ÿ‘ฏโ€โ™€๏ธ', + '๐Ÿง–', + '๐Ÿง–โ€โ™‚๏ธ', + '๐Ÿง–โ€โ™€๏ธ', + '๐Ÿง—', + '๐Ÿง—โ€โ™‚๏ธ', + '๐Ÿง—โ€โ™€๏ธ', + '๐Ÿคบ', + '๐Ÿ‡', + 'โ›ท๏ธ', + '๐Ÿ‚', + '๐ŸŒ๏ธ', + '๐ŸŒ๏ธโ€โ™‚๏ธ', + '๐ŸŒ๏ธโ€โ™€๏ธ', + '๐Ÿ„', + '๐Ÿ„โ€โ™‚๏ธ', + '๐Ÿ„โ€โ™€๏ธ', + '๐Ÿšฃ', + '๐Ÿšฃโ€โ™‚๏ธ', + '๐Ÿšฃโ€โ™€๏ธ', + '๐ŸŠ', + '๐ŸŠโ€โ™‚๏ธ', + '๐ŸŠโ€โ™€๏ธ', + 'โ›น๏ธ', + 'โ›น๏ธโ€โ™‚๏ธ', + 'โ›น๏ธโ€โ™€๏ธ', + '๐Ÿ‹๏ธ', + '๐Ÿ‹๏ธโ€โ™‚๏ธ', + '๐Ÿ‹๏ธโ€โ™€๏ธ', + '๐Ÿšด', + '๐Ÿšดโ€โ™‚๏ธ', + '๐Ÿšดโ€โ™€๏ธ', + '๐Ÿšต', + '๐Ÿšตโ€โ™‚๏ธ', + '๐Ÿšตโ€โ™€๏ธ', + '๐Ÿคธ', + '๐Ÿคธโ€โ™‚๏ธ', + '๐Ÿคธโ€โ™€๏ธ', + '๐Ÿคผ', + '๐Ÿคผโ€โ™‚๏ธ', + '๐Ÿคผโ€โ™€๏ธ', + '๐Ÿคฝ', + '๐Ÿคฝโ€โ™‚๏ธ', + '๐Ÿคฝโ€โ™€๏ธ', + '๐Ÿคพ', + '๐Ÿคพโ€โ™‚๏ธ', + '๐Ÿคพโ€โ™€๏ธ', + '๐Ÿคน', + '๐Ÿคนโ€โ™‚๏ธ', + '๐Ÿคนโ€โ™€๏ธ', + '๐Ÿง˜', + '๐Ÿง˜โ€โ™‚๏ธ', + '๐Ÿง˜โ€โ™€๏ธ', + '๐Ÿ›€', + '๐Ÿ›Œ', + '๐Ÿง‘โ€๐Ÿคโ€๐Ÿง‘', + '๐Ÿ‘ญ', + '๐Ÿ‘ซ', + '๐Ÿ‘ฌ', + '๐Ÿ’', + '๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ', + '๐Ÿ‘จโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘จ', + '๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ’‹โ€๐Ÿ‘ฉ', + '๐Ÿ’‘', + '๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘จ', + '๐Ÿ‘จโ€โค๏ธโ€๐Ÿ‘จ', + '๐Ÿ‘ฉโ€โค๏ธโ€๐Ÿ‘ฉ', + '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ง', + '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', + '๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ง', + '๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง', + '๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ง', + '๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', + '๐Ÿ‘จโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘ง', + '๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', + '๐Ÿ‘จโ€๐Ÿ‘งโ€๐Ÿ‘ง', + '๐Ÿ‘ฉโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘ฆโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘ง', + '๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ฆ', + '๐Ÿ‘ฉโ€๐Ÿ‘งโ€๐Ÿ‘ง', + '๐Ÿ—ฃ๏ธ', + '๐Ÿ‘ค', + '๐Ÿ‘ฅ', + '๐Ÿซ‚', + '๐Ÿ‘ช', + '๐Ÿง‘โ€๐Ÿง‘โ€๐Ÿง’', + '๐Ÿง‘โ€๐Ÿง‘โ€๐Ÿง’โ€๐Ÿง’', + '๐Ÿง‘โ€๐Ÿง’', + '๐Ÿง‘โ€๐Ÿง’โ€๐Ÿง’', + '๐Ÿ‘ฃ', + ], + nature: [ + '๐Ÿต', + '๐Ÿ’', + '๐Ÿฆ', + '๐Ÿฆง', + '๐Ÿถ', + '๐Ÿ•', + '๐Ÿฆฎ', + '๐Ÿ•โ€๐Ÿฆบ', + '๐Ÿฉ', + '๐Ÿบ', + '๐ŸฆŠ', + '๐Ÿฆ', + '๐Ÿฑ', + '๐Ÿˆ', + '๐Ÿˆโ€โฌ›', + '๐Ÿฆ', + '๐Ÿฏ', + '๐Ÿ…', + '๐Ÿ†', + '๐Ÿด', + '๐ŸซŽ', + '๐Ÿซ', + '๐ŸŽ', + '๐Ÿฆ„', + '๐Ÿฆ“', + '๐ŸฆŒ', + '๐Ÿฆฌ', + '๐Ÿฎ', + '๐Ÿ‚', + '๐Ÿƒ', + '๐Ÿ„', + '๐Ÿท', + '๐Ÿ–', + '๐Ÿ—', + '๐Ÿฝ', + '๐Ÿ', + '๐Ÿ‘', + '๐Ÿ', + '๐Ÿช', + '๐Ÿซ', + '๐Ÿฆ™', + '๐Ÿฆ’', + '๐Ÿ˜', + '๐Ÿฆฃ', + '๐Ÿฆ', + '๐Ÿฆ›', + '๐Ÿญ', + '๐Ÿ', + '๐Ÿ€', + '๐Ÿน', + '๐Ÿฐ', + '๐Ÿ‡', + '๐Ÿฟ๏ธ', + '๐Ÿฆซ', + '๐Ÿฆ”', + '๐Ÿฆ‡', + '๐Ÿป', + '๐Ÿปโ€โ„๏ธ', + '๐Ÿจ', + '๐Ÿผ', + '๐Ÿฆฅ', + '๐Ÿฆฆ', + '๐Ÿฆจ', + '๐Ÿฆ˜', + '๐Ÿฆก', + '๐Ÿพ', + '๐Ÿฆƒ', + '๐Ÿ”', + '๐Ÿ“', + '๐Ÿฃ', + '๐Ÿค', + '๐Ÿฅ', + '๐Ÿฆ', + '๐Ÿง', + '๐Ÿ•Š๏ธ', + '๐Ÿฆ…', + '๐Ÿฆ†', + '๐Ÿฆข', + '๐Ÿฆ‰', + '๐Ÿฆค', + '๐Ÿชถ', + '๐Ÿฆฉ', + '๐Ÿฆš', + '๐Ÿฆœ', + '๐Ÿชฝ', + '๐Ÿฆโ€โฌ›', + '๐Ÿชฟ', + '๐Ÿฆโ€๐Ÿ”ฅ', + '๐Ÿธ', + '๐ŸŠ', + '๐Ÿข', + '๐ŸฆŽ', + '๐Ÿ', + '๐Ÿฒ', + '๐Ÿ‰', + '๐Ÿฆ•', + '๐Ÿฆ–', + '๐Ÿณ', + '๐Ÿ‹', + '๐Ÿฌ', + '๐Ÿฆญ', + '๐ŸŸ', + '๐Ÿ ', + '๐Ÿก', + '๐Ÿฆˆ', + '๐Ÿ™', + '๐Ÿš', + '๐Ÿชธ', + '๐Ÿชผ', + '๐ŸŒ', + '๐Ÿฆ‹', + '๐Ÿ›', + '๐Ÿœ', + '๐Ÿ', + '๐Ÿชฒ', + '๐Ÿž', + '๐Ÿฆ—', + '๐Ÿชณ', + '๐Ÿ•ท๏ธ', + '๐Ÿ•ธ๏ธ', + '๐Ÿฆ‚', + '๐ŸฆŸ', + '๐Ÿชฐ', + '๐Ÿชฑ', + '๐Ÿฆ ', + '๐Ÿ’', + '๐ŸŒธ', + '๐Ÿ’ฎ', + '๐Ÿชท', + '๐Ÿต๏ธ', + '๐ŸŒน', + '๐Ÿฅ€', + '๐ŸŒบ', + '๐ŸŒป', + '๐ŸŒผ', + '๐ŸŒท', + '๐Ÿชป', + '๐ŸŒฑ', + '๐Ÿชด', + '๐ŸŒฒ', + '๐ŸŒณ', + '๐ŸŒด', + '๐ŸŒต', + '๐ŸŒพ', + '๐ŸŒฟ', + 'โ˜˜๏ธ', + '๐Ÿ€', + '๐Ÿ', + '๐Ÿ‚', + '๐Ÿƒ', + '๐Ÿชน', + '๐Ÿชบ', + '๐Ÿ„', + ], + food: [ + '๐Ÿ‡', + '๐Ÿˆ', + '๐Ÿ‰', + '๐ŸŠ', + '๐Ÿ‹', + '๐Ÿ‹โ€๐ŸŸฉ', + '๐ŸŒ', + '๐Ÿ', + '๐Ÿฅญ', + '๐ŸŽ', + '๐Ÿ', + '๐Ÿ', + '๐Ÿ‘', + '๐Ÿ’', + '๐Ÿ“', + '๐Ÿซ', + '๐Ÿฅ', + '๐Ÿ…', + '๐Ÿซ’', + '๐Ÿฅฅ', + '๐Ÿฅ‘', + '๐Ÿ†', + '๐Ÿฅ”', + '๐Ÿฅ•', + '๐ŸŒฝ', + '๐ŸŒถ๏ธ', + '๐Ÿซ‘', + '๐Ÿฅ’', + '๐Ÿฅฌ', + '๐Ÿฅฆ', + '๐Ÿง„', + '๐Ÿง…', + '๐Ÿฅœ', + '๐Ÿซ˜', + '๐ŸŒฐ', + '๐Ÿซš', + '๐Ÿซ›', + '๐Ÿ„โ€๐ŸŸซ', + '๐Ÿž', + '๐Ÿฅ', + '๐Ÿฅ–', + '๐Ÿซ“', + '๐Ÿฅจ', + '๐Ÿฅฏ', + '๐Ÿฅž', + '๐Ÿง‡', + '๐Ÿง€', + '๐Ÿ–', + '๐Ÿ—', + '๐Ÿฅฉ', + '๐Ÿฅ“', + '๐Ÿ”', + '๐ŸŸ', + '๐Ÿ•', + '๐ŸŒญ', + '๐Ÿฅช', + '๐ŸŒฎ', + '๐ŸŒฏ', + '๐Ÿซ”', + '๐Ÿฅ™', + '๐Ÿง†', + '๐Ÿฅš', + '๐Ÿณ', + '๐Ÿฅ˜', + '๐Ÿฒ', + '๐Ÿซ•', + '๐Ÿฅฃ', + '๐Ÿฅ—', + '๐Ÿฟ', + '๐Ÿงˆ', + '๐Ÿง‚', + '๐Ÿฅซ', + '๐Ÿฑ', + '๐Ÿ˜', + '๐Ÿ™', + '๐Ÿš', + '๐Ÿ›', + '๐Ÿœ', + '๐Ÿ', + '๐Ÿ ', + '๐Ÿข', + '๐Ÿฃ', + '๐Ÿค', + '๐Ÿฅ', + '๐Ÿฅฎ', + '๐Ÿก', + '๐ŸฅŸ', + '๐Ÿฅ ', + '๐Ÿฅก', + '๐Ÿฆ€', + '๐Ÿฆž', + '๐Ÿฆ', + '๐Ÿฆ‘', + '๐Ÿฆช', + '๐Ÿฆ', + '๐Ÿง', + '๐Ÿจ', + '๐Ÿฉ', + '๐Ÿช', + '๐ŸŽ‚', + '๐Ÿฐ', + '๐Ÿง', + '๐Ÿฅง', + '๐Ÿซ', + '๐Ÿฌ', + '๐Ÿญ', + '๐Ÿฎ', + '๐Ÿฏ', + '๐Ÿผ', + '๐Ÿฅ›', + 'โ˜•', + '๐Ÿซ–', + '๐Ÿต', + '๐Ÿถ', + '๐Ÿพ', + '๐Ÿท', + '๐Ÿธ', + '๐Ÿน', + '๐Ÿบ', + '๐Ÿป', + '๐Ÿฅ‚', + '๐Ÿฅƒ', + '๐Ÿซ—', + '๐Ÿฅค', + '๐Ÿง‹', + '๐Ÿงƒ', + '๐Ÿง‰', + '๐ŸงŠ', + '๐Ÿฅข', + '๐Ÿฝ๏ธ', + '๐Ÿด', + '๐Ÿฅ„', + '๐Ÿ”ช', + '๐Ÿซ™', + '๐Ÿบ', + ], + activity: [ + '๐ŸŽƒ', + '๐ŸŽ„', + '๐ŸŽ†', + '๐ŸŽ‡', + '๐Ÿงจ', + 'โœจ', + '๐ŸŽˆ', + '๐ŸŽ‰', + '๐ŸŽŠ', + '๐ŸŽ‹', + '๐ŸŽ', + '๐ŸŽŽ', + '๐ŸŽ', + '๐ŸŽ', + '๐ŸŽ‘', + '๐Ÿงง', + '๐ŸŽ€', + '๐ŸŽ', + '๐ŸŽ—๏ธ', + '๐ŸŽŸ๏ธ', + '๐ŸŽซ', + '๐ŸŽ–๏ธ', + '๐Ÿ†', + '๐Ÿ…', + '๐Ÿฅ‡', + '๐Ÿฅˆ', + '๐Ÿฅ‰', + 'โšฝ', + 'โšพ', + '๐ŸฅŽ', + '๐Ÿ€', + '๐Ÿ', + '๐Ÿˆ', + '๐Ÿ‰', + '๐ŸŽพ', + '๐Ÿฅ', + '๐ŸŽณ', + '๐Ÿ', + '๐Ÿ‘', + '๐Ÿ’', + '๐Ÿฅ', + '๐Ÿ“', + '๐Ÿธ', + '๐ŸฅŠ', + '๐Ÿฅ‹', + '๐Ÿฅ…', + 'โ›ณ', + 'โ›ธ๏ธ', + '๐ŸŽฃ', + '๐Ÿคฟ', + '๐ŸŽฝ', + '๐ŸŽฟ', + '๐Ÿ›ท', + '๐ŸฅŒ', + '๐ŸŽฏ', + '๐Ÿช€', + '๐Ÿช', + '๐Ÿ”ซ', + '๐ŸŽฑ', + '๐Ÿ”ฎ', + '๐Ÿช„', + '๐ŸŽฎ', + '๐Ÿ•น๏ธ', + '๐ŸŽฐ', + '๐ŸŽฒ', + '๐Ÿงฉ', + '๐Ÿงธ', + '๐Ÿช…', + '๐Ÿชฉ', + '๐Ÿช†', + 'โ™ ๏ธ', + 'โ™ฅ๏ธ', + 'โ™ฆ๏ธ', + 'โ™ฃ๏ธ', + 'โ™Ÿ๏ธ', + '๐Ÿƒ', + '๐Ÿ€„', + '๐ŸŽด', + '๐ŸŽญ', + '๐Ÿ–ผ๏ธ', + '๐ŸŽจ', + '๐Ÿงต', + '๐Ÿชก', + '๐Ÿงถ', + '๐Ÿชข', + ], + travel: [ + '๐ŸŒ', + '๐ŸŒŽ', + '๐ŸŒ', + '๐ŸŒ', + '๐Ÿ—บ๏ธ', + '๐Ÿ—พ', + '๐Ÿงญ', + '๐Ÿ”๏ธ', + 'โ›ฐ๏ธ', + '๐ŸŒ‹', + '๐Ÿ—ป', + '๐Ÿ•๏ธ', + '๐Ÿ–๏ธ', + '๐Ÿœ๏ธ', + '๐Ÿ๏ธ', + '๐Ÿž๏ธ', + '๐ŸŸ๏ธ', + '๐Ÿ›๏ธ', + '๐Ÿ—๏ธ', + '๐Ÿงฑ', + '๐Ÿชจ', + '๐Ÿชต', + '๐Ÿ›–', + '๐Ÿ˜๏ธ', + '๐Ÿš๏ธ', + '๐Ÿ ', + '๐Ÿก', + '๐Ÿข', + '๐Ÿฃ', + '๐Ÿค', + '๐Ÿฅ', + '๐Ÿฆ', + '๐Ÿจ', + '๐Ÿฉ', + '๐Ÿช', + '๐Ÿซ', + '๐Ÿฌ', + '๐Ÿญ', + '๐Ÿฏ', + '๐Ÿฐ', + '๐Ÿ’’', + '๐Ÿ—ผ', + '๐Ÿ—ฝ', + 'โ›ช', + '๐Ÿ•Œ', + '๐Ÿ›•', + '๐Ÿ•', + 'โ›ฉ๏ธ', + '๐Ÿ•‹', + 'โ›ฒ', + 'โ›บ', + '๐ŸŒ', + '๐ŸŒƒ', + '๐Ÿ™๏ธ', + '๐ŸŒ„', + '๐ŸŒ…', + '๐ŸŒ†', + '๐ŸŒ‡', + '๐ŸŒ‰', + 'โ™จ๏ธ', + '๐ŸŽ ', + '๐Ÿ›', + '๐ŸŽก', + '๐ŸŽข', + '๐Ÿ’ˆ', + '๐ŸŽช', + '๐Ÿš‚', + '๐Ÿšƒ', + '๐Ÿš„', + '๐Ÿš…', + '๐Ÿš†', + '๐Ÿš‡', + '๐Ÿšˆ', + '๐Ÿš‰', + '๐ŸšŠ', + '๐Ÿš', + '๐Ÿšž', + '๐Ÿš‹', + '๐ŸšŒ', + '๐Ÿš', + '๐ŸšŽ', + '๐Ÿš', + '๐Ÿš‘', + '๐Ÿš’', + '๐Ÿš“', + '๐Ÿš”', + '๐Ÿš•', + '๐Ÿš–', + '๐Ÿš—', + '๐Ÿš˜', + '๐Ÿš™', + '๐Ÿ›ป', + '๐Ÿšš', + '๐Ÿš›', + '๐Ÿšœ', + '๐ŸŽ๏ธ', + '๐Ÿ๏ธ', + '๐Ÿ›ต', + '๐Ÿฆฝ', + '๐Ÿฆผ', + '๐Ÿ›บ', + '๐Ÿšฒ', + '๐Ÿ›ด', + '๐Ÿ›น', + '๐Ÿ›ผ', + '๐Ÿš', + '๐Ÿ›ฃ๏ธ', + '๐Ÿ›ค๏ธ', + '๐Ÿ›ข๏ธ', + 'โ›ฝ', + '๐Ÿ›ž', + '๐Ÿšจ', + '๐Ÿšฅ', + '๐Ÿšฆ', + '๐Ÿ›‘', + '๐Ÿšง', + 'โš“', + '๐Ÿ›Ÿ', + 'โ›ต', + '๐Ÿ›ถ', + '๐Ÿšค', + '๐Ÿ›ณ๏ธ', + 'โ›ด๏ธ', + '๐Ÿ›ฅ๏ธ', + '๐Ÿšข', + 'โœˆ๏ธ', + '๐Ÿ›ฉ๏ธ', + '๐Ÿ›ซ', + '๐Ÿ›ฌ', + '๐Ÿช‚', + '๐Ÿ’บ', + '๐Ÿš', + '๐ŸšŸ', + '๐Ÿš ', + '๐Ÿšก', + '๐Ÿ›ฐ๏ธ', + '๐Ÿš€', + '๐Ÿ›ธ', + '๐Ÿ›Ž๏ธ', + '๐Ÿงณ', + 'โŒ›', + 'โณ', + 'โŒš', + 'โฐ', + 'โฑ๏ธ', + 'โฒ๏ธ', + '๐Ÿ•ฐ๏ธ', + '๐Ÿ•›', + '๐Ÿ•ง', + '๐Ÿ•', + '๐Ÿ•œ', + '๐Ÿ•‘', + '๐Ÿ•', + '๐Ÿ•’', + '๐Ÿ•ž', + '๐Ÿ•“', + '๐Ÿ•Ÿ', + '๐Ÿ•”', + '๐Ÿ• ', + '๐Ÿ••', + '๐Ÿ•ก', + '๐Ÿ•–', + '๐Ÿ•ข', + '๐Ÿ•—', + '๐Ÿ•ฃ', + '๐Ÿ•˜', + '๐Ÿ•ค', + '๐Ÿ•™', + '๐Ÿ•ฅ', + '๐Ÿ•š', + '๐Ÿ•ฆ', + '๐ŸŒ‘', + '๐ŸŒ’', + '๐ŸŒ“', + '๐ŸŒ”', + '๐ŸŒ•', + '๐ŸŒ–', + '๐ŸŒ—', + '๐ŸŒ˜', + '๐ŸŒ™', + '๐ŸŒš', + '๐ŸŒ›', + '๐ŸŒœ', + '๐ŸŒก๏ธ', + 'โ˜€๏ธ', + '๐ŸŒ', + '๐ŸŒž', + '๐Ÿช', + 'โญ', + '๐ŸŒŸ', + '๐ŸŒ ', + '๐ŸŒŒ', + 'โ˜๏ธ', + 'โ›…', + 'โ›ˆ๏ธ', + '๐ŸŒค๏ธ', + '๐ŸŒฅ๏ธ', + '๐ŸŒฆ๏ธ', + '๐ŸŒง๏ธ', + '๐ŸŒจ๏ธ', + '๐ŸŒฉ๏ธ', + '๐ŸŒช๏ธ', + '๐ŸŒซ๏ธ', + '๐ŸŒฌ๏ธ', + '๐ŸŒ€', + '๐ŸŒˆ', + '๐ŸŒ‚', + 'โ˜‚๏ธ', + 'โ˜”', + 'โ›ฑ๏ธ', + 'โšก', + 'โ„๏ธ', + 'โ˜ƒ๏ธ', + 'โ›„', + 'โ˜„๏ธ', + '๐Ÿ”ฅ', + '๐Ÿ’ง', + '๐ŸŒŠ', + ], + object: [ + '๐Ÿ‘“', + '๐Ÿ•ถ๏ธ', + '๐Ÿฅฝ', + '๐Ÿฅผ', + '๐Ÿฆบ', + '๐Ÿ‘”', + '๐Ÿ‘•', + '๐Ÿ‘–', + '๐Ÿงฃ', + '๐Ÿงค', + '๐Ÿงฅ', + '๐Ÿงฆ', + '๐Ÿ‘—', + '๐Ÿ‘˜', + '๐Ÿฅป', + '๐Ÿฉฑ', + '๐Ÿฉฒ', + '๐Ÿฉณ', + '๐Ÿ‘™', + '๐Ÿ‘š', + '๐Ÿชญ', + '๐Ÿ‘›', + '๐Ÿ‘œ', + '๐Ÿ‘', + '๐Ÿ›๏ธ', + '๐ŸŽ’', + '๐Ÿฉด', + '๐Ÿ‘ž', + '๐Ÿ‘Ÿ', + '๐Ÿฅพ', + '๐Ÿฅฟ', + '๐Ÿ‘ ', + '๐Ÿ‘ก', + '๐Ÿฉฐ', + '๐Ÿ‘ข', + '๐Ÿชฎ', + '๐Ÿ‘‘', + '๐Ÿ‘’', + '๐ŸŽฉ', + '๐ŸŽ“', + '๐Ÿงข', + '๐Ÿช–', + 'โ›‘๏ธ', + '๐Ÿ“ฟ', + '๐Ÿ’„', + '๐Ÿ’', + '๐Ÿ’Ž', + '๐Ÿ”‡', + '๐Ÿ”ˆ', + '๐Ÿ”‰', + '๐Ÿ”Š', + '๐Ÿ“ข', + '๐Ÿ“ฃ', + '๐Ÿ“ฏ', + '๐Ÿ””', + '๐Ÿ”•', + '๐ŸŽผ', + '๐ŸŽต', + '๐ŸŽถ', + '๐ŸŽ™๏ธ', + '๐ŸŽš๏ธ', + '๐ŸŽ›๏ธ', + '๐ŸŽค', + '๐ŸŽง', + '๐Ÿ“ป', + '๐ŸŽท', + '๐Ÿช—', + '๐ŸŽธ', + '๐ŸŽน', + '๐ŸŽบ', + '๐ŸŽป', + '๐Ÿช•', + '๐Ÿฅ', + '๐Ÿช˜', + '๐Ÿช‡', + '๐Ÿชˆ', + '๐Ÿ“ฑ', + '๐Ÿ“ฒ', + 'โ˜Ž๏ธ', + '๐Ÿ“ž', + '๐Ÿ“Ÿ', + '๐Ÿ“ ', + '๐Ÿ”‹', + '๐Ÿชซ', + '๐Ÿ”Œ', + '๐Ÿ’ป', + '๐Ÿ–ฅ๏ธ', + '๐Ÿ–จ๏ธ', + 'โŒจ๏ธ', + '๐Ÿ–ฑ๏ธ', + '๐Ÿ–ฒ๏ธ', + '๐Ÿ’ฝ', + '๐Ÿ’พ', + '๐Ÿ’ฟ', + '๐Ÿ“€', + '๐Ÿงฎ', + '๐ŸŽฅ', + '๐ŸŽž๏ธ', + '๐Ÿ“ฝ๏ธ', + '๐ŸŽฌ', + '๐Ÿ“บ', + '๐Ÿ“ท', + '๐Ÿ“ธ', + '๐Ÿ“น', + '๐Ÿ“ผ', + '๐Ÿ”', + '๐Ÿ”Ž', + '๐Ÿ•ฏ๏ธ', + '๐Ÿ’ก', + '๐Ÿ”ฆ', + '๐Ÿฎ', + '๐Ÿช”', + '๐Ÿ“”', + '๐Ÿ“•', + '๐Ÿ“–', + '๐Ÿ“—', + '๐Ÿ“˜', + '๐Ÿ“™', + '๐Ÿ“š', + '๐Ÿ““', + '๐Ÿ“’', + '๐Ÿ“ƒ', + '๐Ÿ“œ', + '๐Ÿ“„', + '๐Ÿ“ฐ', + '๐Ÿ—ž๏ธ', + '๐Ÿ“‘', + '๐Ÿ”–', + '๐Ÿท๏ธ', + '๐Ÿ’ฐ', + '๐Ÿช™', + '๐Ÿ’ด', + '๐Ÿ’ต', + '๐Ÿ’ถ', + '๐Ÿ’ท', + '๐Ÿ’ธ', + '๐Ÿ’ณ', + '๐Ÿงพ', + '๐Ÿ’น', + 'โœ‰๏ธ', + '๐Ÿ“ง', + '๐Ÿ“จ', + '๐Ÿ“ฉ', + '๐Ÿ“ค', + '๐Ÿ“ฅ', + '๐Ÿ“ฆ', + '๐Ÿ“ซ', + '๐Ÿ“ช', + '๐Ÿ“ฌ', + '๐Ÿ“ญ', + '๐Ÿ“ฎ', + '๐Ÿ—ณ๏ธ', + 'โœ๏ธ', + 'โœ’๏ธ', + '๐Ÿ–‹๏ธ', + '๐Ÿ–Š๏ธ', + '๐Ÿ–Œ๏ธ', + '๐Ÿ–๏ธ', + '๐Ÿ“', + '๐Ÿ’ผ', + '๐Ÿ“', + '๐Ÿ“‚', + '๐Ÿ—‚๏ธ', + '๐Ÿ“…', + '๐Ÿ“†', + '๐Ÿ—’๏ธ', + '๐Ÿ—“๏ธ', + '๐Ÿ“‡', + '๐Ÿ“ˆ', + '๐Ÿ“‰', + '๐Ÿ“Š', + '๐Ÿ“‹', + '๐Ÿ“Œ', + '๐Ÿ“', + '๐Ÿ“Ž', + '๐Ÿ–‡๏ธ', + '๐Ÿ“', + '๐Ÿ“', + 'โœ‚๏ธ', + '๐Ÿ—ƒ๏ธ', + '๐Ÿ—„๏ธ', + '๐Ÿ—‘๏ธ', + '๐Ÿ”’', + '๐Ÿ”“', + '๐Ÿ”', + '๐Ÿ”', + '๐Ÿ”‘', + '๐Ÿ—๏ธ', + '๐Ÿ”จ', + '๐Ÿช“', + 'โ›๏ธ', + 'โš’๏ธ', + '๐Ÿ› ๏ธ', + '๐Ÿ—ก๏ธ', + 'โš”๏ธ', + '๐Ÿ’ฃ', + '๐Ÿชƒ', + '๐Ÿน', + '๐Ÿ›ก๏ธ', + '๐Ÿชš', + '๐Ÿ”ง', + '๐Ÿช›', + '๐Ÿ”ฉ', + 'โš™๏ธ', + '๐Ÿ—œ๏ธ', + 'โš–๏ธ', + '๐Ÿฆฏ', + '๐Ÿ”—', + 'โ›“๏ธโ€๐Ÿ’ฅ', + 'โ›“๏ธ', + '๐Ÿช', + '๐Ÿงฐ', + '๐Ÿงฒ', + '๐Ÿชœ', + 'โš—๏ธ', + '๐Ÿงช', + '๐Ÿงซ', + '๐Ÿงฌ', + '๐Ÿ”ฌ', + '๐Ÿ”ญ', + '๐Ÿ“ก', + '๐Ÿ’‰', + '๐Ÿฉธ', + '๐Ÿ’Š', + '๐Ÿฉน', + '๐Ÿฉผ', + '๐Ÿฉบ', + '๐Ÿฉป', + '๐Ÿšช', + '๐Ÿ›—', + '๐Ÿชž', + '๐ŸชŸ', + '๐Ÿ›๏ธ', + '๐Ÿ›‹๏ธ', + '๐Ÿช‘', + '๐Ÿšฝ', + '๐Ÿช ', + '๐Ÿšฟ', + '๐Ÿ›', + '๐Ÿชค', + '๐Ÿช’', + '๐Ÿงด', + '๐Ÿงท', + '๐Ÿงน', + '๐Ÿงบ', + '๐Ÿงป', + '๐Ÿชฃ', + '๐Ÿงผ', + '๐Ÿซง', + '๐Ÿชฅ', + '๐Ÿงฝ', + '๐Ÿงฏ', + '๐Ÿ›’', + '๐Ÿšฌ', + 'โšฐ๏ธ', + '๐Ÿชฆ', + 'โšฑ๏ธ', + '๐Ÿงฟ', + '๐Ÿชฌ', + '๐Ÿ—ฟ', + '๐Ÿชง', + '๐Ÿชช', + ], + symbol: [ + '๐Ÿง', + '๐Ÿšฎ', + '๐Ÿšฐ', + 'โ™ฟ', + '๐Ÿšน', + '๐Ÿšบ', + '๐Ÿšป', + '๐Ÿšผ', + '๐Ÿšพ', + '๐Ÿ›‚', + '๐Ÿ›ƒ', + '๐Ÿ›„', + '๐Ÿ›…', + 'โš ๏ธ', + '๐Ÿšธ', + 'โ›”', + '๐Ÿšซ', + '๐Ÿšณ', + '๐Ÿšญ', + '๐Ÿšฏ', + '๐Ÿšฑ', + '๐Ÿšท', + '๐Ÿ“ต', + '๐Ÿ”ž', + 'โ˜ข๏ธ', + 'โ˜ฃ๏ธ', + 'โฌ†๏ธ', + 'โ†—๏ธ', + 'โžก๏ธ', + 'โ†˜๏ธ', + 'โฌ‡๏ธ', + 'โ†™๏ธ', + 'โฌ…๏ธ', + 'โ†–๏ธ', + 'โ†•๏ธ', + 'โ†”๏ธ', + 'โ†ฉ๏ธ', + 'โ†ช๏ธ', + 'โคด๏ธ', + 'โคต๏ธ', + '๐Ÿ”ƒ', + '๐Ÿ”„', + '๐Ÿ”™', + '๐Ÿ”š', + '๐Ÿ”›', + '๐Ÿ”œ', + '๐Ÿ”', + '๐Ÿ›', + 'โš›๏ธ', + '๐Ÿ•‰๏ธ', + 'โœก๏ธ', + 'โ˜ธ๏ธ', + 'โ˜ฏ๏ธ', + 'โœ๏ธ', + 'โ˜ฆ๏ธ', + 'โ˜ช๏ธ', + 'โ˜ฎ๏ธ', + '๐Ÿ•Ž', + '๐Ÿ”ฏ', + '๐Ÿชฏ', + 'โ™ˆ', + 'โ™‰', + 'โ™Š', + 'โ™‹', + 'โ™Œ', + 'โ™', + 'โ™Ž', + 'โ™', + 'โ™', + 'โ™‘', + 'โ™’', + 'โ™“', + 'โ›Ž', + '๐Ÿ”€', + '๐Ÿ”', + '๐Ÿ”‚', + 'โ–ถ๏ธ', + 'โฉ', + 'โญ๏ธ', + 'โฏ๏ธ', + 'โ—€๏ธ', + 'โช', + 'โฎ๏ธ', + '๐Ÿ”ผ', + 'โซ', + '๐Ÿ”ฝ', + 'โฌ', + 'โธ๏ธ', + 'โน๏ธ', + 'โบ๏ธ', + 'โ๏ธ', + '๐ŸŽฆ', + '๐Ÿ”…', + '๐Ÿ”†', + '๐Ÿ“ถ', + '๐Ÿ›œ', + '๐Ÿ“ณ', + '๐Ÿ“ด', + 'โšง๏ธ', + 'โœ–๏ธ', + 'โž•', + 'โž–', + 'โž—', + '๐ŸŸฐ', + 'โ™พ๏ธ', + 'โ€ผ๏ธ', + 'โ‰๏ธ', + 'โ“', + 'โ”', + 'โ•', + 'โ—', + 'ใ€ฐ๏ธ', + '๐Ÿ’ฑ', + '๐Ÿ’ฒ', + 'โ™ป๏ธ', + 'โšœ๏ธ', + '๐Ÿ”ฑ', + '๐Ÿ“›', + '๐Ÿ”ฐ', + 'โญ•', + 'โœ…', + 'โ˜‘๏ธ', + 'โœ”๏ธ', + 'โŒ', + 'โŽ', + 'โžฐ', + 'โžฟ', + 'ใ€ฝ๏ธ', + 'โœณ๏ธ', + 'โœด๏ธ', + 'โ‡๏ธ', + 'ยฉ๏ธ', + 'ยฎ๏ธ', + 'โ„ข๏ธ', + '#๏ธโƒฃ', + '*๏ธโƒฃ', + '0๏ธโƒฃ', + '1๏ธโƒฃ', + '2๏ธโƒฃ', + '3๏ธโƒฃ', + '4๏ธโƒฃ', + '5๏ธโƒฃ', + '6๏ธโƒฃ', + '7๏ธโƒฃ', + '8๏ธโƒฃ', + '9๏ธโƒฃ', + '๐Ÿ”Ÿ', + '๐Ÿ” ', + '๐Ÿ”ก', + '๐Ÿ”ข', + '๐Ÿ”ฃ', + '๐Ÿ”ค', + '๐Ÿ…ฐ๏ธ', + '๐Ÿ†Ž', + '๐Ÿ…ฑ๏ธ', + '๐Ÿ†‘', + '๐Ÿ†’', + '๐Ÿ†“', + 'โ„น๏ธ', + '๐Ÿ†”', + 'โ“‚๏ธ', + '๐Ÿ†•', + '๐Ÿ†–', + '๐Ÿ…พ๏ธ', + '๐Ÿ†—', + '๐Ÿ…ฟ๏ธ', + '๐Ÿ†˜', + '๐Ÿ†™', + '๐Ÿ†š', + '๐Ÿˆ', + '๐Ÿˆ‚๏ธ', + '๐Ÿˆท๏ธ', + '๐Ÿˆถ', + '๐Ÿˆฏ', + '๐Ÿ‰', + '๐Ÿˆน', + '๐Ÿˆš', + '๐Ÿˆฒ', + '๐Ÿ‰‘', + '๐Ÿˆธ', + '๐Ÿˆด', + '๐Ÿˆณ', + 'ใŠ—๏ธ', + 'ใŠ™๏ธ', + '๐Ÿˆบ', + '๐Ÿˆต', + '๐Ÿ”ด', + '๐ŸŸ ', + '๐ŸŸก', + '๐ŸŸข', + '๐Ÿ”ต', + '๐ŸŸฃ', + '๐ŸŸค', + 'โšซ', + 'โšช', + '๐ŸŸฅ', + '๐ŸŸง', + '๐ŸŸจ', + '๐ŸŸฉ', + '๐ŸŸฆ', + '๐ŸŸช', + '๐ŸŸซ', + 'โฌ›', + 'โฌœ', + 'โ—ผ๏ธ', + 'โ—ป๏ธ', + 'โ—พ', + 'โ—ฝ', + 'โ–ช๏ธ', + 'โ–ซ๏ธ', + '๐Ÿ”ถ', + '๐Ÿ”ท', + '๐Ÿ”ธ', + '๐Ÿ”น', + '๐Ÿ”บ', + '๐Ÿ”ป', + '๐Ÿ’ ', + '๐Ÿ”˜', + '๐Ÿ”ณ', + '๐Ÿ”ฒ', + ], + flag: [ + '๐Ÿ', + '๐Ÿšฉ', + '๐ŸŽŒ', + '๐Ÿด', + '๐Ÿณ๏ธ', + '๐Ÿณ๏ธโ€๐ŸŒˆ', + '๐Ÿณ๏ธโ€โšง๏ธ', + '๐Ÿดโ€โ˜ ๏ธ', + '๐Ÿ‡ฆ๐Ÿ‡จ', + '๐Ÿ‡ฆ๐Ÿ‡ฉ', + '๐Ÿ‡ฆ๐Ÿ‡ช', + '๐Ÿ‡ฆ๐Ÿ‡ซ', + '๐Ÿ‡ฆ๐Ÿ‡ฌ', + '๐Ÿ‡ฆ๐Ÿ‡ฎ', + '๐Ÿ‡ฆ๐Ÿ‡ฑ', + '๐Ÿ‡ฆ๐Ÿ‡ฒ', + '๐Ÿ‡ฆ๐Ÿ‡ด', + '๐Ÿ‡ฆ๐Ÿ‡ถ', + '๐Ÿ‡ฆ๐Ÿ‡ท', + '๐Ÿ‡ฆ๐Ÿ‡ธ', + '๐Ÿ‡ฆ๐Ÿ‡น', + '๐Ÿ‡ฆ๐Ÿ‡บ', + '๐Ÿ‡ฆ๐Ÿ‡ผ', + '๐Ÿ‡ฆ๐Ÿ‡ฝ', + '๐Ÿ‡ฆ๐Ÿ‡ฟ', + '๐Ÿ‡ง๐Ÿ‡ฆ', + '๐Ÿ‡ง๐Ÿ‡ง', + '๐Ÿ‡ง๐Ÿ‡ฉ', + '๐Ÿ‡ง๐Ÿ‡ช', + '๐Ÿ‡ง๐Ÿ‡ซ', + '๐Ÿ‡ง๐Ÿ‡ฌ', + '๐Ÿ‡ง๐Ÿ‡ญ', + '๐Ÿ‡ง๐Ÿ‡ฎ', + '๐Ÿ‡ง๐Ÿ‡ฏ', + '๐Ÿ‡ง๐Ÿ‡ฑ', + '๐Ÿ‡ง๐Ÿ‡ฒ', + '๐Ÿ‡ง๐Ÿ‡ณ', + '๐Ÿ‡ง๐Ÿ‡ด', + '๐Ÿ‡ง๐Ÿ‡ถ', + '๐Ÿ‡ง๐Ÿ‡ท', + '๐Ÿ‡ง๐Ÿ‡ธ', + '๐Ÿ‡ง๐Ÿ‡น', + '๐Ÿ‡ง๐Ÿ‡ป', + '๐Ÿ‡ง๐Ÿ‡ผ', + '๐Ÿ‡ง๐Ÿ‡พ', + '๐Ÿ‡ง๐Ÿ‡ฟ', + '๐Ÿ‡จ๐Ÿ‡ฆ', + '๐Ÿ‡จ๐Ÿ‡จ', + '๐Ÿ‡จ๐Ÿ‡ฉ', + '๐Ÿ‡จ๐Ÿ‡ซ', + '๐Ÿ‡จ๐Ÿ‡ฌ', + '๐Ÿ‡จ๐Ÿ‡ญ', + '๐Ÿ‡จ๐Ÿ‡ฎ', + '๐Ÿ‡จ๐Ÿ‡ฐ', + '๐Ÿ‡จ๐Ÿ‡ฑ', + '๐Ÿ‡จ๐Ÿ‡ฒ', + '๐Ÿ‡จ๐Ÿ‡ณ', + '๐Ÿ‡จ๐Ÿ‡ด', + '๐Ÿ‡จ๐Ÿ‡ต', + '๐Ÿ‡จ๐Ÿ‡ท', + '๐Ÿ‡จ๐Ÿ‡บ', + '๐Ÿ‡จ๐Ÿ‡ป', + '๐Ÿ‡จ๐Ÿ‡ผ', + '๐Ÿ‡จ๐Ÿ‡ฝ', + '๐Ÿ‡จ๐Ÿ‡พ', + '๐Ÿ‡จ๐Ÿ‡ฟ', + '๐Ÿ‡ฉ๐Ÿ‡ช', + '๐Ÿ‡ฉ๐Ÿ‡ฌ', + '๐Ÿ‡ฉ๐Ÿ‡ฏ', + '๐Ÿ‡ฉ๐Ÿ‡ฐ', + '๐Ÿ‡ฉ๐Ÿ‡ฒ', + '๐Ÿ‡ฉ๐Ÿ‡ด', + '๐Ÿ‡ฉ๐Ÿ‡ฟ', + '๐Ÿ‡ช๐Ÿ‡ฆ', + '๐Ÿ‡ช๐Ÿ‡จ', + '๐Ÿ‡ช๐Ÿ‡ช', + '๐Ÿ‡ช๐Ÿ‡ฌ', + '๐Ÿ‡ช๐Ÿ‡ญ', + '๐Ÿ‡ช๐Ÿ‡ท', + '๐Ÿ‡ช๐Ÿ‡ธ', + '๐Ÿ‡ช๐Ÿ‡น', + '๐Ÿ‡ช๐Ÿ‡บ', + '๐Ÿ‡ซ๐Ÿ‡ฎ', + '๐Ÿ‡ซ๐Ÿ‡ฏ', + '๐Ÿ‡ซ๐Ÿ‡ฐ', + '๐Ÿ‡ซ๐Ÿ‡ฒ', + '๐Ÿ‡ซ๐Ÿ‡ด', + '๐Ÿ‡ซ๐Ÿ‡ท', + '๐Ÿ‡ฌ๐Ÿ‡ฆ', + '๐Ÿ‡ฌ๐Ÿ‡ง', + '๐Ÿ‡ฌ๐Ÿ‡ฉ', + '๐Ÿ‡ฌ๐Ÿ‡ช', + '๐Ÿ‡ฌ๐Ÿ‡ซ', + '๐Ÿ‡ฌ๐Ÿ‡ฌ', + '๐Ÿ‡ฌ๐Ÿ‡ญ', + '๐Ÿ‡ฌ๐Ÿ‡ฎ', + '๐Ÿ‡ฌ๐Ÿ‡ฑ', + '๐Ÿ‡ฌ๐Ÿ‡ฒ', + '๐Ÿ‡ฌ๐Ÿ‡ณ', + '๐Ÿ‡ฌ๐Ÿ‡ต', + '๐Ÿ‡ฌ๐Ÿ‡ถ', + '๐Ÿ‡ฌ๐Ÿ‡ท', + '๐Ÿ‡ฌ๐Ÿ‡ธ', + '๐Ÿ‡ฌ๐Ÿ‡น', + '๐Ÿ‡ฌ๐Ÿ‡บ', + '๐Ÿ‡ฌ๐Ÿ‡ผ', + '๐Ÿ‡ฌ๐Ÿ‡พ', + '๐Ÿ‡ญ๐Ÿ‡ฐ', + '๐Ÿ‡ญ๐Ÿ‡ฒ', + '๐Ÿ‡ญ๐Ÿ‡ณ', + '๐Ÿ‡ญ๐Ÿ‡ท', + '๐Ÿ‡ญ๐Ÿ‡น', + '๐Ÿ‡ญ๐Ÿ‡บ', + '๐Ÿ‡ฎ๐Ÿ‡จ', + '๐Ÿ‡ฎ๐Ÿ‡ฉ', + '๐Ÿ‡ฎ๐Ÿ‡ช', + '๐Ÿ‡ฎ๐Ÿ‡ฑ', + '๐Ÿ‡ฎ๐Ÿ‡ฒ', + '๐Ÿ‡ฎ๐Ÿ‡ณ', + '๐Ÿ‡ฎ๐Ÿ‡ด', + '๐Ÿ‡ฎ๐Ÿ‡ถ', + '๐Ÿ‡ฎ๐Ÿ‡ท', + '๐Ÿ‡ฎ๐Ÿ‡ธ', + '๐Ÿ‡ฎ๐Ÿ‡น', + '๐Ÿ‡ฏ๐Ÿ‡ช', + '๐Ÿ‡ฏ๐Ÿ‡ฒ', + '๐Ÿ‡ฏ๐Ÿ‡ด', + '๐Ÿ‡ฏ๐Ÿ‡ต', + '๐Ÿ‡ฐ๐Ÿ‡ช', + '๐Ÿ‡ฐ๐Ÿ‡ฌ', + '๐Ÿ‡ฐ๐Ÿ‡ญ', + '๐Ÿ‡ฐ๐Ÿ‡ฎ', + '๐Ÿ‡ฐ๐Ÿ‡ฒ', + '๐Ÿ‡ฐ๐Ÿ‡ณ', + '๐Ÿ‡ฐ๐Ÿ‡ต', + '๐Ÿ‡ฐ๐Ÿ‡ท', + '๐Ÿ‡ฐ๐Ÿ‡ผ', + '๐Ÿ‡ฐ๐Ÿ‡พ', + '๐Ÿ‡ฐ๐Ÿ‡ฟ', + '๐Ÿ‡ฑ๐Ÿ‡ฆ', + '๐Ÿ‡ฑ๐Ÿ‡ง', + '๐Ÿ‡ฑ๐Ÿ‡จ', + '๐Ÿ‡ฑ๐Ÿ‡ฎ', + '๐Ÿ‡ฑ๐Ÿ‡ฐ', + '๐Ÿ‡ฑ๐Ÿ‡ท', + '๐Ÿ‡ฑ๐Ÿ‡ธ', + '๐Ÿ‡ฑ๐Ÿ‡น', + '๐Ÿ‡ฑ๐Ÿ‡บ', + '๐Ÿ‡ฑ๐Ÿ‡ป', + '๐Ÿ‡ฑ๐Ÿ‡พ', + '๐Ÿ‡ฒ๐Ÿ‡ฆ', + '๐Ÿ‡ฒ๐Ÿ‡จ', + '๐Ÿ‡ฒ๐Ÿ‡ฉ', + '๐Ÿ‡ฒ๐Ÿ‡ช', + '๐Ÿ‡ฒ๐Ÿ‡ซ', + '๐Ÿ‡ฒ๐Ÿ‡ฌ', + '๐Ÿ‡ฒ๐Ÿ‡ญ', + '๐Ÿ‡ฒ๐Ÿ‡ฐ', + '๐Ÿ‡ฒ๐Ÿ‡ฑ', + '๐Ÿ‡ฒ๐Ÿ‡ฒ', + '๐Ÿ‡ฒ๐Ÿ‡ณ', + '๐Ÿ‡ฒ๐Ÿ‡ด', + '๐Ÿ‡ฒ๐Ÿ‡ต', + '๐Ÿ‡ฒ๐Ÿ‡ถ', + '๐Ÿ‡ฒ๐Ÿ‡ท', + '๐Ÿ‡ฒ๐Ÿ‡ธ', + '๐Ÿ‡ฒ๐Ÿ‡น', + '๐Ÿ‡ฒ๐Ÿ‡บ', + '๐Ÿ‡ฒ๐Ÿ‡ป', + '๐Ÿ‡ฒ๐Ÿ‡ผ', + '๐Ÿ‡ฒ๐Ÿ‡ฝ', + '๐Ÿ‡ฒ๐Ÿ‡พ', + '๐Ÿ‡ฒ๐Ÿ‡ฟ', + '๐Ÿ‡ณ๐Ÿ‡ฆ', + '๐Ÿ‡ณ๐Ÿ‡จ', + '๐Ÿ‡ณ๐Ÿ‡ช', + '๐Ÿ‡ณ๐Ÿ‡ซ', + '๐Ÿ‡ณ๐Ÿ‡ฌ', + '๐Ÿ‡ณ๐Ÿ‡ฎ', + '๐Ÿ‡ณ๐Ÿ‡ฑ', + '๐Ÿ‡ณ๐Ÿ‡ด', + '๐Ÿ‡ณ๐Ÿ‡ต', + '๐Ÿ‡ณ๐Ÿ‡ท', + '๐Ÿ‡ณ๐Ÿ‡บ', + '๐Ÿ‡ณ๐Ÿ‡ฟ', + '๐Ÿ‡ด๐Ÿ‡ฒ', + '๐Ÿ‡ต๐Ÿ‡ฆ', + '๐Ÿ‡ต๐Ÿ‡ช', + '๐Ÿ‡ต๐Ÿ‡ซ', + '๐Ÿ‡ต๐Ÿ‡ฌ', + '๐Ÿ‡ต๐Ÿ‡ญ', + '๐Ÿ‡ต๐Ÿ‡ฐ', + '๐Ÿ‡ต๐Ÿ‡ฑ', + '๐Ÿ‡ต๐Ÿ‡ฒ', + '๐Ÿ‡ต๐Ÿ‡ณ', + '๐Ÿ‡ต๐Ÿ‡ท', + '๐Ÿ‡ต๐Ÿ‡ธ', + '๐Ÿ‡ต๐Ÿ‡น', + '๐Ÿ‡ต๐Ÿ‡ผ', + '๐Ÿ‡ต๐Ÿ‡พ', + '๐Ÿ‡ถ๐Ÿ‡ฆ', + '๐Ÿ‡ท๐Ÿ‡ช', + '๐Ÿ‡ท๐Ÿ‡ด', + '๐Ÿ‡ท๐Ÿ‡ธ', + '๐Ÿ‡ท๐Ÿ‡บ', + '๐Ÿ‡ท๐Ÿ‡ผ', + '๐Ÿ‡ธ๐Ÿ‡ฆ', + '๐Ÿ‡ธ๐Ÿ‡ง', + '๐Ÿ‡ธ๐Ÿ‡จ', + '๐Ÿ‡ธ๐Ÿ‡ฉ', + '๐Ÿ‡ธ๐Ÿ‡ช', + '๐Ÿ‡ธ๐Ÿ‡ฌ', + '๐Ÿ‡ธ๐Ÿ‡ญ', + '๐Ÿ‡ธ๐Ÿ‡ฎ', + '๐Ÿ‡ธ๐Ÿ‡ฏ', + '๐Ÿ‡ธ๐Ÿ‡ฐ', + '๐Ÿ‡ธ๐Ÿ‡ฑ', + '๐Ÿ‡ธ๐Ÿ‡ฒ', + '๐Ÿ‡ธ๐Ÿ‡ณ', + '๐Ÿ‡ธ๐Ÿ‡ด', + '๐Ÿ‡ธ๐Ÿ‡ท', + '๐Ÿ‡ธ๐Ÿ‡ธ', + '๐Ÿ‡ธ๐Ÿ‡น', + '๐Ÿ‡ธ๐Ÿ‡ป', + '๐Ÿ‡ธ๐Ÿ‡ฝ', + '๐Ÿ‡ธ๐Ÿ‡พ', + '๐Ÿ‡ธ๐Ÿ‡ฟ', + '๐Ÿ‡น๐Ÿ‡ฆ', + '๐Ÿ‡น๐Ÿ‡จ', + '๐Ÿ‡น๐Ÿ‡ฉ', + '๐Ÿ‡น๐Ÿ‡ซ', + '๐Ÿ‡น๐Ÿ‡ฌ', + '๐Ÿ‡น๐Ÿ‡ญ', + '๐Ÿ‡น๐Ÿ‡ฏ', + '๐Ÿ‡น๐Ÿ‡ฐ', + '๐Ÿ‡น๐Ÿ‡ฑ', + '๐Ÿ‡น๐Ÿ‡ฒ', + '๐Ÿ‡น๐Ÿ‡ณ', + '๐Ÿ‡น๐Ÿ‡ด', + '๐Ÿ‡น๐Ÿ‡ท', + '๐Ÿ‡น๐Ÿ‡น', + '๐Ÿ‡น๐Ÿ‡ป', + '๐Ÿ‡น๐Ÿ‡ผ', + '๐Ÿ‡น๐Ÿ‡ฟ', + '๐Ÿ‡บ๐Ÿ‡ฆ', + '๐Ÿ‡บ๐Ÿ‡ฌ', + '๐Ÿ‡บ๐Ÿ‡ฒ', + '๐Ÿ‡บ๐Ÿ‡ณ', + '๐Ÿ‡บ๐Ÿ‡ธ', + '๐Ÿ‡บ๐Ÿ‡พ', + '๐Ÿ‡บ๐Ÿ‡ฟ', + '๐Ÿ‡ป๐Ÿ‡ฆ', + '๐Ÿ‡ป๐Ÿ‡จ', + '๐Ÿ‡ป๐Ÿ‡ช', + '๐Ÿ‡ป๐Ÿ‡ฌ', + '๐Ÿ‡ป๐Ÿ‡ฎ', + '๐Ÿ‡ป๐Ÿ‡ณ', + '๐Ÿ‡ป๐Ÿ‡บ', + '๐Ÿ‡ผ๐Ÿ‡ซ', + '๐Ÿ‡ผ๐Ÿ‡ธ', + '๐Ÿ‡ฝ๐Ÿ‡ฐ', + '๐Ÿ‡พ๐Ÿ‡ช', + '๐Ÿ‡พ๐Ÿ‡น', + '๐Ÿ‡ฟ๐Ÿ‡ฆ', + '๐Ÿ‡ฟ๐Ÿ‡ฒ', + '๐Ÿ‡ฟ๐Ÿ‡ผ', + '๐Ÿด๓ ง๓ ข๓ ฅ๓ ฎ๓ ง๓ ฟ', + '๐Ÿด๓ ง๓ ข๓ ณ๓ ฃ๓ ด๓ ฟ', + '๐Ÿด๓ ง๓ ข๓ ท๓ ฌ๓ ณ๓ ฟ', + ], + }; + + function emoji_tab_click(event) { + var tab = event.target; + + var pages = document.getElementsByClassName('emoji_page'); + for (var i = 0; i < pages.length; i++) { + pages[i].style.display = 'none'; + } + + var tabs = document.getElementsByClassName('emoji_tab'); + for (var i = 0; i < tabs.length; i++) { + tabs[i].classList.remove('selected'); + } + + var page = document.getElementById(tab.emoji_page); + page.style.display = 'inline-block'; + tab.classList.add('selected'); + } + + function emoji_insert(event) { + var node = event.target; + var blocker = document.getElementById('emoji_blocker'); + blocker.style.display = 'none'; + var e = node.innerText; + emoji_recently_used(e); + var ts = document.getElementsByClassName('emoji_target'); + for (var i = 0; i < ts.length; i++) { + var tt = ts[i]; + if (tt.tagName == 'INPUT' || tt.tagName == 'TEXTAREA') { + tt.focus(); + var start = tt.selectionStart || 0; + var end = tt.selectionEnd || 0; + tt.value = + tt.value.substring(0, start) + + e + + tt.value.substring(end, tt.value.length); + tt.focus(); + tt.selectionStart = start + e.length; + tt.selectionEnd = start + e.length; + } + } + } + + function emoji_menu_dismiss(event) { + if (event.type == 'resize' || event.target.id == 'emoji_blocker') { + var blocker = document.getElementById('emoji_blocker'); + blocker.style.display = 'none'; + } + } + + var emoji_recent = []; + + function emoji_recently_used(e) { + while (true) { + var i = emoji_recent.indexOf(e); + if (i < 0) break; + emoji_recent.splice(i, 1); + } + emoji_recent.unshift(e); + if (emoji_recent.length > 100) emoji_recent = emoji_recent.slice(0, 100); + + var page = document.getElementById('emoji_recent'); + var old = page.getElementsByTagName('a'); + for (var i = old.length - 1; i >= 0; i--) { + old[i].parentNode.removeChild(old[i]); + } + + for (var j = 0; j < emoji_recent.length; j++) { + var a = document.createElement('a'); + a.innerText = emoji_recent[j]; + a.className = 'emoji_square'; + a.onclick = emoji_insert; + page.appendChild(a); + } + + try { + localStorage.setItem('emoji_recent', emoji_recent.join(',')); + } catch (e) {} + } + + function build_emoji_menu() { + try { + emoji_recent = localStorage.getItem('emoji_recent'); + if (emoji_recent) emoji_recent = emoji_recent.split(','); + } catch (e) {} + if (!emoji_recent) emoji_recent = []; + + var menu = document.createElement('div'); + menu.className = 'emoji_menu'; + + var tab_bar = document.createElement('div'); + tab_bar.className = 'emoji_tab_bar'; + menu.appendChild(tab_bar); + + var page_box = document.createElement('div'); + page_box.className = 'emoji_page_box'; + menu.appendChild(page_box); + + var selected_tab = null; + var n = emoji_categories.length; + for (var i = 0; i < n; i++) { + var cat = emoji_categories[i].name; + var label = emoji_categories[i].label; + var icon = emoji_categories[i].icon; + var em = emoji[cat]; + + if (cat == 'recent') em = emoji_recent; + + var m = em ? em.length : 0; + + var tab = document.createElement('div'); + tab.className = 'emoji_tab'; + tab.innerText = icon; + tab.onclick = emoji_tab_click; + tab_bar.appendChild(tab); + + var page = document.createElement('div'); + page.className = 'emoji_page'; + page.id = 'emoji_' + cat; + tab.emoji_page = page.id; + page_box.appendChild(page); + + var head = document.createElement('b'); + head.innerText = label; + page.appendChild(head); + + for (var j = 0; j < m; j++) { + var a = document.createElement('a'); + a.innerText = em[j]; + a.className = 'emoji_square'; + a.onclick = emoji_insert; + page.appendChild(a); + } + + if (!selected_tab && m) selected_tab = tab; + } + + var blocker = document.createElement('div'); + blocker.id = 'emoji_blocker'; + blocker.style.display = 'none'; + blocker.appendChild(menu); + blocker.onclick = emoji_menu_dismiss; + window.addEventListener('resize', emoji_menu_dismiss); + + document.body.appendChild(blocker); + + if (selected_tab) emoji_tab_click({ target: selected_tab }); + } + + function emoji_menu_popup(event) { + var blocker = document.getElementById('emoji_blocker'); + if (!blocker) { + build_emoji_menu(); + blocker = document.getElementById('emoji_blocker'); + } + blocker.style.display = 'block'; + + var rect = event.target.getBoundingClientRect(); + var menu = blocker.getElementsByClassName('emoji_menu')[0]; + var x = rect.x - 8; + var y = rect.y - 8; + var w = menu.offsetWidth; + var h = menu.offsetHeight; + + var maxw = blocker.clientWidth - 8; + var maxh = blocker.clientHeight - 8; + if (x + w >= maxw) x = maxw - w; + if (y + h >= maxh) y = maxh - h; + if (x < 0) x = 0; + if (y < 0) y = 0; + + menu.style.left = x + 'px'; + menu.style.top = y + 'px'; + + return false; + } + + function emoji_init() { + var ts = document.getElementsByClassName('emoji_target'); + for (var i = 0; i < ts.length; i++) { + var tt = ts[i]; + var button = document.createElement('a'); + button.className = 'emoji_button'; + button.innerText = '\u{1F600}'; + button.onclick = emoji_menu_popup; + tt.parentNode.insertBefore(button, tt.nextSibling); + + tt.style.boxSizing = 'border-box'; + tt.style.paddingRight = '1.5em'; + } + } + + emoji_init(); +})(); +// @license-end diff --git a/src/emojiButton/index.ts b/src/emojiButton/index.ts new file mode 100644 index 0000000..77bfd60 --- /dev/null +++ b/src/emojiButton/index.ts @@ -0,0 +1 @@ +export { default } from './plugin.js'; diff --git a/src/emojiButton/plugin.ts b/src/emojiButton/plugin.ts new file mode 100644 index 0000000..1110114 --- /dev/null +++ b/src/emojiButton/plugin.ts @@ -0,0 +1,47 @@ +import fs from 'node:fs'; +import { join } from 'node:path'; + +import Debug from 'debug'; +import type { TwtKprPluginConfiguration } from 'express-twtkpr'; +import { getReadStream } from 'express-twtkpr'; + +import { __dirname } from '../constants.js'; + +console.log({ __dirname }); + +const PLUGIN_NAME = 'emojiButton'; + +export default (): TwtKprPluginConfiguration => ({ + clientCSS: () => { + const cssStream = fs.createReadStream( + join(__dirname, 'src', PLUGIN_NAME, 'client', 'emoji.css') + ); + + cssStream.on('error', (err) => { + console.error(err); + cssStream.close(); + cssStream.push(null); + }); + + return cssStream; + }, + + clientJS: () => { + const jsFileStream = getReadStream( + join(__dirname, 'src', PLUGIN_NAME, 'client', 'emoji.js') + ); + /* + const jsStream = Readable.from(` + const twtSubmitButton = document.querySelector('.twtControls-submitButton'); + const emojiTarget = document.querySelector('.emoji_target'); + emojiTarget.addEventListener('change', () => { + if (twtSubmitButton) twtSubmitButton.removeAttribute('disabled'); + }); + `); + */ + + return jsFileStream; + }, + + name: PLUGIN_NAME, +}); diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..020e20d --- /dev/null +++ b/src/index.ts @@ -0,0 +1,3 @@ +export { default as emojiButton } from './emojiButton/index.js'; +export { default as postToMastodon } from './postToMastodon/index.js'; +export { default as uploadButton } from './uploadButton/index.js'; diff --git a/src/postToMastodon/client/script.js b/src/postToMastodon/client/script.js new file mode 100644 index 0000000..5651d9a --- /dev/null +++ b/src/postToMastodon/client/script.js @@ -0,0 +1,34 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT + +(() => { + const twtForm = document.getElementById('twtForm'); + + /* + document + .querySelector('.twtControls-contentLabel') + ?.insertAdjacentHTML('beforebegin', renderUploadButton()); + + document + .querySelector('#twtControlsEditButton') + ?.insertAdjacentHTML('beforebegin', renderUploadButton('small')); + + const twtControlsContentInput = document.getElementById( + 'twtControlsContentInput' + ); + + twtControlsContentInput.addEventListener('drop', dropHandler); + + twtControlsContentInput.addEventListener('dragover', dragOverHandler); + + window.addEventListener('dragover', dragOverWindowHandler); + + window.addEventListener('drop', dropWindowHandler); + + Array.from(document.querySelectorAll('.twtControls-uploadInput')).forEach( + (uploadInput) => { + uploadInput.addEventListener('change', uploadChangeHandler); + } + ); + */ +})(); +// @license-end diff --git a/src/postToMastodon/index.ts b/src/postToMastodon/index.ts new file mode 100644 index 0000000..77bfd60 --- /dev/null +++ b/src/postToMastodon/index.ts @@ -0,0 +1 @@ +export { default } from './plugin.js'; diff --git a/src/postToMastodon/plugin.ts b/src/postToMastodon/plugin.ts new file mode 100644 index 0000000..b8bba31 --- /dev/null +++ b/src/postToMastodon/plugin.ts @@ -0,0 +1,88 @@ +import type { + TwtKprConfiguration, + TwtKprPluginConfiguration, +} from 'express-twtkpr'; + +import Debug from 'debug'; + +import { __dirname } from '../constants.js'; + +const PLUGIN_NAME = 'postToMastodon'; + +// curl https://toot.cafe/api/v1/statuses -H 'Authorization: Bearer A0k6vbobTQvG-n9DStsfGV03BKxKkZHL-IhljR3Lvik' -F 'status=Test posting from cURL via the API. Hello from the command line!' + +export default (config: TwtKprConfiguration): TwtKprPluginConfiguration => { + const debug = Debug(`twtkprPlugin:${PLUGIN_NAME}`); + + const { application_token, server_url } = + config?.plugins?.[PLUGIN_NAME] ?? {}; + + if (!application_token || !server_url) return {}; + + return { + onAfterTwt: async (twt) => { + // TODO: add some console.log / error to output things that we can't return a message for + // That way, it shows up _somewhere_ + + // Don't do anything if the twt is a reply (starts with a hash) + const [, content] = twt.split(/\t/); + if (content.match(/^\(#(\w+)\)/)) { + // it's a reply, skip + return; + } + + const formData = new FormData(); + formData.append('status', content.replace(/\s*\u2028/g, '\n')); + + debug(`Sending message to Mastodon instance at ${server_url}`); + + const res = await fetch( + `${server_url}${server_url.endsWith('/') ? '' : '/'}api/v1/statuses`, + { + method: 'POST', + body: formData, + headers: { + Authorization: `Bearer ${application_token}`, + }, + } + ); + + if (!res.ok) { + console.error( + `Bad response (${res.status}) from Mastodon server ${ + server_url + }: ${res.statusText}` + ); + return; + } + + const result = await res.text(); + + console.log(`Twt sent to Mastodon server ${server_url}, response:`, { + result, + }); + }, + + // use JS to add a checkbox to the form + // update the Twt post function to send the whole form - that will + // allow you to add new things to it and they will be sent + + /* + clientJS: () => { + const jsStream = fs.createReadStream( + path.join(__dirname, 'plugins', PLUGIN_NAME, 'script.js') + ); + + jsStream.on('error', (err) => { + console.error(err); + jsStream.close(); + jsStream.push(null); + }); + + return jsStream; + }, + */ + + name: PLUGIN_NAME, + }; +}; diff --git a/src/uploadButton/client/script.js b/src/uploadButton/client/script.js new file mode 100644 index 0000000..ac44401 --- /dev/null +++ b/src/uploadButton/client/script.js @@ -0,0 +1,154 @@ +// @license magnet:?xt=urn:btih:d3d9a9a6595521f9666a5e94cc830dab83b65699&dn=expat.txt MIT +const injectUploadButton = (route) => { + // const route = '/files'; + + /** + * + * @param uploadConfiguration + * @param variant + * @returns + */ + const renderUploadButton = (variant = 'normal') => ` + + `; + + const uploadFiles = async (files, uploadRoute, secondAttempt = false) => { + if (!uploadRoute || !window.token || !window.refreshToken) return; + + debug('uploadFiles', token, files, uploadRoute, secondAttempt); + + const formData = new FormData(); + for (let i = 0; i < files.length; i++) { + formData.append('files', files[i]); + } + + try { + const res = await fetch(uploadRoute, { + method: 'POST', + type: 'upload', + body: formData, + headers: { + Authorization: `Bearer ${token}`, + }, + credentials: 'include', + }); + + if (res.ok) { + showToast(`File${files.length !== 1 ? 's' : ''} uploaded`); + + const filePath = await res.text(); + twtControlsContentInput.value += filePath + .split('\n') + .map((currFilePath) => + [ + ' ', + location.protocol, + '//', + location.hostname, + location.protocol !== 'https:' && location.port !== 80 + ? ':' + location.port + : '', + currFilePath, + ].join('') + ) + .join(''); + + return; + } + + if (!secondAttempt) { + await refreshToken(); + return uploadFiles(files, uploadRoute, true); + } + + showToast( + `Unable to upload image${files.length !== 1 ? 's' : ''} refresh token, please try again later.`, + 'error' + ); + } catch (err) { + console.error(err); + } + }; + + /* Handlers */ + + const dragOverHandler = (ev) => { + const files = [...ev.dataTransfer.items].filter( + (item) => item.kind === 'file' + ); + + if (files.length > 0) { + ev.preventDefault(); + ev.dataTransfer.dropEffect = 'copy'; + } + }; + + const dragOverWindowHandler = (ev) => { + const files = [...ev.dataTransfer.items].filter( + (item) => item.kind === 'file' + ); + + if (files.length > 0) { + ev.preventDefault(); + + if (!twtControlsContentInput.contains(ev.target)) { + ev.dataTransfer.dropEffect = 'none'; + } + } + }; + + const dropHandler = (ev) => { + ev.preventDefault(); + + const files = [...ev.dataTransfer.items] + .map((item) => item.getAsFile()) + .filter((file) => file); + + debug('dropHandler', files); + uploadFiles(files, route); + }; + + const dropWindowHandler = (ev) => { + if ([...ev.dataTransfer.items].some((item) => item.kind === 'file')) { + ev.preventDefault(); + } + }; + + const uploadChangeHandler = (ev) => { + uploadFiles(ev.target.files, route); + }; + + document + .querySelector('.twtControls-contentLabel') + ?.insertAdjacentHTML('beforebegin', renderUploadButton()); + + document + .querySelector('#twtControlsEditButton') + ?.insertAdjacentHTML('beforebegin', renderUploadButton('small')); + + const twtControlsContentInput = document.getElementById( + 'twtControlsContentInput' + ); + + twtControlsContentInput.addEventListener('drop', dropHandler); + + twtControlsContentInput.addEventListener('dragover', dragOverHandler); + + window.addEventListener('dragover', dragOverWindowHandler); + + window.addEventListener('drop', dropWindowHandler); + + Array.from(document.querySelectorAll('.twtControls-uploadInput')).forEach( + (uploadInput) => { + uploadInput.addEventListener('change', uploadChangeHandler); + } + ); +}; +// @license-end diff --git a/src/uploadButton/client/styles.css b/src/uploadButton/client/styles.css new file mode 100644 index 0000000..eda28a7 --- /dev/null +++ b/src/uploadButton/client/styles.css @@ -0,0 +1,37 @@ +/** + * Begin TwtKpr UploadPlugin CSS + */ +.twtControls-uploadInputLabel { + align-items: center; + cursor: pointer; + display: flex; + justify-content: center; + max-width: 100%; + text-align: center; + transition: all 0.5s; +} + +.twtControls-uploadInputLabel input { + display: none; +} + +/* +.twtControls-uploadInputLabel-normal { + display: none; +} +*/ + +.twtControls-uploadInputLabel-small { + font-size: small; +} + +.twtControls-uploadInputLabel:hover { + background-color: var(--bg-hl); + color: var(--fg-hl); +} + +/* +.twtControls-uploadInput { + display: none; +} +*/ diff --git a/src/uploadButton/defaults.ts b/src/uploadButton/defaults.ts new file mode 100644 index 0000000..2f5d353 --- /dev/null +++ b/src/uploadButton/defaults.ts @@ -0,0 +1,40 @@ +/* + uploadConfiguration: { + ...uploadConfiguration, + active: uploadActive, + allowEmptyFiles, + allowedMimeTypes: getDestinationByMimeTypeConfiguration(allowedMimeTypes), + createDirsFromUploads, + directory, + encoding, + fileWriteStreamHandler, + filter, + hashAlgorithm: hashAlgorithm as string | false | undefined, + keepExtensions, + maxFields, + maxFileSize, + maxFiles, + maxTotalFileSize, + minFileSize, + route, + }, +*/ + +// falls back to formidable defaults where it can +export default { + // local values + allowedMimeTypes: '', + directory: 'public', + imageFit: 'inside', + imageHeight: 1024, + imageWidth: 1024, + route: 'files', + // uploadEncoding: 'utf-8', + + // defaults for formidable + // allowEmptyFiles: false, // same as formidable + // encoding: 'utf-8', // same as formidable + hashAlgorithm: 'sha256', + keepExtensions: true, // TODO: verify this is necessary + maxFiles: 10, +}; diff --git a/src/uploadButton/index.ts b/src/uploadButton/index.ts new file mode 100644 index 0000000..77bfd60 --- /dev/null +++ b/src/uploadButton/index.ts @@ -0,0 +1 @@ +export { default } from './plugin.js'; diff --git a/src/uploadButton/plugin.ts b/src/uploadButton/plugin.ts new file mode 100644 index 0000000..cfe6ede --- /dev/null +++ b/src/uploadButton/plugin.ts @@ -0,0 +1,237 @@ +import type { NextFunction, Request, Response } from 'express'; +import type { + MimeOptions, + TwtKprConfiguration, + TwtKprPluginConfiguration, +} from 'express-twtkpr'; + +import fs, { promises as fsp, fstat } from 'node:fs'; +import { extname, join } from 'node:path'; +import { Readable } from 'node:stream'; + +import Debug from 'debug'; +import { combineStreams, getReadStream } from 'express-twtkpr'; +import formidable from 'formidable'; +import sharp, { FitEnum } from 'sharp'; + +import { __dirname } from '../constants.js'; +import defaults from './defaults.js'; +import { getDestinationByMimeTypeConfiguration } from './utils.js'; + +const PLUGIN_NAME = 'uploadButton'; + +export default (config: TwtKprConfiguration): TwtKprPluginConfiguration => { + const debug = Debug(`twtkprPlugin:${PLUGIN_NAME}}`); + const { route = '/files' } = config?.plugins?.[PLUGIN_NAME] ?? {}; + + return { + clientCSS: () => { + const stream = getReadStream( + join(__dirname, 'src', PLUGIN_NAME, 'client', 'styles.css') + ); + return stream; + }, + clientJS: () => { + const jsStream = getReadStream( + join(__dirname, 'src', PLUGIN_NAME, 'client', 'script.js') + ); + const jsCallerStream = Readable.from(`injectUploadButton('${route}');`); + + return combineStreams([jsStream, jsCallerStream]); + }, + + name: PLUGIN_NAME, + + postRoutes: [ + { + path: route, + handler: async (req: Request, res: Response, next: NextFunction) => { + const { + allowedMimeTypes, + directory, + imageFit, + imageHeight, + imageWidth, + route, + ...otherProps + } = Object.assign( + {}, + defaults, + config?.plugins?.uploadConfiguration ?? {} + ); + + if (Array.isArray(allowedMimeTypes) && !allowedMimeTypes.length) { + next(); + return; + } + + debug('using configuration: ', { + uploadConfiguration: config?.plugins?.uploadConfiguration, + }); + + const form = formidable({ + uploadDir: directory, + ...otherProps, + }); + + form.parse(req, async (err, fields, files) => { + if (err) { + next(err); + return; + } + const uploadsDir = (route ?? '').replaceAll('/', ''); + + let hadFileError = false; + const processedFiles: string[] = []; + const destinationByMimeType = + getDestinationByMimeTypeConfiguration(allowedMimeTypes); + + debug(`processing ${(files?.files ?? []).length} files`); + + for (const file of files?.files ?? []) { + const { + filepath, + hash, + mimetype, + newFilename, + originalFilename, + } = file ?? {}; + if (!(filepath && newFilename && originalFilename)) return; + + debug({ file }); + + let ext = extname(originalFilename).toLocaleLowerCase(); + if (ext === '.jpeg') ext = '.jpg'; + + let destinationDir = ''; + Object.keys(destinationByMimeType).forEach((mimeType) => { + if ( + file.mimetype?.split('/')?.[0] === + mimeType.toLocaleLowerCase() + ) + destinationDir = + ( + destinationByMimeType[ + mimeType as keyof typeof destinationByMimeType + ] as MimeOptions + ).directory ?? ''; + }); + if (destinationDir === '') + destinationDir = + ( + destinationByMimeType[ + '*' as keyof typeof destinationByMimeType + ] as MimeOptions + )?.directory ?? uploadsDir; + + const finalPath = join(process.cwd(), 'public', destinationDir); + + const useOriginalName = !( + mimetype?.includes('image') || mimetype?.includes('video') + ); + let hashNameLength = 8; + let finalFilename; + let fileExists; + do { + finalFilename = ( + !useOriginalName && hash + ? `${hash.substring(0, hashNameLength)}${ext}` + : originalFilename + ) + .replace(/[^\w\.]+/g, '_') + .replace(/_+/g, '_') + .toLocaleLowerCase(); + + if (!useOriginalName) { + try { + await fsp.stat(join(finalPath, finalFilename)); + fileExists = true; + hashNameLength++; + } catch { + fileExists = false; + } + } + } while (!useOriginalName && fileExists); + + debug(`creating '${finalPath}'`); + fsp.mkdir(finalPath, { recursive: true }); + + const pathToOutputFile = join(finalPath, finalFilename); + let wasRelocated = false; + + if (mimetype?.includes('image')) { + // use sharp to shrink + debug(`converting '${filepath}' to '/${pathToOutputFile}'`); + + try { + await sharp(filepath) + .autoOrient() + // shrink to 1024 on biggest edge, do not enlarge + .resize({ + fit: imageFit as keyof FitEnum | undefined, + height: imageHeight, + width: imageWidth, + withoutEnlargement: true, + }) + .toFile(pathToOutputFile); + /* + await sharp(filepath) + .metadata() + .then(({ height, width }) => + sharp(filepath) + // shrink to 1024 on biggest edge, do not enlarge + .resize({ + height: height >= width ? 1024 : undefined, + width: width >= height ? 1024 : undefined, + withoutEnlargement: true, + }) + .toFile(pathToOutputFile) + ); + */ + wasRelocated = true; + } catch { + // at least we tried + } + } + + try { + if (!wasRelocated) { + debug(`copying '${filepath}' to '/${pathToOutputFile}'`); + + await fsp.copyFile(filepath, pathToOutputFile); + } + + debug(`cleaning up '${filepath}'`); + await fsp.rm(filepath); + + debug(`processed successfully`); + processedFiles.push(`/${destinationDir}/${finalFilename}`); + } catch (err) { + debug(`error!`); + hadFileError = true; + console.error(err); + } + } + + debug('generating reply...'); + if (hadFileError && processedFiles.length) { + res + .type('text/plain') + .status(206) + .send(processedFiles.join('\n')); + return; + } + + if (!processedFiles.length) { + res.type('text/plain').status(500).send('No files processed'); + return; + } + + res.type('text/plain').status(201).send(processedFiles.join('\n')); + }); + }, + requiresAuth: true, + }, + ], + }; +}; diff --git a/src/uploadButton/types.ts b/src/uploadButton/types.ts new file mode 100644 index 0000000..4b0facd --- /dev/null +++ b/src/uploadButton/types.ts @@ -0,0 +1,18 @@ +import type { MimeOptions } from 'express-twtkpr'; + +import formidable from 'formidable'; + +export interface MimeImageOptions extends MimeOptions { + compression?: string; + maxHeight?: string; + maxWidth?: string; +} + +export interface UploadConfiguration extends Partial< + Omit +> { + active: boolean; + directory: string; + allowedMimeTypes: string | string[] | Record; + route: string; +} diff --git a/src/uploadButton/utils.ts b/src/uploadButton/utils.ts new file mode 100644 index 0000000..d2cc5a2 --- /dev/null +++ b/src/uploadButton/utils.ts @@ -0,0 +1,58 @@ +import type { MimeOptions } from 'express-twtkpr'; + +/** + * + * @param allowedMimeTypes + * @returns + */ +export const getDestinationByMimeTypeConfiguration = ( + allowedMimeTypes?: string | string[] | Record +) => { + const fallback: Record = { + audio: { + directory: 'audio', + rename: false, + }, + image: { + directory: 'images', + rename: true, + }, + video: { + directory: 'videos', + rename: true, + }, + '*': { + directory: 'files', + rename: false, + }, + }; + + const mimeTypeArrayReducer = ( + acc: Record, + curr: string + ) => { + if (fallback[curr]) acc[curr] = fallback[curr]; + else + acc[curr] = { + directory: `${curr}s`, + rename: false, + }; + + return acc; + }; + + if (!allowedMimeTypes) return fallback; + + if (typeof allowedMimeTypes === 'string') + return allowedMimeTypes + .split(',') + .map((val) => val.trim()) + .reduce(mimeTypeArrayReducer, {}); + + if (Array.isArray(allowedMimeTypes)) + return (allowedMimeTypes as string[]).reduce(mimeTypeArrayReducer, {}); + + if (typeof allowedMimeTypes === 'object') return allowedMimeTypes; + + return fallback; +}; diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..944ff0b --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,17 @@ +{ + "compilerOptions": { + "declaration": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "module": "nodenext", + "noImplicitAny": true, + "outDir": "dist", + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "target": "esnext" + }, + "include": ["./package.json", "./types.d.ts", "src/**/*.ts", "test/**/*.ts"], + "exclude": ["node_modules", "./vitest.setup.ts", "**/__tests__/*.*"] +} diff --git a/yarn.lock b/yarn.lock index 3267dfc..f7ec616 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,11 +2,3316 @@ # Manual changes might be lost - proceed with caution! __metadata: - version: 8 + version: 9 cacheKey: 10c0 -"express-twtkpr-upload-button@workspace:.": +"@cacheable/node-cache@npm:^3.0.0": + version: 3.0.1 + resolution: "@cacheable/node-cache@npm:3.0.1" + dependencies: + "@cacheable/utils": "npm:^2.4.1" + hookified: "npm:^2.1.0" + keyv: "npm:^5.6.0" + checksum: 10c0/fb46d1be3fea35d874b62a0108022535c66d64524ce85943937b731cbe28bb92cc237bc36db6888ab11a7fa65d4de225f9d546aab43a0f7810ba3a493ae4db6e + languageName: node + linkType: hard + +"@cacheable/utils@npm:^2.4.1": + version: 2.4.1 + resolution: "@cacheable/utils@npm:2.4.1" + dependencies: + hashery: "npm:^1.5.1" + keyv: "npm:^5.6.0" + checksum: 10c0/ca2af47636ed27ab26dfedf12add639f42b90c289ecd5d816fb7a299074d9df463751745a83abfb81f6236a70c8ea40f0902e984869638a5ca3a7274e203f987 + languageName: node + linkType: hard + +"@emnapi/core@npm:1.10.0": + version: 1.10.0 + resolution: "@emnapi/core@npm:1.10.0" + dependencies: + "@emnapi/wasi-threads": "npm:1.2.1" + tslib: "npm:^2.4.0" + checksum: 10c0/f51d08227857b60632de7714d708124f0e100a1462dde6df8221760939aa3204a73193830371830fac0716f3ccd2129f2cac1b17cd7d7958bc4da9018a296edb + languageName: node + linkType: hard + +"@emnapi/runtime@npm:1.10.0, @emnapi/runtime@npm:^1.7.0": + version: 1.10.0 + resolution: "@emnapi/runtime@npm:1.10.0" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/953f14991d1aefb92ee6f8eb27dea725e484791a53a0cb5f47d9e0087b9a2c929ff2e92adf95af15d6ad456db6300c6b761ebf72b50a875b874a83520b3ba093 + languageName: node + linkType: hard + +"@emnapi/wasi-threads@npm:1.2.1": + version: 1.2.1 + resolution: "@emnapi/wasi-threads@npm:1.2.1" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/32fcfa81ab396533b2ec1f4082b1ff779a05d9c836bbbd3f4398405b0e6814c0d9503b7993130e37bc6941dbc1ded49f55e9700ae9ca4e803bab2b5bc5deb331 + languageName: node + linkType: hard + +"@eslint-community/eslint-utils@npm:^4.8.0": + version: 4.9.1 + resolution: "@eslint-community/eslint-utils@npm:4.9.1" + dependencies: + eslint-visitor-keys: "npm:^3.4.3" + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + checksum: 10c0/dc4ab5e3e364ef27e33666b11f4b86e1a6c1d7cbf16f0c6ff87b1619b3562335e9201a3d6ce806221887ff780ec9d828962a290bb910759fd40a674686503f02 + languageName: node + linkType: hard + +"@eslint-community/regexpp@npm:^4.12.2": + version: 4.12.2 + resolution: "@eslint-community/regexpp@npm:4.12.2" + checksum: 10c0/fddcbc66851b308478d04e302a4d771d6917a0b3740dc351513c0da9ca2eab8a1adf99f5e0aa7ab8b13fa0df005c81adeee7e63a92f3effd7d367a163b721c2d + languageName: node + linkType: hard + +"@eslint/config-array@npm:^0.23.5": + version: 0.23.5 + resolution: "@eslint/config-array@npm:0.23.5" + dependencies: + "@eslint/object-schema": "npm:^3.0.5" + debug: "npm:^4.3.1" + minimatch: "npm:^10.2.4" + checksum: 10c0/b24833c4c76e78ee075d306cd3f095db46b2db0f90cc13a6ee6e4275f9889731c05bf5403ab5fefb79c756e07ac9184ed0e04570341382f9eccbccc80e6d1a0c + languageName: node + linkType: hard + +"@eslint/config-helpers@npm:^0.5.5": + version: 0.5.5 + resolution: "@eslint/config-helpers@npm:0.5.5" + dependencies: + "@eslint/core": "npm:^1.2.1" + checksum: 10c0/18889c062cd6bdbd4cd92fe57318c44465ea66184aa0ba204a4420712c66764c64093a7905b6c2ffde23e51b268ca2cec1a39c605d336bebf17ee1ba4f0fc0bb + languageName: node + linkType: hard + +"@eslint/core@npm:^1.2.1": + version: 1.2.1 + resolution: "@eslint/core@npm:1.2.1" + dependencies: + "@types/json-schema": "npm:^7.0.15" + checksum: 10c0/10979b40588ecfef771fcb5013a542a35fb30692cc95a65f3481b0b36fbd89f5679efeb30d57f4eed35203d859aabace2a620177d6c536f71b299a1af2f3398f + languageName: node + linkType: hard + +"@eslint/object-schema@npm:^3.0.5": + version: 3.0.5 + resolution: "@eslint/object-schema@npm:3.0.5" + checksum: 10c0/1db337431f520b99e9edda64ef5fafd7ec6a029843eeb608753025125b6649d861d843cffafafd3c4e37926d7d5f9ec0c6a8e3665c13c3da2144e8132892e92e + languageName: node + linkType: hard + +"@eslint/plugin-kit@npm:^0.7.1": + version: 0.7.1 + resolution: "@eslint/plugin-kit@npm:0.7.1" + dependencies: + "@eslint/core": "npm:^1.2.1" + levn: "npm:^0.4.1" + checksum: 10c0/335b0c1c46fd906cb50bd5ce442b9cee18dc44342ce35c718ba4a63d1aa51d2797f16a517b2f4fe371ccd777b6862fafb2dc8195e00e69197ef4cb17ab32c01b + languageName: node + linkType: hard + +"@exodus/blakejs@npm:^1.1.1-exodus.0": + version: 1.1.1-exodus.0 + resolution: "@exodus/blakejs@npm:1.1.1-exodus.0" + checksum: 10c0/abd5ef599324137cddff0c33e67534532444d7031ed895894e1c8424b898aa30ffa1bb775be9daaf3d6dc71e5a2f180694e7f304c8ab876300f1b8338cf07850 + languageName: node + linkType: hard + +"@humanfs/core@npm:^0.19.2": + version: 0.19.2 + resolution: "@humanfs/core@npm:0.19.2" + dependencies: + "@humanfs/types": "npm:^0.15.0" + checksum: 10c0/d0a1d52d7b30c27d49475a53072d1510b81c5803e44b342fb8faf3887f1aa27593a1e6dc76a45268e7892d3f4e198146659281f6b6d55eacf3fd5a38bac30c5c + languageName: node + linkType: hard + +"@humanfs/node@npm:^0.16.6": + version: 0.16.8 + resolution: "@humanfs/node@npm:0.16.8" + dependencies: + "@humanfs/core": "npm:^0.19.2" + "@humanfs/types": "npm:^0.15.0" + "@humanwhocodes/retry": "npm:^0.4.0" + checksum: 10c0/56140579db811af4e160b195d45d0f29acf644d192c93fe24c9e594ebf06f19dfc157494a07c84540b8a071c0e4b37209c2362765d31734f4d0be869c2422e25 + languageName: node + linkType: hard + +"@humanfs/types@npm:^0.15.0": + version: 0.15.0 + resolution: "@humanfs/types@npm:0.15.0" + checksum: 10c0/fc26b9a024b0e55f7eaf64036df94345bf5d36d6a41ef80ef38e78f1f7430ce26cf435af736adae58913baae18eac3f38c18739054a3d379102015978eae862e + languageName: node + linkType: hard + +"@humanwhocodes/module-importer@npm:^1.0.1": + version: 1.0.1 + resolution: "@humanwhocodes/module-importer@npm:1.0.1" + checksum: 10c0/909b69c3b86d482c26b3359db16e46a32e0fb30bd306a3c176b8313b9e7313dba0f37f519de6aa8b0a1921349e505f259d19475e123182416a506d7f87e7f529 + languageName: node + linkType: hard + +"@humanwhocodes/retry@npm:^0.4.0, @humanwhocodes/retry@npm:^0.4.2": + version: 0.4.3 + resolution: "@humanwhocodes/retry@npm:0.4.3" + checksum: 10c0/3775bb30087d4440b3f7406d5a057777d90e4b9f435af488a4923ef249e93615fb78565a85f173a186a076c7706a81d0d57d563a2624e4de2c5c9c66c486ce42 + languageName: node + linkType: hard + +"@img/colour@npm:^1.0.0": + version: 1.1.0 + resolution: "@img/colour@npm:1.1.0" + checksum: 10c0/2ebea2c0bbaee73b99badcefa04e1e71d83f36e5369337d3121dca841f4569533c4e2faddda6d62dd247f0d5cca143711f9446c59bcce81e427ba433a7a94a17 + languageName: node + linkType: hard + +"@img/sharp-darwin-arm64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-darwin-arm64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-darwin-arm64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-darwin-arm64": + optional: true + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-darwin-x64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-darwin-x64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-darwin-x64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-darwin-x64": + optional: true + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@img/sharp-libvips-darwin-arm64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-darwin-arm64@npm:1.2.4" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-libvips-darwin-x64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-darwin-x64@npm:1.2.4" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-arm64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-arm64@npm:1.2.4" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-arm@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-arm@npm:1.2.4" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-ppc64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-ppc64@npm:1.2.4" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-riscv64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-riscv64@npm:1.2.4" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-s390x@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-s390x@npm:1.2.4" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linux-x64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linux-x64@npm:1.2.4" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-libvips-linuxmusl-arm64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linuxmusl-arm64@npm:1.2.4" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-libvips-linuxmusl-x64@npm:1.2.4": + version: 1.2.4 + resolution: "@img/sharp-libvips-linuxmusl-x64@npm:1.2.4" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-linux-arm64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-arm64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-arm64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-arm@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-arm@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-arm": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-arm": + optional: true + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-ppc64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-ppc64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-ppc64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-ppc64": + optional: true + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-riscv64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-riscv64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-riscv64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-riscv64": + optional: true + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-s390x@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-s390x@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-s390x": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-s390x": + optional: true + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linux-x64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linux-x64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linux-x64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linux-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@img/sharp-linuxmusl-arm64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linuxmusl-arm64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-linuxmusl-x64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-linuxmusl-x64@npm:0.34.5" + dependencies: + "@img/sharp-libvips-linuxmusl-x64": "npm:1.2.4" + dependenciesMeta: + "@img/sharp-libvips-linuxmusl-x64": + optional: true + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@img/sharp-wasm32@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-wasm32@npm:0.34.5" + dependencies: + "@emnapi/runtime": "npm:^1.7.0" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@img/sharp-win32-arm64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-win32-arm64@npm:0.34.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@img/sharp-win32-ia32@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-win32-ia32@npm:0.34.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@img/sharp-win32-x64@npm:0.34.5": + version: 0.34.5 + resolution: "@img/sharp-win32-x64@npm:0.34.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@isaacs/fs-minipass@npm:^4.0.0": + version: 4.0.1 + resolution: "@isaacs/fs-minipass@npm:4.0.1" + dependencies: + minipass: "npm:^7.0.4" + checksum: 10c0/c25b6dc1598790d5b55c0947a9b7d111cfa92594db5296c3b907e2f533c033666f692a3939eadac17b1c7c40d362d0b0635dc874cbfe3e70db7c2b07cc97a5d2 + languageName: node + linkType: hard + +"@jridgewell/sourcemap-codec@npm:^1.5.5": + version: 1.5.5 + resolution: "@jridgewell/sourcemap-codec@npm:1.5.5" + checksum: 10c0/f9e538f302b63c0ebc06eecb1dd9918dd4289ed36147a0ddce35d6ea4d7ebbda243cda7b2213b6a5e1d8087a298d5cf630fb2bd39329cdecb82017023f6081a0 + languageName: node + linkType: hard + +"@keyv/serialize@npm:^1.1.1": + version: 1.1.1 + resolution: "@keyv/serialize@npm:1.1.1" + checksum: 10c0/b0008cae4a54400c3abf587b8cc2474c6f528ee58969ce6cf9cb07a04006f80c73c85971d6be6544408318a2bc40108236a19a82aea0a6de95aae49533317374 + languageName: node + linkType: hard + +"@napi-rs/wasm-runtime@npm:^1.1.4": + version: 1.1.4 + resolution: "@napi-rs/wasm-runtime@npm:1.1.4" + dependencies: + "@tybys/wasm-util": "npm:^0.10.1" + peerDependencies: + "@emnapi/core": ^1.7.1 + "@emnapi/runtime": ^1.7.1 + checksum: 10c0/2e88e1955258949ccf2d18c79975821ad38071b465ef126a5e14110977b97868867b016c1ad046e963cccc42c0bd9db6c8ff5fd1ebb61b87bb3487f339041658 + languageName: node + linkType: hard + +"@noble/hashes@npm:^1.1.5": + version: 1.8.0 + resolution: "@noble/hashes@npm:1.8.0" + checksum: 10c0/06a0b52c81a6fa7f04d67762e08b2c476a00285858150caeaaff4037356dd5e119f45b2a530f638b77a5eeca013168ec1b655db41bae3236cb2e9d511484fc77 + languageName: node + linkType: hard + +"@oxc-project/types@npm:=0.129.0": + version: 0.129.0 + resolution: "@oxc-project/types@npm:0.129.0" + checksum: 10c0/3714ba117af387992c2e5e779eedc1ccaf5a92c4d5c9b014dcc65d5a53012f8daae7aeb28930fef9eae7516bcdc500a0e689480eb1cb44a2e02830201fce7f1a + languageName: node + linkType: hard + +"@paralleldrive/cuid2@npm:^2.2.2": + version: 2.3.1 + resolution: "@paralleldrive/cuid2@npm:2.3.1" + dependencies: + "@noble/hashes": "npm:^1.1.5" + checksum: 10c0/6576b73de49d826b0f33cbab88424dec1f6fa454a9e59a7b621f78c2cfdd2e59d7f48175826d698940a717f45eeb5e87a508583a7316e608f6a05a861a40c129 + languageName: node + linkType: hard + +"@pkgr/core@npm:^0.2.9": + version: 0.2.9 + resolution: "@pkgr/core@npm:0.2.9" + checksum: 10c0/ac8e4e8138b1a7a4ac6282873aef7389c352f1f8b577b4850778f5182e4a39a5241facbe48361fec817f56d02b51691b383010843fb08b34a8e8ea3614688fd5 + languageName: node + linkType: hard + +"@rolldown/binding-android-arm64@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-android-arm64@npm:1.0.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rolldown/binding-darwin-arm64@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-darwin-arm64@npm:1.0.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rolldown/binding-darwin-x64@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-darwin-x64@npm:1.0.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rolldown/binding-freebsd-x64@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-freebsd-x64@npm:1.0.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-linux-arm-gnueabihf@npm:1.0.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"@rolldown/binding-linux-arm64-gnu@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-linux-arm64-gnu@npm:1.0.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-arm64-musl@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-linux-arm64-musl@npm:1.0.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rolldown/binding-linux-ppc64-gnu@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-linux-ppc64-gnu@npm:1.0.0" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-s390x-gnu@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-linux-s390x-gnu@npm:1.0.0" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-x64-gnu@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-linux-x64-gnu@npm:1.0.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rolldown/binding-linux-x64-musl@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-linux-x64-musl@npm:1.0.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rolldown/binding-openharmony-arm64@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-openharmony-arm64@npm:1.0.0" + conditions: os=openharmony & cpu=arm64 + languageName: node + linkType: hard + +"@rolldown/binding-wasm32-wasi@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-wasm32-wasi@npm:1.0.0" + dependencies: + "@emnapi/core": "npm:1.10.0" + "@emnapi/runtime": "npm:1.10.0" + "@napi-rs/wasm-runtime": "npm:^1.1.4" + conditions: cpu=wasm32 + languageName: node + linkType: hard + +"@rolldown/binding-win32-arm64-msvc@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-win32-arm64-msvc@npm:1.0.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rolldown/binding-win32-x64-msvc@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/binding-win32-x64-msvc@npm:1.0.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"@rolldown/pluginutils@npm:1.0.0": + version: 1.0.0 + resolution: "@rolldown/pluginutils@npm:1.0.0" + checksum: 10c0/44aba363862f6f4defb60a6045fe236769a2307fbe8233b21ef91b728c31033e1167b5209ba7ac7c2f3b7d7738776bfd71913b42876afafab9ac406d03c6c178 + languageName: node + linkType: hard + +"@standard-schema/spec@npm:^1.1.0": + version: 1.1.0 + resolution: "@standard-schema/spec@npm:1.1.0" + checksum: 10c0/d90f55acde4b2deb983529c87e8025fa693de1a5e8b49ecc6eb84d1fd96328add0e03d7d551442156c7432fd78165b2c26ff561b970a9a881f046abb78d6a526 + languageName: node + linkType: hard + +"@tybys/wasm-util@npm:^0.10.1": + version: 0.10.2 + resolution: "@tybys/wasm-util@npm:0.10.2" + dependencies: + tslib: "npm:^2.4.0" + checksum: 10c0/26165bcd1fd7269f42d7fbe3de318f854a8968de8397e89fc9a423bb3e2da35a52150f382e6323b3367595beb16d9800a6f35971a5599daf76da1742ec3afc25 + languageName: node + linkType: hard + +"@types/body-parser@npm:*": + version: 1.19.6 + resolution: "@types/body-parser@npm:1.19.6" + dependencies: + "@types/connect": "npm:*" + "@types/node": "npm:*" + checksum: 10c0/542da05c924dce58ee23f50a8b981fee36921850c82222e384931fda3e106f750f7880c47be665217d72dbe445129049db6eb1f44e7a06b09d62af8f3cca8ea7 + languageName: node + linkType: hard + +"@types/chai@npm:^5.2.2": + version: 5.2.3 + resolution: "@types/chai@npm:5.2.3" + dependencies: + "@types/deep-eql": "npm:*" + assertion-error: "npm:^2.0.1" + checksum: 10c0/e0ef1de3b6f8045a5e473e867c8565788c444271409d155588504840ad1a53611011f85072188c2833941189400228c1745d78323dac13fcede9c2b28bacfb2f + languageName: node + linkType: hard + +"@types/connect@npm:*": + version: 3.4.38 + resolution: "@types/connect@npm:3.4.38" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/2e1cdba2c410f25649e77856505cd60223250fa12dff7a503e492208dbfdd25f62859918f28aba95315251fd1f5e1ffbfca1e25e73037189ab85dd3f8d0a148c + languageName: node + linkType: hard + +"@types/debug@npm:^4.1.13": + version: 4.1.13 + resolution: "@types/debug@npm:4.1.13" + dependencies: + "@types/ms": "npm:*" + checksum: 10c0/e5e124021bbdb23a82727eee0a726ae0fc8a3ae1f57253cbcc47497f259afb357de7f6941375e773e1abbfa1604c1555b901a409d762ec2bb4c1612131d4afb7 + languageName: node + linkType: hard + +"@types/deep-eql@npm:*": + version: 4.0.2 + resolution: "@types/deep-eql@npm:4.0.2" + checksum: 10c0/bf3f811843117900d7084b9d0c852da9a044d12eb40e6de73b552598a6843c21291a8a381b0532644574beecd5e3491c5ff3a0365ab86b15d59862c025384844 + languageName: node + linkType: hard + +"@types/esrecurse@npm:^4.3.1": + version: 4.3.1 + resolution: "@types/esrecurse@npm:4.3.1" + checksum: 10c0/90dad74d5da3ad27606d8e8e757322f33171cfeaa15ad558b615cf71bb2a516492d18f55f4816384685a3eb2412142e732bbae9a4a7cd2cf3deb7572aa4ebe03 + languageName: node + linkType: hard + +"@types/estree@npm:^1.0.0, @types/estree@npm:^1.0.6, @types/estree@npm:^1.0.8": + version: 1.0.9 + resolution: "@types/estree@npm:1.0.9" + checksum: 10c0/3ad3286ca2988cd550dafb8f2ad599c8474868e954fa601a36655bdfefd8039f7c714b8c1c7f2ae219ffbd58bd4660e66fa7479a0120fc02d4777057d4865387 + languageName: node + linkType: hard + +"@types/express-serve-static-core@npm:^5.0.0": + version: 5.1.1 + resolution: "@types/express-serve-static-core@npm:5.1.1" + dependencies: + "@types/node": "npm:*" + "@types/qs": "npm:*" + "@types/range-parser": "npm:*" + "@types/send": "npm:*" + checksum: 10c0/ee88216e114368ef06bcafeceb74a7e8671b90900fb0ab1d49ff41542c3a344231ef0d922bf63daa79f0585f3eebe2ce5ec7f83facc581eff8bcdb136a225ef3 + languageName: node + linkType: hard + +"@types/express@npm:^5.0.6": + version: 5.0.6 + resolution: "@types/express@npm:5.0.6" + dependencies: + "@types/body-parser": "npm:*" + "@types/express-serve-static-core": "npm:^5.0.0" + "@types/serve-static": "npm:^2" + checksum: 10c0/f1071e3389a955d4f9a38aae38634121c7cd9b3171ba4201ec9b56bd534aba07866839d278adc0dda05b942b05a901a02fd174201c3b1f70ce22b10b6c68f24b + languageName: node + linkType: hard + +"@types/formidable@npm:^3.5.1": + version: 3.5.1 + resolution: "@types/formidable@npm:3.5.1" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/e942ce8ebd6e12f8751f5e138bdd5ad0efb921bf1aa48c66e8e25a548d28eb2102551a47c6b2d958bd4dc9e2f41927a201c03192c2b58f526c0fdae3b0c9589c + languageName: node + linkType: hard + +"@types/http-errors@npm:*": + version: 2.0.5 + resolution: "@types/http-errors@npm:2.0.5" + checksum: 10c0/00f8140fbc504f47356512bd88e1910c2f07e04233d99c88c854b3600ce0523c8cd0ba7d1897667243282eb44c59abb9245959e2428b9de004f93937f52f7c15 + languageName: node + linkType: hard + +"@types/json-schema@npm:^7.0.15": + version: 7.0.15 + resolution: "@types/json-schema@npm:7.0.15" + checksum: 10c0/a996a745e6c5d60292f36731dd41341339d4eeed8180bb09226e5c8d23759067692b1d88e5d91d72ee83dfc00d3aca8e7bd43ea120516c17922cbcb7c3e252db + languageName: node + linkType: hard + +"@types/ms@npm:*": + version: 2.1.0 + resolution: "@types/ms@npm:2.1.0" + checksum: 10c0/5ce692ffe1549e1b827d99ef8ff71187457e0eb44adbae38fdf7b9a74bae8d20642ee963c14516db1d35fa2652e65f47680fdf679dcbde52bbfadd021f497225 + languageName: node + linkType: hard + +"@types/node@npm:*": + version: 25.7.0 + resolution: "@types/node@npm:25.7.0" + dependencies: + undici-types: "npm:~7.21.0" + checksum: 10c0/47ec7eaca154c36ad6d1ac0270e6e254eedf20b9dc49afe3bc76e4f7eba29ceac705f8903b162aeaf40e3941101ffe76ffb374989359ea3ef8c8509d8b443f55 + languageName: node + linkType: hard + +"@types/qs@npm:*": + version: 6.15.1 + resolution: "@types/qs@npm:6.15.1" + checksum: 10c0/1dfdbcb4cf2a8f66d57f0b9a9fe6b1c7091cb816687b6698c1351eaf31f62e412cea9b7453a9637b570cd5fad8dced527e5a9e69b4fcc6e318daacd8b749f094 + languageName: node + linkType: hard + +"@types/range-parser@npm:*": + version: 1.2.7 + resolution: "@types/range-parser@npm:1.2.7" + checksum: 10c0/361bb3e964ec5133fa40644a0b942279ed5df1949f21321d77de79f48b728d39253e5ce0408c9c17e4e0fd95ca7899da36841686393b9f7a1e209916e9381a3c + languageName: node + linkType: hard + +"@types/send@npm:*": + version: 1.2.1 + resolution: "@types/send@npm:1.2.1" + dependencies: + "@types/node": "npm:*" + checksum: 10c0/7673747f8c2d8e67f3b1b3b57e9d4d681801a4f7b526ecf09987bb9a84a61cf94aa411c736183884dc762c1c402a61681eb1ef200d8d45d7e5ec0ab67ea5f6c1 + languageName: node + linkType: hard + +"@types/serve-static@npm:^2": + version: 2.2.0 + resolution: "@types/serve-static@npm:2.2.0" + dependencies: + "@types/http-errors": "npm:*" + "@types/node": "npm:*" + checksum: 10c0/a3c6126bdbf9685e6c7dc03ad34639666eff32754e912adeed9643bf3dd3aa0ff043002a7f69039306e310d233eb8e160c59308f95b0a619f32366bbc48ee094 + languageName: node + linkType: hard + +"@vitest/expect@npm:4.1.6": + version: 4.1.6 + resolution: "@vitest/expect@npm:4.1.6" + dependencies: + "@standard-schema/spec": "npm:^1.1.0" + "@types/chai": "npm:^5.2.2" + "@vitest/spy": "npm:4.1.6" + "@vitest/utils": "npm:4.1.6" + chai: "npm:^6.2.2" + tinyrainbow: "npm:^3.1.0" + checksum: 10c0/a6767bdf586c82f64674998bf74987e99aa106ac5d0b5c4c2c1d3924e145b34fd80e138c65568a8fc2544aa71c85b1272f9607fe5ef6a7060ece1c232db46655 + languageName: node + linkType: hard + +"@vitest/mocker@npm:4.1.6": + version: 4.1.6 + resolution: "@vitest/mocker@npm:4.1.6" + dependencies: + "@vitest/spy": "npm:4.1.6" + estree-walker: "npm:^3.0.3" + magic-string: "npm:^0.30.21" + peerDependencies: + msw: ^2.4.9 + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + msw: + optional: true + vite: + optional: true + checksum: 10c0/d9f3236940e160467edb7a2552fa014451347c4f08c13d26220fcfe7e12b385fd4975c6a81a6b174117650772cf3c45195b3a1838f8ee28fc8e6c37e07b99b2d + languageName: node + linkType: hard + +"@vitest/pretty-format@npm:4.1.6": + version: 4.1.6 + resolution: "@vitest/pretty-format@npm:4.1.6" + dependencies: + tinyrainbow: "npm:^3.1.0" + checksum: 10c0/f818a6abff9b7cf642edc2d0fe84d4f124911696bc7591f2af9ab6d88685b72133a1e9f87499e9b4dc2314dff85403ea66c64f7b408b2eb39f9880c6d3517ca0 + languageName: node + linkType: hard + +"@vitest/runner@npm:4.1.6": + version: 4.1.6 + resolution: "@vitest/runner@npm:4.1.6" + dependencies: + "@vitest/utils": "npm:4.1.6" + pathe: "npm:^2.0.3" + checksum: 10c0/8047051d730de66b7cde8e6803ea718eaa8342ffbe55ff3d787fe7085a2b824a979689782d5303e464411fe67b556384b0c5af337e3e335cf140bf7adf5f6aa0 + languageName: node + linkType: hard + +"@vitest/snapshot@npm:4.1.6": + version: 4.1.6 + resolution: "@vitest/snapshot@npm:4.1.6" + dependencies: + "@vitest/pretty-format": "npm:4.1.6" + "@vitest/utils": "npm:4.1.6" + magic-string: "npm:^0.30.21" + pathe: "npm:^2.0.3" + checksum: 10c0/596d7cd2fe12b57516e983e550d238c324a3cefaac826e557b0903cfbb11f6ff79582bf2df6dc3163cf604c305ffe3840e47f03a95b8fb8d7bf6200462e8cfea + languageName: node + linkType: hard + +"@vitest/spy@npm:4.1.6": + version: 4.1.6 + resolution: "@vitest/spy@npm:4.1.6" + checksum: 10c0/908034532fb10888f759603194b11058bdabdf9bb86ef7839feec98f809e4802cf8d74c279c521ef2df12fa9ab97d0aec7c886e1e6910c5c9dfb10ba00913d91 + languageName: node + linkType: hard + +"@vitest/utils@npm:4.1.6": + version: 4.1.6 + resolution: "@vitest/utils@npm:4.1.6" + dependencies: + "@vitest/pretty-format": "npm:4.1.6" + convert-source-map: "npm:^2.0.0" + tinyrainbow: "npm:^3.1.0" + checksum: 10c0/36437888088a1aae8565e62b9f145de9fb1599725574924477c655c7617ad677b575ac0eb3f2b3288854ed1aafff914a0417dffbb7f5244c821f157119701227 + languageName: node + linkType: hard + +"abbrev@npm:^4.0.0": + version: 4.0.0 + resolution: "abbrev@npm:4.0.0" + checksum: 10c0/b4cc16935235e80702fc90192e349e32f8ef0ed151ef506aa78c81a7c455ec18375c4125414b99f84b2e055199d66383e787675f0bcd87da7a4dbd59f9eac1d5 + languageName: node + linkType: hard + +"accepts@npm:^2.0.0": + version: 2.0.0 + resolution: "accepts@npm:2.0.0" + dependencies: + mime-types: "npm:^3.0.0" + negotiator: "npm:^1.0.0" + checksum: 10c0/98374742097e140891546076215f90c32644feacf652db48412329de4c2a529178a81aa500fbb13dd3e6cbf6e68d829037b123ac037fc9a08bcec4b87b358eef + languageName: node + linkType: hard + +"acorn-jsx@npm:^5.3.2": + version: 5.3.2 + resolution: "acorn-jsx@npm:5.3.2" + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + checksum: 10c0/4c54868fbef3b8d58927d5e33f0a4de35f59012fe7b12cf9dfbb345fb8f46607709e1c4431be869a23fb63c151033d84c4198fa9f79385cec34fcb1dd53974c1 + languageName: node + linkType: hard + +"acorn@npm:^8.16.0": + version: 8.16.0 + resolution: "acorn@npm:8.16.0" + bin: + acorn: bin/acorn + checksum: 10c0/c9c52697227661b68d0debaf972222d4f622aa06b185824164e153438afa7b08273432ca43ea792cadb24dada1d46f6f6bb1ef8de9956979288cc1b96bf9914e + languageName: node + linkType: hard + +"ajv@npm:^6.14.0": + version: 6.15.0 + resolution: "ajv@npm:6.15.0" + dependencies: + fast-deep-equal: "npm:^3.1.1" + fast-json-stable-stringify: "npm:^2.0.0" + json-schema-traverse: "npm:^0.4.1" + uri-js: "npm:^4.2.2" + checksum: 10c0/67966499dd272ecde1c2e467084411132891523d057487587879d39ac04207f4351b7b2324c83198013967fbfa632c1612adc960114a30770fbe07a0773b32c2 + languageName: node + linkType: hard + +"asap@npm:^2.0.0": + version: 2.0.6 + resolution: "asap@npm:2.0.6" + checksum: 10c0/c6d5e39fe1f15e4b87677460bd66b66050cd14c772269cee6688824c1410a08ab20254bb6784f9afb75af9144a9f9a7692d49547f4d19d715aeb7c0318f3136d + languageName: node + linkType: hard + +"asn1.js@npm:^5.4.1": + version: 5.4.1 + resolution: "asn1.js@npm:5.4.1" + dependencies: + bn.js: "npm:^4.0.0" + inherits: "npm:^2.0.1" + minimalistic-assert: "npm:^1.0.0" + safer-buffer: "npm:^2.1.0" + checksum: 10c0/b577232fa6069cc52bb128e564002c62b2b1fe47f7137bdcd709c0b8495aa79cee0f8cc458a831b2d8675900eea0d05781b006be5e1aa4f0ae3577a73ec20324 + languageName: node + linkType: hard + +"assertion-error@npm:^2.0.1": + version: 2.0.1 + resolution: "assertion-error@npm:2.0.1" + checksum: 10c0/bbbcb117ac6480138f8c93cf7f535614282dea9dc828f540cdece85e3c665e8f78958b96afac52f29ff883c72638e6a87d469ecc9fe5bc902df03ed24a55dba8 + languageName: node + linkType: hard + +"async-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-function@npm:1.0.0" + checksum: 10c0/669a32c2cb7e45091330c680e92eaeb791bc1d4132d827591e499cd1f776ff5a873e77e5f92d0ce795a8d60f10761dec9ddfe7225a5de680f5d357f67b1aac73 + languageName: node + linkType: hard + +"async-generator-function@npm:^1.0.0": + version: 1.0.0 + resolution: "async-generator-function@npm:1.0.0" + checksum: 10c0/2c50ef856c543ad500d8d8777d347e3c1ba623b93e99c9263ecc5f965c1b12d2a140e2ab6e43c3d0b85366110696f28114649411cbcd10b452a92a2318394186 + languageName: node + linkType: hard + +"bagpipe@npm:^0.3.5": + version: 0.3.5 + resolution: "bagpipe@npm:0.3.5" + checksum: 10c0/0fc6d3bb283ac93b00b943e8aa541ccb1e3a17a627ca25d72585ef18a286558861d41662c62e4040b9f5fe93ad927aa6cd5153798971e6ebf1a9e748da25aee1 + languageName: node + linkType: hard + +"balanced-match@npm:^4.0.2": + version: 4.0.4 + resolution: "balanced-match@npm:4.0.4" + checksum: 10c0/07e86102a3eb2ee2a6a1a89164f29d0dbaebd28f2ca3f5ca786f36b8b23d9e417eb3be45a4acf754f837be5ac0a2317de90d3fcb7f4f4dc95720a1f36b26a17b + languageName: node + linkType: hard + +"base32.js@npm:^0.1.0": + version: 0.1.0 + resolution: "base32.js@npm:0.1.0" + checksum: 10c0/d5f520f8082193850df798a0a64c528eb56b25d507daa94393c39342cc07c41e1e8e3fae71dc318e397b9e28cee800548f582493018d46962b20fce8735efaad + languageName: node + linkType: hard + +"bcryptjs@npm:^3.0.3": + version: 3.0.3 + resolution: "bcryptjs@npm:3.0.3" + bin: + bcrypt: bin/bcrypt + checksum: 10c0/127c94699f07eab5fbbb89d600c3f0e36ae6fd001e028139740b41fffb62a23a2743523fb88f442ae3308a27d4843b97ccb9e436d78f5c5899be187d0972c6d5 + languageName: node + linkType: hard + +"bn.js@npm:^4.0.0": + version: 4.12.3 + resolution: "bn.js@npm:4.12.3" + checksum: 10c0/53b6a4db8a583abd2522eacd480fece26fe6c4d8d35d03e5e11e15cb0873a3044eb4e3d1f9fef56f47eb008219e99ba5b620c26f57db49a687c6ab2cf848d50b + languageName: node + linkType: hard + +"body-parser@npm:^2.2.1": + version: 2.2.2 + resolution: "body-parser@npm:2.2.2" + dependencies: + bytes: "npm:^3.1.2" + content-type: "npm:^1.0.5" + debug: "npm:^4.4.3" + http-errors: "npm:^2.0.0" + iconv-lite: "npm:^0.7.0" + on-finished: "npm:^2.4.1" + qs: "npm:^6.14.1" + raw-body: "npm:^3.0.1" + type-is: "npm:^2.0.1" + checksum: 10c0/95a830a003b38654b75166ca765358aa92ee3d561bf0e41d6ccdde0e1a0c9783cab6b90b20eb635d23172c010b59d3563a137a738e74da4ba714463510d05137 + languageName: node + linkType: hard + +"brace-expansion@npm:^5.0.5": + version: 5.0.6 + resolution: "brace-expansion@npm:5.0.6" + dependencies: + balanced-match: "npm:^4.0.2" + checksum: 10c0/8c919869b90f61d533b341d3340be5ee4413232ea89b8246cbc2f38eb014f1d8182785c98a006eaf6111d02dc9eeffefdc240d5ac158625b2ed084dccd4bbf9b + languageName: node + linkType: hard + +"buffer-equal-constant-time@npm:^1.0.1": + version: 1.0.1 + resolution: "buffer-equal-constant-time@npm:1.0.1" + checksum: 10c0/fb2294e64d23c573d0dd1f1e7a466c3e978fe94a4e0f8183937912ca374619773bef8e2aceb854129d2efecbbc515bbd0cc78d2734a3e3031edb0888531bbc8e + languageName: node + linkType: hard + +"bytes@npm:^3.1.2, bytes@npm:~3.1.2": + version: 3.1.2 + resolution: "bytes@npm:3.1.2" + checksum: 10c0/76d1c43cbd602794ad8ad2ae94095cddeb1de78c5dddaa7005c51af10b0176c69971a6d88e805a90c2b6550d76636e43c40d8427a808b8645ede885de4a0358e + languageName: node + linkType: hard + +"call-bind-apply-helpers@npm:^1.0.1, call-bind-apply-helpers@npm:^1.0.2": + version: 1.0.2 + resolution: "call-bind-apply-helpers@npm:1.0.2" + dependencies: + es-errors: "npm:^1.3.0" + function-bind: "npm:^1.1.2" + checksum: 10c0/47bd9901d57b857590431243fea704ff18078b16890a6b3e021e12d279bbf211d039155e27d7566b374d49ee1f8189344bac9833dec7a20cdec370506361c938 + languageName: node + linkType: hard + +"call-bound@npm:^1.0.2": + version: 1.0.4 + resolution: "call-bound@npm:1.0.4" + dependencies: + call-bind-apply-helpers: "npm:^1.0.2" + get-intrinsic: "npm:^1.3.0" + checksum: 10c0/f4796a6a0941e71c766aea672f63b72bc61234c4f4964dc6d7606e3664c307e7d77845328a8f3359ce39ddb377fed67318f9ee203dea1d47e46165dcf2917644 + languageName: node + linkType: hard + +"chai@npm:^6.2.2": + version: 6.2.2 + resolution: "chai@npm:6.2.2" + checksum: 10c0/e6c69e5f0c11dffe6ea13d0290936ebb68fcc1ad688b8e952e131df6a6d5797d5e860bc55cef1aca2e950c3e1f96daf79e9d5a70fb7dbaab4e46355e2635ed53 + languageName: node + linkType: hard + +"chownr@npm:^3.0.0": + version: 3.0.0 + resolution: "chownr@npm:3.0.0" + checksum: 10c0/43925b87700f7e3893296c8e9c56cc58f926411cce3a6e5898136daaf08f08b9a8eb76d37d3267e707d0dcc17aed2e2ebdf5848c0c3ce95cf910a919935c1b10 + languageName: node + linkType: hard + +"content-disposition@npm:^1.0.0": + version: 1.1.0 + resolution: "content-disposition@npm:1.1.0" + checksum: 10c0/94e0aef65873e69330f5f187fbc44ebce593bdcb8013dd8a68b7d0f159ca089bd30db3f8095d829f81c341695b60a6085ee6e15e6d775c4a325b586cc8d91974 + languageName: node + linkType: hard + +"content-type@npm:^1.0.5": + version: 1.0.5 + resolution: "content-type@npm:1.0.5" + checksum: 10c0/b76ebed15c000aee4678c3707e0860cb6abd4e680a598c0a26e17f0bfae723ec9cc2802f0ff1bc6e4d80603719010431d2231018373d4dde10f9ccff9dadf5af + languageName: node + linkType: hard + +"convert-source-map@npm:^2.0.0": + version: 2.0.0 + resolution: "convert-source-map@npm:2.0.0" + checksum: 10c0/8f2f7a27a1a011cc6cc88cc4da2d7d0cfa5ee0369508baae3d98c260bb3ac520691464e5bbe4ae7cdf09860c1d69ecc6f70c63c6e7c7f7e3f18ec08484dc7d9b + languageName: node + linkType: hard + +"cookie-parser@npm:^1.4.7": + version: 1.4.7 + resolution: "cookie-parser@npm:1.4.7" + dependencies: + cookie: "npm:0.7.2" + cookie-signature: "npm:1.0.6" + checksum: 10c0/46bef553de409031b69a6074ce512d131a98e4fa12612669f1a9c3dd98d56897a31db86a3f4338d4a3a895c6f8d5cfd6fa4d99cdf588e0e8eda655efc3f384dc + languageName: node + linkType: hard + +"cookie-signature@npm:1.0.6": + version: 1.0.6 + resolution: "cookie-signature@npm:1.0.6" + checksum: 10c0/b36fd0d4e3fef8456915fcf7742e58fbfcc12a17a018e0eb9501c9d5ef6893b596466f03b0564b81af29ff2538fd0aa4b9d54fe5ccbfb4c90ea50ad29fe2d221 + languageName: node + linkType: hard + +"cookie-signature@npm:^1.2.1": + version: 1.2.2 + resolution: "cookie-signature@npm:1.2.2" + checksum: 10c0/54e05df1a293b3ce81589b27dddc445f462f6fa6812147c033350cd3561a42bc14481674e05ed14c7bd0ce1e8bb3dc0e40851bad75415733711294ddce0b7bc6 + languageName: node + linkType: hard + +"cookie-signature@npm:~1.0.7": + version: 1.0.7 + resolution: "cookie-signature@npm:1.0.7" + checksum: 10c0/e7731ad2995ae2efeed6435ec1e22cdd21afef29d300c27281438b1eab2bae04ef0d1a203928c0afec2cee72aa36540b8747406ebe308ad23c8e8cc3c26c9c51 + languageName: node + linkType: hard + +"cookie@npm:0.7.2, cookie@npm:^0.7.1, cookie@npm:~0.7.2": + version: 0.7.2 + resolution: "cookie@npm:0.7.2" + checksum: 10c0/9596e8ccdbf1a3a88ae02cf5ee80c1c50959423e1022e4e60b91dd87c622af1da309253d8abdb258fb5e3eacb4f08e579dc58b4897b8087574eee0fd35dfa5d2 + languageName: node + linkType: hard + +"cross-spawn@npm:^7.0.6": + version: 7.0.6 + resolution: "cross-spawn@npm:7.0.6" + dependencies: + path-key: "npm:^3.1.0" + shebang-command: "npm:^2.0.0" + which: "npm:^2.0.1" + checksum: 10c0/053ea8b2135caff68a9e81470e845613e374e7309a47731e81639de3eaeb90c3d01af0e0b44d2ab9d50b43467223b88567dfeb3262db942dc063b9976718ffc1 + languageName: node + linkType: hard + +"dayjs@npm:^1.11.20": + version: 1.11.20 + resolution: "dayjs@npm:1.11.20" + checksum: 10c0/8af525e2aa100c8db9923d706c42b2b2d30579faf89456619413a5c10916efc92c2b166e193c27c02eb3174b30aa440ee1e7b72b0a2876b3da651d204db848a0 + languageName: node + linkType: hard + +"debug@npm:^4.3.1, debug@npm:^4.3.2, debug@npm:^4.4.0, debug@npm:^4.4.3": + version: 4.4.3 + resolution: "debug@npm:4.4.3" + dependencies: + ms: "npm:^2.1.3" + peerDependenciesMeta: + supports-color: + optional: true + checksum: 10c0/d79136ec6c83ecbefd0f6a5593da6a9c91ec4d7ddc4b54c883d6e71ec9accb5f67a1a5e96d00a328196b5b5c86d365e98d8a3a70856aaf16b4e7b1985e67f5a6 + languageName: node + linkType: hard + +"debug@npm:~2.6.9": + version: 2.6.9 + resolution: "debug@npm:2.6.9" + dependencies: + ms: "npm:2.0.0" + checksum: 10c0/121908fb839f7801180b69a7e218a40b5a0b718813b886b7d6bdb82001b931c938e2941d1e4450f33a1b1df1da653f5f7a0440c197f29fbf8a6e9d45ff6ef589 + languageName: node + linkType: hard + +"deep-is@npm:^0.1.3": + version: 0.1.4 + resolution: "deep-is@npm:0.1.4" + checksum: 10c0/7f0ee496e0dff14a573dc6127f14c95061b448b87b995fc96c017ce0a1e66af1675e73f1d6064407975bc4ea6ab679497a29fff7b5b9c4e99cb10797c1ad0b4c + languageName: node + linkType: hard + +"depd@npm:^2.0.0, depd@npm:~2.0.0": + version: 2.0.0 + resolution: "depd@npm:2.0.0" + checksum: 10c0/58bd06ec20e19529b06f7ad07ddab60e504d9e0faca4bd23079fac2d279c3594334d736508dc350e06e510aba5e22e4594483b3a6562ce7c17dd797f4cc4ad2c + languageName: node + linkType: hard + +"detect-libc@npm:^2.0.3, detect-libc@npm:^2.1.2": + version: 2.1.2 + resolution: "detect-libc@npm:2.1.2" + checksum: 10c0/acc675c29a5649fa1fb6e255f993b8ee829e510b6b56b0910666949c80c364738833417d0edb5f90e4e46be17228b0f2b66a010513984e18b15deeeac49369c4 + languageName: node + linkType: hard + +"dezalgo@npm:^1.0.4": + version: 1.0.4 + resolution: "dezalgo@npm:1.0.4" + dependencies: + asap: "npm:^2.0.0" + wrappy: "npm:1" + checksum: 10c0/8a870ed42eade9a397e6141fe5c025148a59ed52f1f28b1db5de216b4d57f0af7a257070c3af7ce3d5508c1ce9dd5009028a76f4b2cc9370dc56551d2355fad8 + languageName: node + linkType: hard + +"dunder-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "dunder-proto@npm:1.0.1" + dependencies: + call-bind-apply-helpers: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + gopd: "npm:^1.2.0" + checksum: 10c0/199f2a0c1c16593ca0a145dbf76a962f8033ce3129f01284d48c45ed4e14fea9bbacd7b3610b6cdc33486cef20385ac054948fefc6272fcce645c09468f93031 + languageName: node + linkType: hard + +"ecdsa-sig-formatter@npm:1.0.11": + version: 1.0.11 + resolution: "ecdsa-sig-formatter@npm:1.0.11" + dependencies: + safe-buffer: "npm:^5.0.1" + checksum: 10c0/ebfbf19d4b8be938f4dd4a83b8788385da353d63307ede301a9252f9f7f88672e76f2191618fd8edfc2f24679236064176fab0b78131b161ee73daa37125408c + languageName: node + linkType: hard + +"ee-first@npm:1.1.1": + version: 1.1.1 + resolution: "ee-first@npm:1.1.1" + checksum: 10c0/b5bb125ee93161bc16bfe6e56c6b04de5ad2aa44234d8f644813cc95d861a6910903132b05093706de2b706599367c4130eb6d170f6b46895686b95f87d017b7 + languageName: node + linkType: hard + +"encodeurl@npm:^2.0.0": + version: 2.0.0 + resolution: "encodeurl@npm:2.0.0" + checksum: 10c0/5d317306acb13e6590e28e27924c754163946a2480de11865c991a3a7eed4315cd3fba378b543ca145829569eefe9b899f3d84bb09870f675ae60bc924b01ceb + languageName: node + linkType: hard + +"env-paths@npm:^2.2.0": + version: 2.2.1 + resolution: "env-paths@npm:2.2.1" + checksum: 10c0/285325677bf00e30845e330eec32894f5105529db97496ee3f598478e50f008c5352a41a30e5e72ec9de8a542b5a570b85699cd63bd2bc646dbcb9f311d83bc4 + languageName: node + linkType: hard + +"es-define-property@npm:^1.0.1": + version: 1.0.1 + resolution: "es-define-property@npm:1.0.1" + checksum: 10c0/3f54eb49c16c18707949ff25a1456728c883e81259f045003499efba399c08bad00deebf65cccde8c0e07908c1a225c9d472b7107e558f2a48e28d530e34527c + languageName: node + linkType: hard + +"es-errors@npm:^1.3.0": + version: 1.3.0 + resolution: "es-errors@npm:1.3.0" + checksum: 10c0/0a61325670072f98d8ae3b914edab3559b6caa980f08054a3b872052640d91da01d38df55df797fcc916389d77fc92b8d5906cf028f4db46d7e3003abecbca85 + languageName: node + linkType: hard + +"es-module-lexer@npm:^2.0.0": + version: 2.1.0 + resolution: "es-module-lexer@npm:2.1.0" + checksum: 10c0/93bcf2454fa72d67fe3ccd0abef8ce7933f5840a319513418a643dd8e9c6aa8f49709cecfae02ded722805dd327232d30723a807cc52e6809d6ac697c62c29fb + languageName: node + linkType: hard + +"es-object-atoms@npm:^1.0.0, es-object-atoms@npm:^1.1.1": + version: 1.1.1 + resolution: "es-object-atoms@npm:1.1.1" + dependencies: + es-errors: "npm:^1.3.0" + checksum: 10c0/65364812ca4daf48eb76e2a3b7a89b3f6a2e62a1c420766ce9f692665a29d94fe41fe88b65f24106f449859549711e4b40d9fb8002d862dfd7eb1c512d10be0c + languageName: node + linkType: hard + +"escape-html@npm:^1.0.3": + version: 1.0.3 + resolution: "escape-html@npm:1.0.3" + checksum: 10c0/524c739d776b36c3d29fa08a22e03e8824e3b2fd57500e5e44ecf3cc4707c34c60f9ca0781c0e33d191f2991161504c295e98f68c78fe7baa6e57081ec6ac0a3 + languageName: node + linkType: hard + +"escape-string-regexp@npm:^4.0.0": + version: 4.0.0 + resolution: "escape-string-regexp@npm:4.0.0" + checksum: 10c0/9497d4dd307d845bd7f75180d8188bb17ea8c151c1edbf6b6717c100e104d629dc2dfb687686181b0f4b7d732c7dfdc4d5e7a8ff72de1b0ca283a75bbb3a9cd9 + languageName: node + linkType: hard + +"eslint-config-prettier@npm:^10.1.8": + version: 10.1.8 + resolution: "eslint-config-prettier@npm:10.1.8" + peerDependencies: + eslint: ">=7.0.0" + bin: + eslint-config-prettier: bin/cli.js + checksum: 10c0/e1bcfadc9eccd526c240056b1e59c5cd26544fe59feb85f38f4f1f116caed96aea0b3b87868e68b3099e55caaac3f2e5b9f58110f85db893e83a332751192682 + languageName: node + linkType: hard + +"eslint-plugin-prettier@npm:^5.5.5": + version: 5.5.5 + resolution: "eslint-plugin-prettier@npm:5.5.5" + dependencies: + prettier-linter-helpers: "npm:^1.0.1" + synckit: "npm:^0.11.12" + peerDependencies: + "@types/eslint": ">=8.0.0" + eslint: ">=8.0.0" + eslint-config-prettier: ">= 7.0.0 <10.0.0 || >=10.1.0" + prettier: ">=3.0.0" + peerDependenciesMeta: + "@types/eslint": + optional: true + eslint-config-prettier: + optional: true + checksum: 10c0/091449b28c77ab2efbbf674e977181f2c8453d95a4df68218bddd87a4dfaa9ecc4eda60164e416f5986fb5d577e66e8d8e1e23d81e8555f8d735375598b03257 + languageName: node + linkType: hard + +"eslint-plugin-security@npm:^4.0.0": + version: 4.0.0 + resolution: "eslint-plugin-security@npm:4.0.0" + dependencies: + safe-regex: "npm:^2.1.1" + checksum: 10c0/559f315d7ad6131f1bc1cd5738dc82f6eecab7fec12134049a0420b50b59e2ab11e0cbc676ddeae84b111014102ecc7433dfe8b11d1f012821a7628610c8500d + languageName: node + linkType: hard + +"eslint-scope@npm:^9.1.2": + version: 9.1.2 + resolution: "eslint-scope@npm:9.1.2" + dependencies: + "@types/esrecurse": "npm:^4.3.1" + "@types/estree": "npm:^1.0.8" + esrecurse: "npm:^4.3.0" + estraverse: "npm:^5.2.0" + checksum: 10c0/9fb8bca5a73e5741efb6cec84467027b6cb6f4203ff9b43a938e272c5cd30800bde46a5c20dfd1609f840225f0b62b7673be391b20acadf8658ca9fa4729b3dd + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^3.4.3": + version: 3.4.3 + resolution: "eslint-visitor-keys@npm:3.4.3" + checksum: 10c0/92708e882c0a5ffd88c23c0b404ac1628cf20104a108c745f240a13c332a11aac54f49a22d5762efbffc18ecbc9a580d1b7ad034bf5f3cc3307e5cbff2ec9820 + languageName: node + linkType: hard + +"eslint-visitor-keys@npm:^5.0.1": + version: 5.0.1 + resolution: "eslint-visitor-keys@npm:5.0.1" + checksum: 10c0/16190bdf2cbae40a1109384c94450c526a79b0b9c3cb21e544256ed85ac48a4b84db66b74a6561d20fe6ab77447f150d711c2ad5ad74df4fcc133736bce99678 + languageName: node + linkType: hard + +"eslint@npm:^10.3.0": + version: 10.3.0 + resolution: "eslint@npm:10.3.0" + dependencies: + "@eslint-community/eslint-utils": "npm:^4.8.0" + "@eslint-community/regexpp": "npm:^4.12.2" + "@eslint/config-array": "npm:^0.23.5" + "@eslint/config-helpers": "npm:^0.5.5" + "@eslint/core": "npm:^1.2.1" + "@eslint/plugin-kit": "npm:^0.7.1" + "@humanfs/node": "npm:^0.16.6" + "@humanwhocodes/module-importer": "npm:^1.0.1" + "@humanwhocodes/retry": "npm:^0.4.2" + "@types/estree": "npm:^1.0.6" + ajv: "npm:^6.14.0" + cross-spawn: "npm:^7.0.6" + debug: "npm:^4.3.2" + escape-string-regexp: "npm:^4.0.0" + eslint-scope: "npm:^9.1.2" + eslint-visitor-keys: "npm:^5.0.1" + espree: "npm:^11.2.0" + esquery: "npm:^1.7.0" + esutils: "npm:^2.0.2" + fast-deep-equal: "npm:^3.1.3" + file-entry-cache: "npm:^8.0.0" + find-up: "npm:^5.0.0" + glob-parent: "npm:^6.0.2" + ignore: "npm:^5.2.0" + imurmurhash: "npm:^0.1.4" + is-glob: "npm:^4.0.0" + json-stable-stringify-without-jsonify: "npm:^1.0.1" + minimatch: "npm:^10.2.4" + natural-compare: "npm:^1.4.0" + optionator: "npm:^0.9.3" + peerDependencies: + jiti: "*" + peerDependenciesMeta: + jiti: + optional: true + bin: + eslint: bin/eslint.js + checksum: 10c0/81e3ceba949f62d1b530660279db86cf814f5dc43d7cc3759a8008fe4fc679d46568279fe1cceb7ddbbc98ab57a96ae524f6e811ffc6897b49b90ea08aa785e5 + languageName: node + linkType: hard + +"espree@npm:^11.2.0": + version: 11.2.0 + resolution: "espree@npm:11.2.0" + dependencies: + acorn: "npm:^8.16.0" + acorn-jsx: "npm:^5.3.2" + eslint-visitor-keys: "npm:^5.0.1" + checksum: 10c0/cf87e18ffd9dc113eb8d16588e7757701bc10c9934a71cce8b89c2611d51672681a918307bd6b19ac3ccd0e7ba1cbccc2f815b36b52fa7e73097b251014c3d81 + languageName: node + linkType: hard + +"esquery@npm:^1.7.0": + version: 1.7.0 + resolution: "esquery@npm:1.7.0" + dependencies: + estraverse: "npm:^5.1.0" + checksum: 10c0/77d5173db450b66f3bc685d11af4c90cffeedb340f34a39af96d43509a335ce39c894fd79233df32d38f5e4e219fa0f7076f6ec90bae8320170ba082c0db4793 + languageName: node + linkType: hard + +"esrecurse@npm:^4.3.0": + version: 4.3.0 + resolution: "esrecurse@npm:4.3.0" + dependencies: + estraverse: "npm:^5.2.0" + checksum: 10c0/81a37116d1408ded88ada45b9fb16dbd26fba3aadc369ce50fcaf82a0bac12772ebd7b24cd7b91fc66786bf2c1ac7b5f196bc990a473efff972f5cb338877cf5 + languageName: node + linkType: hard + +"estraverse@npm:^5.1.0, estraverse@npm:^5.2.0": + version: 5.3.0 + resolution: "estraverse@npm:5.3.0" + checksum: 10c0/1ff9447b96263dec95d6d67431c5e0771eb9776427421260a3e2f0fdd5d6bd4f8e37a7338f5ad2880c9f143450c9b1e4fc2069060724570a49cf9cf0312bd107 + languageName: node + linkType: hard + +"estree-walker@npm:^3.0.3": + version: 3.0.3 + resolution: "estree-walker@npm:3.0.3" + dependencies: + "@types/estree": "npm:^1.0.0" + checksum: 10c0/c12e3c2b2642d2bcae7d5aa495c60fa2f299160946535763969a1c83fc74518ffa9c2cd3a8b69ac56aea547df6a8aac25f729a342992ef0bbac5f1c73e78995d + languageName: node + linkType: hard + +"esutils@npm:^2.0.2": + version: 2.0.3 + resolution: "esutils@npm:2.0.3" + checksum: 10c0/9a2fe69a41bfdade834ba7c42de4723c97ec776e40656919c62cbd13607c45e127a003f05f724a1ea55e5029a4cf2de444b13009f2af71271e42d93a637137c7 + languageName: node + linkType: hard + +"etag@npm:^1.8.1": + version: 1.8.1 + resolution: "etag@npm:1.8.1" + checksum: 10c0/12be11ef62fb9817314d790089a0a49fae4e1b50594135dcb8076312b7d7e470884b5100d249b28c18581b7fd52f8b485689ffae22a11ed9ec17377a33a08f84 + languageName: node + linkType: hard + +"expect-type@npm:^1.3.0": + version: 1.3.0 + resolution: "expect-type@npm:1.3.0" + checksum: 10c0/8412b3fe4f392c420ab41dae220b09700e4e47c639a29ba7ba2e83cc6cffd2b4926f7ac9e47d7e277e8f4f02acda76fd6931cb81fd2b382fa9477ef9ada953fd + languageName: node + linkType: hard + +"exponential-backoff@npm:^3.1.1": + version: 3.1.3 + resolution: "exponential-backoff@npm:3.1.3" + checksum: 10c0/77e3ae682b7b1f4972f563c6dbcd2b0d54ac679e62d5d32f3e5085feba20483cf28bd505543f520e287a56d4d55a28d7874299941faf637e779a1aa5994d1267 + languageName: node + linkType: hard + +"express-rate-limit@npm:8, express-rate-limit@npm:^8.5.0": + version: 8.5.1 + resolution: "express-rate-limit@npm:8.5.1" + dependencies: + ip-address: "npm:^10.2.0" + peerDependencies: + express: ">= 4.11" + checksum: 10c0/bcd89bb916376f38858b2623cc486bc9a91124ff3c7dee038fafc4c03949db72b0ddc796ade17cc43af3f16af314b689dd3c6557996d8e007791151335b0f7f7 + languageName: node + linkType: hard + +"express-session@npm:^1.19.0": + version: 1.19.0 + resolution: "express-session@npm:1.19.0" + dependencies: + cookie: "npm:~0.7.2" + cookie-signature: "npm:~1.0.7" + debug: "npm:~2.6.9" + depd: "npm:~2.0.0" + on-headers: "npm:~1.1.0" + parseurl: "npm:~1.3.3" + safe-buffer: "npm:~5.2.1" + uid-safe: "npm:~2.1.5" + checksum: 10c0/b1766010a728c58ca1b93ea33d49008b0b16a8751e5767d36b5bf3dd2f7f77d9933bb55352d296edbad4824c8c65e33554f058a33f201406557c1b3615fd10dc + languageName: node + linkType: hard + +"express-slow-down@npm:^3.1.0": + version: 3.1.0 + resolution: "express-slow-down@npm:3.1.0" + dependencies: + express-rate-limit: "npm:8" + peerDependencies: + express: 4 || 5 || ^5.0.0-beta.1 + checksum: 10c0/58c4494ed8d84fa52c3bc9b820e7f2a06059e2c70afa3323f1f009031f8438c978eed0e7b8d4eeb066489b6e8a8635dd812ecdf66a4b6b67971ce418ed4d6256 + languageName: node + linkType: hard + +"express-twtkpr-core-plugins@workspace:.": version: 0.0.0-use.local - resolution: "express-twtkpr-upload-button@workspace:." + resolution: "express-twtkpr-core-plugins@workspace:." + dependencies: + "@types/debug": "npm:^4.1.13" + "@types/express": "npm:^5.0.6" + "@types/formidable": "npm:^3.5.1" + debug: "npm:^4.4.3" + eslint: "npm:^10.3.0" + eslint-config-prettier: "npm:^10.1.8" + eslint-plugin-prettier: "npm:^5.5.5" + eslint-plugin-security: "npm:^4.0.0" + express: "npm:^5.2.1" + express-twtkpr: "npm:^0.9.0" + formidable: "npm:^3.5.4" + prettier: "npm:^3.8.3" + sharp: "npm:^0.34.5" + typescript: "npm:^6.0.3" + vitest: "npm:^4.1.5" languageName: unknown linkType: soft + +"express-twtkpr@npm:^0.9.0": + version: 0.9.0 + resolution: "express-twtkpr@npm:0.9.0" + dependencies: + "@cacheable/node-cache": "npm:^3.0.0" + "@exodus/blakejs": "npm:^1.1.1-exodus.0" + base32.js: "npm:^0.1.0" + bcryptjs: "npm:^3.0.3" + cookie-parser: "npm:^1.4.7" + dayjs: "npm:^1.11.20" + debug: "npm:^4.4.3" + express: "npm:^5.2.1" + express-rate-limit: "npm:^8.5.0" + express-session: "npm:^1.19.0" + express-slow-down: "npm:^3.1.0" + jsonwebtoken: "npm:^9.0.3" + link: "npm:^2.1.2" + session-file-store: "npm:^1.5.0" + twtxt-lib: "npm:^0.10.1" + uuid: "npm:^14.0.0" + zod: "npm:^4.4.3" + checksum: 10c0/bfd45bfddf50192114b46602776684cd7122aeb313114bf3048839b6c47193491dd9720d972db20616d50cc624c2ad326bede5e7b48d4f2c6857d0a0d259f162 + languageName: node + linkType: hard + +"express@npm:^5.2.1": + version: 5.2.1 + resolution: "express@npm:5.2.1" + dependencies: + accepts: "npm:^2.0.0" + body-parser: "npm:^2.2.1" + content-disposition: "npm:^1.0.0" + content-type: "npm:^1.0.5" + cookie: "npm:^0.7.1" + cookie-signature: "npm:^1.2.1" + debug: "npm:^4.4.0" + depd: "npm:^2.0.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + etag: "npm:^1.8.1" + finalhandler: "npm:^2.1.0" + fresh: "npm:^2.0.0" + http-errors: "npm:^2.0.0" + merge-descriptors: "npm:^2.0.0" + mime-types: "npm:^3.0.0" + on-finished: "npm:^2.4.1" + once: "npm:^1.4.0" + parseurl: "npm:^1.3.3" + proxy-addr: "npm:^2.0.7" + qs: "npm:^6.14.0" + range-parser: "npm:^1.2.1" + router: "npm:^2.2.0" + send: "npm:^1.1.0" + serve-static: "npm:^2.2.0" + statuses: "npm:^2.0.1" + type-is: "npm:^2.0.1" + vary: "npm:^1.1.2" + checksum: 10c0/45e8c841ad188a41402ddcd1294901e861ee0819f632fb494f2ed344ef9c43315d294d443fb48d594e6586a3b779785120f43321417adaef8567316a55072949 + languageName: node + linkType: hard + +"fast-deep-equal@npm:^3.1.1, fast-deep-equal@npm:^3.1.3": + version: 3.1.3 + resolution: "fast-deep-equal@npm:3.1.3" + checksum: 10c0/40dedc862eb8992c54579c66d914635afbec43350afbbe991235fdcb4e3a8d5af1b23ae7e79bef7d4882d0ecee06c3197488026998fb19f72dc95acff1d1b1d0 + languageName: node + linkType: hard + +"fast-diff@npm:^1.1.2": + version: 1.3.0 + resolution: "fast-diff@npm:1.3.0" + checksum: 10c0/5c19af237edb5d5effda008c891a18a585f74bf12953be57923f17a3a4d0979565fc64dbc73b9e20926b9d895f5b690c618cbb969af0cf022e3222471220ad29 + languageName: node + linkType: hard + +"fast-json-stable-stringify@npm:^2.0.0": + version: 2.1.0 + resolution: "fast-json-stable-stringify@npm:2.1.0" + checksum: 10c0/7f081eb0b8a64e0057b3bb03f974b3ef00135fbf36c1c710895cd9300f13c94ba809bb3a81cf4e1b03f6e5285610a61abbd7602d0652de423144dfee5a389c9b + languageName: node + linkType: hard + +"fast-levenshtein@npm:^2.0.6": + version: 2.0.6 + resolution: "fast-levenshtein@npm:2.0.6" + checksum: 10c0/111972b37338bcb88f7d9e2c5907862c280ebf4234433b95bc611e518d192ccb2d38119c4ac86e26b668d75f7f3894f4ff5c4982899afced7ca78633b08287c4 + languageName: node + linkType: hard + +"fdir@npm:^6.5.0": + version: 6.5.0 + resolution: "fdir@npm:6.5.0" + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + checksum: 10c0/e345083c4306b3aed6cb8ec551e26c36bab5c511e99ea4576a16750ddc8d3240e63826cc624f5ae17ad4dc82e68a253213b60d556c11bfad064b7607847ed07f + languageName: node + linkType: hard + +"file-entry-cache@npm:^8.0.0": + version: 8.0.0 + resolution: "file-entry-cache@npm:8.0.0" + dependencies: + flat-cache: "npm:^4.0.0" + checksum: 10c0/9e2b5938b1cd9b6d7e3612bdc533afd4ac17b2fc646569e9a8abbf2eb48e5eb8e316bc38815a3ef6a1b456f4107f0d0f055a614ca613e75db6bf9ff4d72c1638 + languageName: node + linkType: hard + +"finalhandler@npm:^2.1.0": + version: 2.1.1 + resolution: "finalhandler@npm:2.1.1" + dependencies: + debug: "npm:^4.4.0" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + on-finished: "npm:^2.4.1" + parseurl: "npm:^1.3.3" + statuses: "npm:^2.0.1" + checksum: 10c0/6bd664e21b7b2e79efcaace7d1a427169f61cce048fae68eb56290e6934e676b78e55d89f5998c5508871345bc59a61f47002dc505dc7288be68cceac1b701e2 + languageName: node + linkType: hard + +"find-up@npm:^5.0.0": + version: 5.0.0 + resolution: "find-up@npm:5.0.0" + dependencies: + locate-path: "npm:^6.0.0" + path-exists: "npm:^4.0.0" + checksum: 10c0/062c5a83a9c02f53cdd6d175a37ecf8f87ea5bbff1fdfb828f04bfa021441bc7583e8ebc0872a4c1baab96221fb8a8a275a19809fb93fbc40bd69ec35634069a + languageName: node + linkType: hard + +"flat-cache@npm:^4.0.0": + version: 4.0.1 + resolution: "flat-cache@npm:4.0.1" + dependencies: + flatted: "npm:^3.2.9" + keyv: "npm:^4.5.4" + checksum: 10c0/2c59d93e9faa2523e4fda6b4ada749bed432cfa28c8e251f33b25795e426a1c6dbada777afb1f74fcfff33934fdbdea921ee738fcc33e71adc9d6eca984a1cfc + languageName: node + linkType: hard + +"flatted@npm:^3.2.9": + version: 3.4.2 + resolution: "flatted@npm:3.4.2" + checksum: 10c0/a65b67aae7172d6cdf63691be7de6c5cd5adbdfdfe2e9da1a09b617c9512ed794037741ee53d93114276bff3f93cd3b0d97d54f9b316e1e4885dde6e9ffdf7ed + languageName: node + linkType: hard + +"formidable@npm:^3.5.4": + version: 3.5.4 + resolution: "formidable@npm:3.5.4" + dependencies: + "@paralleldrive/cuid2": "npm:^2.2.2" + dezalgo: "npm:^1.0.4" + once: "npm:^1.4.0" + checksum: 10c0/3a311ce57617eb8f532368e91c0f2bbfb299a0f1a35090e085bd6ca772298f196fbb0b66f0d4b5549d7bf3c5e1844439338d4402b7b6d1fedbe206ad44a931f8 + languageName: node + linkType: hard + +"forwarded@npm:0.2.0": + version: 0.2.0 + resolution: "forwarded@npm:0.2.0" + checksum: 10c0/9b67c3fac86acdbc9ae47ba1ddd5f2f81526fa4c8226863ede5600a3f7c7416ef451f6f1e240a3cc32d0fd79fcfe6beb08fd0da454f360032bde70bf80afbb33 + languageName: node + linkType: hard + +"fresh@npm:^2.0.0": + version: 2.0.0 + resolution: "fresh@npm:2.0.0" + checksum: 10c0/0557548194cb9a809a435bf92bcfbc20c89e8b5eb38861b73ced36750437251e39a111fc3a18b98531be9dd91fe1411e4969f229dc579ec0251ce6c5d4900bbc + languageName: node + linkType: hard + +"fs-extra@npm:^8.0.1": + version: 8.1.0 + resolution: "fs-extra@npm:8.1.0" + dependencies: + graceful-fs: "npm:^4.2.0" + jsonfile: "npm:^4.0.0" + universalify: "npm:^0.1.0" + checksum: 10c0/259f7b814d9e50d686899550c4f9ded85c46c643f7fe19be69504888e007fcbc08f306fae8ec495b8b998635e997c9e3e175ff2eeed230524ef1c1684cc96423 + languageName: node + linkType: hard + +"fsevents@npm:~2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 + conditions: os=darwin + languageName: node + linkType: hard + +"fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + +"function-bind@npm:^1.1.2": + version: 1.1.2 + resolution: "function-bind@npm:1.1.2" + checksum: 10c0/d8680ee1e5fcd4c197e4ac33b2b4dce03c71f4d91717292785703db200f5c21f977c568d28061226f9b5900cbcd2c84463646134fd5337e7925e0942bc3f46d5 + languageName: node + linkType: hard + +"generator-function@npm:^2.0.0": + version: 2.0.1 + resolution: "generator-function@npm:2.0.1" + checksum: 10c0/8a9f59df0f01cfefafdb3b451b80555e5cf6d76487095db91ac461a0e682e4ff7a9dbce15f4ecec191e53586d59eece01949e05a4b4492879600bbbe8e28d6b8 + languageName: node + linkType: hard + +"get-intrinsic@npm:^1.2.5, get-intrinsic@npm:^1.3.0": + version: 1.3.1 + resolution: "get-intrinsic@npm:1.3.1" + dependencies: + async-function: "npm:^1.0.0" + async-generator-function: "npm:^1.0.0" + call-bind-apply-helpers: "npm:^1.0.2" + es-define-property: "npm:^1.0.1" + es-errors: "npm:^1.3.0" + es-object-atoms: "npm:^1.1.1" + function-bind: "npm:^1.1.2" + generator-function: "npm:^2.0.0" + get-proto: "npm:^1.0.1" + gopd: "npm:^1.2.0" + has-symbols: "npm:^1.1.0" + hasown: "npm:^2.0.2" + math-intrinsics: "npm:^1.1.0" + checksum: 10c0/9f4ab0cf7efe0fd2c8185f52e6f637e708f3a112610c88869f8f041bb9ecc2ce44bf285dfdbdc6f4f7c277a5b88d8e94a432374d97cca22f3de7fc63795deb5d + languageName: node + linkType: hard + +"get-proto@npm:^1.0.1": + version: 1.0.1 + resolution: "get-proto@npm:1.0.1" + dependencies: + dunder-proto: "npm:^1.0.1" + es-object-atoms: "npm:^1.0.0" + checksum: 10c0/9224acb44603c5526955e83510b9da41baf6ae73f7398875fba50edc5e944223a89c4a72b070fcd78beb5f7bdda58ecb6294adc28f7acfc0da05f76a2399643c + languageName: node + linkType: hard + +"glob-parent@npm:^6.0.2": + version: 6.0.2 + resolution: "glob-parent@npm:6.0.2" + dependencies: + is-glob: "npm:^4.0.3" + checksum: 10c0/317034d88654730230b3f43bb7ad4f7c90257a426e872ea0bf157473ac61c99bf5d205fad8f0185f989be8d2fa6d3c7dce1645d99d545b6ea9089c39f838e7f8 + languageName: node + linkType: hard + +"gopd@npm:^1.2.0": + version: 1.2.0 + resolution: "gopd@npm:1.2.0" + checksum: 10c0/50fff1e04ba2b7737c097358534eacadad1e68d24cccee3272e04e007bed008e68d2614f3987788428fd192a5ae3889d08fb2331417e4fc4a9ab366b2043cead + languageName: node + linkType: hard + +"graceful-fs@npm:^4.1.6, graceful-fs@npm:^4.2.0, graceful-fs@npm:^4.2.6": + version: 4.2.11 + resolution: "graceful-fs@npm:4.2.11" + checksum: 10c0/386d011a553e02bc594ac2ca0bd6d9e4c22d7fa8cfbfc448a6d148c59ea881b092db9dbe3547ae4b88e55f1b01f7c4a2ecc53b310c042793e63aa44cf6c257f2 + languageName: node + linkType: hard + +"has-symbols@npm:^1.1.0": + version: 1.1.0 + resolution: "has-symbols@npm:1.1.0" + checksum: 10c0/dde0a734b17ae51e84b10986e651c664379018d10b91b6b0e9b293eddb32f0f069688c841fb40f19e9611546130153e0a2a48fd7f512891fb000ddfa36f5a20e + languageName: node + linkType: hard + +"hashery@npm:^1.5.1": + version: 1.5.1 + resolution: "hashery@npm:1.5.1" + dependencies: + hookified: "npm:^1.15.0" + checksum: 10c0/ab4225b655a7b0d05df99b1a59d5b3a51fe433f82422ca25e6f3f4c4ddd30adb49ebd38e0047ef9bded93319c1e9fc857e16aa382e554929c871cb77d39fc463 + languageName: node + linkType: hard + +"hasown@npm:^2.0.2": + version: 2.0.3 + resolution: "hasown@npm:2.0.3" + dependencies: + function-bind: "npm:^1.1.2" + checksum: 10c0/f5eb28c3fd0d3e4facd821c1eeee3836c37b70ab0b0fc532e8a39976e18fef43652415dadc52f8c7a5ff6d5ac93b7bef128789aa6f90f4e9b9a9083dce74ab38 + languageName: node + linkType: hard + +"hookified@npm:^1.15.0": + version: 1.15.1 + resolution: "hookified@npm:1.15.1" + checksum: 10c0/6b691374fa97ae57169fb29f90e723499fda5e85494654fbe55c4768b3ccbf3e14c0adc8d0f365f32c503b60d7c06f907781f5966c03d41c423575eb5e16860c + languageName: node + linkType: hard + +"hookified@npm:^2.1.0": + version: 2.2.0 + resolution: "hookified@npm:2.2.0" + checksum: 10c0/7017d2b66945490293a5aba239e7b39f39071dd940fa019348c7ffea92b91b8c267853c4c51680ed0f3687b33352582fa4d2cff6dd4c5a1c5c44b037276f07aa + languageName: node + linkType: hard + +"http-errors@npm:^2.0.0, http-errors@npm:^2.0.1, http-errors@npm:~2.0.1": + version: 2.0.1 + resolution: "http-errors@npm:2.0.1" + dependencies: + depd: "npm:~2.0.0" + inherits: "npm:~2.0.4" + setprototypeof: "npm:~1.2.0" + statuses: "npm:~2.0.2" + toidentifier: "npm:~1.0.1" + checksum: 10c0/fb38906cef4f5c83952d97661fe14dc156cb59fe54812a42cd448fa57b5c5dfcb38a40a916957737bd6b87aab257c0648d63eb5b6a9ca9f548e105b6072712d4 + languageName: node + linkType: hard + +"iconv-lite@npm:^0.7.0, iconv-lite@npm:~0.7.0": + version: 0.7.2 + resolution: "iconv-lite@npm:0.7.2" + dependencies: + safer-buffer: "npm:>= 2.1.2 < 3.0.0" + checksum: 10c0/3c228920f3bd307f56bf8363706a776f4a060eb042f131cd23855ceca962951b264d0997ab38a1ad340e1c5df8499ed26e1f4f0db6b2a2ad9befaff22f14b722 + languageName: node + linkType: hard + +"ignore@npm:^5.2.0": + version: 5.3.2 + resolution: "ignore@npm:5.3.2" + checksum: 10c0/f9f652c957983634ded1e7f02da3b559a0d4cc210fca3792cb67f1b153623c9c42efdc1c4121af171e295444459fc4a9201101fb041b1104a3c000bccb188337 + languageName: node + linkType: hard + +"imurmurhash@npm:^0.1.4": + version: 0.1.4 + resolution: "imurmurhash@npm:0.1.4" + checksum: 10c0/8b51313850dd33605c6c9d3fd9638b714f4c4c40250cff658209f30d40da60f78992fb2df5dabee4acf589a6a82bbc79ad5486550754bd9ec4e3fc0d4a57d6a6 + languageName: node + linkType: hard + +"inherits@npm:^2.0.1, inherits@npm:~2.0.4": + version: 2.0.4 + resolution: "inherits@npm:2.0.4" + checksum: 10c0/4e531f648b29039fb7426fb94075e6545faa1eb9fe83c29f0b6d9e7263aceb4289d2d4557db0d428188eeb449cc7c5e77b0a0b2c4e248ff2a65933a0dee49ef2 + languageName: node + linkType: hard + +"ip-address@npm:^10.2.0": + version: 10.2.0 + resolution: "ip-address@npm:10.2.0" + checksum: 10c0/5a00aada6e922c9c69dfc800ed5d0fa3348675ebdeed0e1575f503f27ca385b5f534363c9af7ad1daf64c1f1409388cdd3cc2e9b9b0fe1c924a431378d55075a + languageName: node + linkType: hard + +"ipaddr.js@npm:1.9.1": + version: 1.9.1 + resolution: "ipaddr.js@npm:1.9.1" + checksum: 10c0/0486e775047971d3fdb5fb4f063829bac45af299ae0b82dcf3afa2145338e08290563a2a70f34b732d795ecc8311902e541a8530eeb30d75860a78ff4e94ce2a + languageName: node + linkType: hard + +"is-extglob@npm:^2.1.1": + version: 2.1.1 + resolution: "is-extglob@npm:2.1.1" + checksum: 10c0/5487da35691fbc339700bbb2730430b07777a3c21b9ebaecb3072512dfd7b4ba78ac2381a87e8d78d20ea08affb3f1971b4af629173a6bf435ff8a4c47747912 + languageName: node + linkType: hard + +"is-glob@npm:^4.0.0, is-glob@npm:^4.0.3": + version: 4.0.3 + resolution: "is-glob@npm:4.0.3" + dependencies: + is-extglob: "npm:^2.1.1" + checksum: 10c0/17fb4014e22be3bbecea9b2e3a76e9e34ff645466be702f1693e8f1ee1adac84710d0be0bd9f967d6354036fd51ab7c2741d954d6e91dae6bb69714de92c197a + languageName: node + linkType: hard + +"is-promise@npm:^4.0.0": + version: 4.0.0 + resolution: "is-promise@npm:4.0.0" + checksum: 10c0/ebd5c672d73db781ab33ccb155fb9969d6028e37414d609b115cc534654c91ccd061821d5b987eefaa97cf4c62f0b909bb2f04db88306de26e91bfe8ddc01503 + languageName: node + linkType: hard + +"is-typedarray@npm:^1.0.0": + version: 1.0.0 + resolution: "is-typedarray@npm:1.0.0" + checksum: 10c0/4c096275ba041a17a13cca33ac21c16bc4fd2d7d7eb94525e7cd2c2f2c1a3ab956e37622290642501ff4310601e413b675cf399ad6db49855527d2163b3eeeec + languageName: node + linkType: hard + +"isexe@npm:^2.0.0": + version: 2.0.0 + resolution: "isexe@npm:2.0.0" + checksum: 10c0/228cfa503fadc2c31596ab06ed6aa82c9976eec2bfd83397e7eaf06d0ccf42cd1dfd6743bf9aeb01aebd4156d009994c5f76ea898d2832c1fe342da923ca457d + languageName: node + linkType: hard + +"isexe@npm:^4.0.0": + version: 4.0.0 + resolution: "isexe@npm:4.0.0" + checksum: 10c0/5884815115bceac452877659a9c7726382531592f43dc29e5d48b7c4100661aed54018cb90bd36cb2eaeba521092570769167acbb95c18d39afdccbcca06c5ce + languageName: node + linkType: hard + +"json-buffer@npm:3.0.1": + version: 3.0.1 + resolution: "json-buffer@npm:3.0.1" + checksum: 10c0/0d1c91569d9588e7eef2b49b59851f297f3ab93c7b35c7c221e288099322be6b562767d11e4821da500f3219542b9afd2e54c5dc573107c1126ed1080f8e96d7 + languageName: node + linkType: hard + +"json-schema-traverse@npm:^0.4.1": + version: 0.4.1 + resolution: "json-schema-traverse@npm:0.4.1" + checksum: 10c0/108fa90d4cc6f08243aedc6da16c408daf81793bf903e9fd5ab21983cda433d5d2da49e40711da016289465ec2e62e0324dcdfbc06275a607fe3233fde4942ce + languageName: node + linkType: hard + +"json-stable-stringify-without-jsonify@npm:^1.0.1": + version: 1.0.1 + resolution: "json-stable-stringify-without-jsonify@npm:1.0.1" + checksum: 10c0/cb168b61fd4de83e58d09aaa6425ef71001bae30d260e2c57e7d09a5fd82223e2f22a042dedaab8db23b7d9ae46854b08bb1f91675a8be11c5cffebef5fb66a5 + languageName: node + linkType: hard + +"jsonfile@npm:^4.0.0": + version: 4.0.0 + resolution: "jsonfile@npm:4.0.0" + dependencies: + graceful-fs: "npm:^4.1.6" + dependenciesMeta: + graceful-fs: + optional: true + checksum: 10c0/7dc94b628d57a66b71fb1b79510d460d662eb975b5f876d723f81549c2e9cd316d58a2ddf742b2b93a4fa6b17b2accaf1a738a0e2ea114bdfb13a32e5377e480 + languageName: node + linkType: hard + +"jsonwebtoken@npm:^9.0.3": + version: 9.0.3 + resolution: "jsonwebtoken@npm:9.0.3" + dependencies: + jws: "npm:^4.0.1" + lodash.includes: "npm:^4.3.0" + lodash.isboolean: "npm:^3.0.3" + lodash.isinteger: "npm:^4.0.4" + lodash.isnumber: "npm:^3.0.3" + lodash.isplainobject: "npm:^4.0.6" + lodash.isstring: "npm:^4.0.1" + lodash.once: "npm:^4.0.0" + ms: "npm:^2.1.1" + semver: "npm:^7.5.4" + checksum: 10c0/6ca7f1e54886ea3bde7146a5a22b53847c46e25453c7f7307a69818b9a6ad48c390b2e59d5690fcfd03c529b01960060cc4bb0c686991d6edae2285dfd30f4ba + languageName: node + linkType: hard + +"jwa@npm:^2.0.1": + version: 2.0.1 + resolution: "jwa@npm:2.0.1" + dependencies: + buffer-equal-constant-time: "npm:^1.0.1" + ecdsa-sig-formatter: "npm:1.0.11" + safe-buffer: "npm:^5.0.1" + checksum: 10c0/ab3ebc6598e10dc11419d4ed675c9ca714a387481466b10e8a6f3f65d8d9c9237e2826f2505280a739cf4cbcf511cb288eeec22b5c9c63286fc5a2e4f97e78cf + languageName: node + linkType: hard + +"jws@npm:^4.0.1": + version: 4.0.1 + resolution: "jws@npm:4.0.1" + dependencies: + jwa: "npm:^2.0.1" + safe-buffer: "npm:^5.0.1" + checksum: 10c0/6be1ed93023aef570ccc5ea8d162b065840f3ef12f0d1bb3114cade844de7a357d5dc558201d9a65101e70885a6fa56b17462f520e6b0d426195510618a154d0 + languageName: node + linkType: hard + +"keyv@npm:^4.5.4": + version: 4.5.4 + resolution: "keyv@npm:4.5.4" + dependencies: + json-buffer: "npm:3.0.1" + checksum: 10c0/aa52f3c5e18e16bb6324876bb8b59dd02acf782a4b789c7b2ae21107fab95fab3890ed448d4f8dba80ce05391eeac4bfabb4f02a20221342982f806fa2cf271e + languageName: node + linkType: hard + +"keyv@npm:^5.6.0": + version: 5.6.0 + resolution: "keyv@npm:5.6.0" + dependencies: + "@keyv/serialize": "npm:^1.1.1" + checksum: 10c0/c3ea795b6e03593ca57c8f70928a69bad14c13389a7fb75649a115ff55615244b04d8902798d841c17f0bb4a8a8866c97133b543b93f151b440170bba09176db + languageName: node + linkType: hard + +"kruptein@npm:^2.0.4": + version: 2.2.3 + resolution: "kruptein@npm:2.2.3" + dependencies: + asn1.js: "npm:^5.4.1" + checksum: 10c0/bb49bf80eda500bacd5e2f934ee6edb347559719908b81a712c86db75c8a14109ba66796f906323ae68b04d687bccc2c057208ca96cad576d3d5cb0281ea20dd + languageName: node + linkType: hard + +"levn@npm:^0.4.1": + version: 0.4.1 + resolution: "levn@npm:0.4.1" + dependencies: + prelude-ls: "npm:^1.2.1" + type-check: "npm:~0.4.0" + checksum: 10c0/effb03cad7c89dfa5bd4f6989364bfc79994c2042ec5966cb9b95990e2edee5cd8969ddf42616a0373ac49fac1403437deaf6e9050fbbaa3546093a59b9ac94e + languageName: node + linkType: hard + +"lightningcss-android-arm64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-android-arm64@npm:1.32.0" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-darwin-arm64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-darwin-arm64@npm:1.32.0" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-darwin-x64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-darwin-x64@npm:1.32.0" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-freebsd-x64@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-freebsd-x64@npm:1.32.0" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + +"lightningcss-linux-arm-gnueabihf@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-arm-gnueabihf@npm:1.32.0" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + +"lightningcss-linux-arm64-gnu@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-arm64-gnu@npm:1.32.0" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-arm64-musl@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-arm64-musl@npm:1.32.0" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-linux-x64-gnu@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-x64-gnu@npm:1.32.0" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"lightningcss-linux-x64-musl@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-linux-x64-musl@npm:1.32.0" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"lightningcss-win32-arm64-msvc@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-win32-arm64-msvc@npm:1.32.0" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"lightningcss-win32-x64-msvc@npm:1.32.0": + version: 1.32.0 + resolution: "lightningcss-win32-x64-msvc@npm:1.32.0" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + +"lightningcss@npm:^1.32.0": + version: 1.32.0 + resolution: "lightningcss@npm:1.32.0" + dependencies: + detect-libc: "npm:^2.0.3" + lightningcss-android-arm64: "npm:1.32.0" + lightningcss-darwin-arm64: "npm:1.32.0" + lightningcss-darwin-x64: "npm:1.32.0" + lightningcss-freebsd-x64: "npm:1.32.0" + lightningcss-linux-arm-gnueabihf: "npm:1.32.0" + lightningcss-linux-arm64-gnu: "npm:1.32.0" + lightningcss-linux-arm64-musl: "npm:1.32.0" + lightningcss-linux-x64-gnu: "npm:1.32.0" + lightningcss-linux-x64-musl: "npm:1.32.0" + lightningcss-win32-arm64-msvc: "npm:1.32.0" + lightningcss-win32-x64-msvc: "npm:1.32.0" + dependenciesMeta: + lightningcss-android-arm64: + optional: true + lightningcss-darwin-arm64: + optional: true + lightningcss-darwin-x64: + optional: true + lightningcss-freebsd-x64: + optional: true + lightningcss-linux-arm-gnueabihf: + optional: true + lightningcss-linux-arm64-gnu: + optional: true + lightningcss-linux-arm64-musl: + optional: true + lightningcss-linux-x64-gnu: + optional: true + lightningcss-linux-x64-musl: + optional: true + lightningcss-win32-arm64-msvc: + optional: true + lightningcss-win32-x64-msvc: + optional: true + checksum: 10c0/70945bd55097af46fc9fab7f5ed09cd5869d85940a2acab7ee06d0117004a1d68155708a2d462531cea2fc3c67aefc9333a7068c80b0b78dd404c16838809e03 + languageName: node + linkType: hard + +"link@npm:^2.1.2": + version: 2.1.2 + resolution: "link@npm:2.1.2" + bin: + link: dist/cli.js + checksum: 10c0/1b4a70eb649f36f2fc31210940cfddb38dfa7ba6096d29e3ee071276fe1f430356ed7cfe4eb941a1b3f4192c7a691857c329492eaa668900e72fbfd95578c49e + languageName: node + linkType: hard + +"locate-path@npm:^6.0.0": + version: 6.0.0 + resolution: "locate-path@npm:6.0.0" + dependencies: + p-locate: "npm:^5.0.0" + checksum: 10c0/d3972ab70dfe58ce620e64265f90162d247e87159b6126b01314dd67be43d50e96a50b517bce2d9452a79409c7614054c277b5232377de50416564a77ac7aad3 + languageName: node + linkType: hard + +"lodash.includes@npm:^4.3.0": + version: 4.3.0 + resolution: "lodash.includes@npm:4.3.0" + checksum: 10c0/7ca498b9b75bf602d04e48c0adb842dfc7d90f77bcb2a91a2b2be34a723ad24bc1c8b3683ec6b2552a90f216c723cdea530ddb11a3320e08fa38265703978f4b + languageName: node + linkType: hard + +"lodash.isboolean@npm:^3.0.3": + version: 3.0.3 + resolution: "lodash.isboolean@npm:3.0.3" + checksum: 10c0/0aac604c1ef7e72f9a6b798e5b676606042401dd58e49f051df3cc1e3adb497b3d7695635a5cbec4ae5f66456b951fdabe7d6b387055f13267cde521f10ec7f7 + languageName: node + linkType: hard + +"lodash.isinteger@npm:^4.0.4": + version: 4.0.4 + resolution: "lodash.isinteger@npm:4.0.4" + checksum: 10c0/4c3e023a2373bf65bf366d3b8605b97ec830bca702a926939bcaa53f8e02789b6a176e7f166b082f9365bfec4121bfeb52e86e9040cb8d450e64c858583f61b7 + languageName: node + linkType: hard + +"lodash.isnumber@npm:^3.0.3": + version: 3.0.3 + resolution: "lodash.isnumber@npm:3.0.3" + checksum: 10c0/2d01530513a1ee4f72dd79528444db4e6360588adcb0e2ff663db2b3f642d4bb3d687051ae1115751ca9082db4fdef675160071226ca6bbf5f0c123dbf0aa12d + languageName: node + linkType: hard + +"lodash.isplainobject@npm:^4.0.6": + version: 4.0.6 + resolution: "lodash.isplainobject@npm:4.0.6" + checksum: 10c0/afd70b5c450d1e09f32a737bed06ff85b873ecd3d3d3400458725283e3f2e0bb6bf48e67dbe7a309eb371a822b16a26cca4a63c8c52db3fc7dc9d5f9dd324cbb + languageName: node + linkType: hard + +"lodash.isstring@npm:^4.0.1": + version: 4.0.1 + resolution: "lodash.isstring@npm:4.0.1" + checksum: 10c0/09eaf980a283f9eef58ef95b30ec7fee61df4d6bf4aba3b5f096869cc58f24c9da17900febc8ffd67819b4e29de29793190e88dc96983db92d84c95fa85d1c92 + languageName: node + linkType: hard + +"lodash.once@npm:^4.0.0": + version: 4.1.1 + resolution: "lodash.once@npm:4.1.1" + checksum: 10c0/46a9a0a66c45dd812fcc016e46605d85ad599fe87d71a02f6736220554b52ffbe82e79a483ad40f52a8a95755b0d1077fba259da8bfb6694a7abbf4a48f1fc04 + languageName: node + linkType: hard + +"magic-string@npm:^0.30.21": + version: 0.30.21 + resolution: "magic-string@npm:0.30.21" + dependencies: + "@jridgewell/sourcemap-codec": "npm:^1.5.5" + checksum: 10c0/299378e38f9a270069fc62358522ddfb44e94244baa0d6a8980ab2a9b2490a1d03b236b447eee309e17eb3bddfa482c61259d47960eb018a904f0ded52780c4a + languageName: node + linkType: hard + +"math-intrinsics@npm:^1.1.0": + version: 1.1.0 + resolution: "math-intrinsics@npm:1.1.0" + checksum: 10c0/7579ff94e899e2f76ab64491d76cf606274c874d8f2af4a442c016bd85688927fcfca157ba6bf74b08e9439dc010b248ce05b96cc7c126a354c3bae7fcb48b7f + languageName: node + linkType: hard + +"media-typer@npm:^1.1.0": + version: 1.1.0 + resolution: "media-typer@npm:1.1.0" + checksum: 10c0/7b4baa40b25964bb90e2121ee489ec38642127e48d0cc2b6baa442688d3fde6262bfdca86d6bbf6ba708784afcac168c06840c71facac70e390f5f759ac121b9 + languageName: node + linkType: hard + +"merge-descriptors@npm:^2.0.0": + version: 2.0.0 + resolution: "merge-descriptors@npm:2.0.0" + checksum: 10c0/95389b7ced3f9b36fbdcf32eb946dc3dd1774c2fdf164609e55b18d03aa499b12bd3aae3a76c1c7185b96279e9803525550d3eb292b5224866060a288f335cb3 + languageName: node + linkType: hard + +"mime-db@npm:^1.54.0": + version: 1.54.0 + resolution: "mime-db@npm:1.54.0" + checksum: 10c0/8d907917bc2a90fa2df842cdf5dfeaf509adc15fe0531e07bb2f6ab15992416479015828d6a74200041c492e42cce3ebf78e5ce714388a0a538ea9c53eece284 + languageName: node + linkType: hard + +"mime-types@npm:^3.0.0, mime-types@npm:^3.0.2": + version: 3.0.2 + resolution: "mime-types@npm:3.0.2" + dependencies: + mime-db: "npm:^1.54.0" + checksum: 10c0/35a0dd1035d14d185664f346efcdb72e93ef7a9b6e9ae808bd1f6358227010267fab52657b37562c80fc888ff76becb2b2938deb5e730818b7983bf8bd359767 + languageName: node + linkType: hard + +"minimalistic-assert@npm:^1.0.0": + version: 1.0.1 + resolution: "minimalistic-assert@npm:1.0.1" + checksum: 10c0/96730e5601cd31457f81a296f521eb56036e6f69133c0b18c13fe941109d53ad23a4204d946a0d638d7f3099482a0cec8c9bb6d642604612ce43ee536be3dddd + languageName: node + linkType: hard + +"minimatch@npm:^10.2.4": + version: 10.2.5 + resolution: "minimatch@npm:10.2.5" + dependencies: + brace-expansion: "npm:^5.0.5" + checksum: 10c0/6bb058bd6324104b9ec2f763476a35386d05079c1f5fe4fbf1f324a25237cd4534d6813ecd71f48208f4e635c1221899bef94c3c89f7df55698fe373aaae20fd + languageName: node + linkType: hard + +"minipass@npm:^7.0.4, minipass@npm:^7.1.2": + version: 7.1.3 + resolution: "minipass@npm:7.1.3" + checksum: 10c0/539da88daca16533211ea5a9ee98dc62ff5742f531f54640dd34429e621955e91cc280a91a776026264b7f9f6735947629f920944e9c1558369e8bf22eb33fbb + languageName: node + linkType: hard + +"minizlib@npm:^3.1.0": + version: 3.1.0 + resolution: "minizlib@npm:3.1.0" + dependencies: + minipass: "npm:^7.1.2" + checksum: 10c0/5aad75ab0090b8266069c9aabe582c021ae53eb33c6c691054a13a45db3b4f91a7fb1bd79151e6b4e9e9a86727b522527c0a06ec7d45206b745d54cd3097bcec + languageName: node + linkType: hard + +"ms@npm:2.0.0": + version: 2.0.0 + resolution: "ms@npm:2.0.0" + checksum: 10c0/f8fda810b39fd7255bbdc451c46286e549794fcc700dc9cd1d25658bbc4dc2563a5de6fe7c60f798a16a60c6ceb53f033cb353f493f0cf63e5199b702943159d + languageName: node + linkType: hard + +"ms@npm:^2.1.1, ms@npm:^2.1.3": + version: 2.1.3 + resolution: "ms@npm:2.1.3" + checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48 + languageName: node + linkType: hard + +"nanoid@npm:^3.3.11": + version: 3.3.12 + resolution: "nanoid@npm:3.3.12" + bin: + nanoid: bin/nanoid.cjs + checksum: 10c0/ba142b7b39e11e80c16dd74b0365d407880c87c1cf7e1480956981ae940ee36060fa5b6f092cd1e315184dd19244c657bd017d03327bd3c62247d691c5e8edfb + languageName: node + linkType: hard + +"natural-compare@npm:^1.4.0": + version: 1.4.0 + resolution: "natural-compare@npm:1.4.0" + checksum: 10c0/f5f9a7974bfb28a91afafa254b197f0f22c684d4a1731763dda960d2c8e375b36c7d690e0d9dc8fba774c537af14a7e979129bca23d88d052fbeb9466955e447 + languageName: node + linkType: hard + +"negotiator@npm:^1.0.0": + version: 1.0.0 + resolution: "negotiator@npm:1.0.0" + checksum: 10c0/4c559dd52669ea48e1914f9d634227c561221dd54734070791f999c52ed0ff36e437b2e07d5c1f6e32909fc625fe46491c16e4a8f0572567d4dd15c3a4fda04b + languageName: node + linkType: hard + +"node-gyp@npm:latest": + version: 12.3.0 + resolution: "node-gyp@npm:12.3.0" + dependencies: + env-paths: "npm:^2.2.0" + exponential-backoff: "npm:^3.1.1" + graceful-fs: "npm:^4.2.6" + nopt: "npm:^9.0.0" + proc-log: "npm:^6.0.0" + semver: "npm:^7.3.5" + tar: "npm:^7.5.4" + tinyglobby: "npm:^0.2.12" + undici: "npm:^6.25.0" + which: "npm:^6.0.0" + bin: + node-gyp: bin/node-gyp.js + checksum: 10c0/9d9032b405cbe42f72a105259d9eb679376470c102df4a2dbaa51e07d59bf741dcffb85897087ea9d8318b9cabb824a8978af51508ae142f0239ae1e6a3c2329 + languageName: node + linkType: hard + +"nopt@npm:^9.0.0": + version: 9.0.0 + resolution: "nopt@npm:9.0.0" + dependencies: + abbrev: "npm:^4.0.0" + bin: + nopt: bin/nopt.js + checksum: 10c0/1822eb6f9b020ef6f7a7516d7b64a8036e09666ea55ac40416c36e4b2b343122c3cff0e2f085675f53de1d2db99a2a89a60ccea1d120bcd6a5347bf6ceb4a7fd + languageName: node + linkType: hard + +"object-assign@npm:^4.1.1": + version: 4.1.1 + resolution: "object-assign@npm:4.1.1" + checksum: 10c0/1f4df9945120325d041ccf7b86f31e8bcc14e73d29171e37a7903050e96b81323784ec59f93f102ec635bcf6fa8034ba3ea0a8c7e69fa202b87ae3b6cec5a414 + languageName: node + linkType: hard + +"object-inspect@npm:^1.13.3, object-inspect@npm:^1.13.4": + version: 1.13.4 + resolution: "object-inspect@npm:1.13.4" + checksum: 10c0/d7f8711e803b96ea3191c745d6f8056ce1f2496e530e6a19a0e92d89b0fa3c76d910c31f0aa270432db6bd3b2f85500a376a83aaba849a8d518c8845b3211692 + languageName: node + linkType: hard + +"obug@npm:^2.1.1": + version: 2.1.1 + resolution: "obug@npm:2.1.1" + checksum: 10c0/59dccd7de72a047e08f8649e94c1015ec72f94eefb6ddb57fb4812c4b425a813bc7e7cd30c9aca20db3c59abc3c85cc7a62bb656a968741d770f4e8e02bc2e78 + languageName: node + linkType: hard + +"on-finished@npm:^2.4.1": + version: 2.4.1 + resolution: "on-finished@npm:2.4.1" + dependencies: + ee-first: "npm:1.1.1" + checksum: 10c0/46fb11b9063782f2d9968863d9cbba33d77aa13c17f895f56129c274318b86500b22af3a160fe9995aa41317efcd22941b6eba747f718ced08d9a73afdb087b4 + languageName: node + linkType: hard + +"on-headers@npm:~1.1.0": + version: 1.1.0 + resolution: "on-headers@npm:1.1.0" + checksum: 10c0/2c3b6b0d68ec9adbd561dc2d61c9b14da8ac03d8a2f0fd9e97bdf0600c887d5d97f664ff3be6876cf40cda6e3c587d73a4745e10b426ac50c7664fc5a0dfc0a1 + languageName: node + linkType: hard + +"once@npm:^1.4.0": + version: 1.4.0 + resolution: "once@npm:1.4.0" + dependencies: + wrappy: "npm:1" + checksum: 10c0/5d48aca287dfefabd756621c5dfce5c91a549a93e9fdb7b8246bc4c4790aa2ec17b34a260530474635147aeb631a2dcc8b32c613df0675f96041cbb8244517d0 + languageName: node + linkType: hard + +"optionator@npm:^0.9.3": + version: 0.9.4 + resolution: "optionator@npm:0.9.4" + dependencies: + deep-is: "npm:^0.1.3" + fast-levenshtein: "npm:^2.0.6" + levn: "npm:^0.4.1" + prelude-ls: "npm:^1.2.1" + type-check: "npm:^0.4.0" + word-wrap: "npm:^1.2.5" + checksum: 10c0/4afb687a059ee65b61df74dfe87d8d6815cd6883cb8b3d5883a910df72d0f5d029821f37025e4bccf4048873dbdb09acc6d303d27b8f76b1a80dd5a7d5334675 + languageName: node + linkType: hard + +"p-limit@npm:^3.0.2": + version: 3.1.0 + resolution: "p-limit@npm:3.1.0" + dependencies: + yocto-queue: "npm:^0.1.0" + checksum: 10c0/9db675949dbdc9c3763c89e748d0ef8bdad0afbb24d49ceaf4c46c02c77d30db4e0652ed36d0a0a7a95154335fab810d95c86153105bb73b3a90448e2bb14e1a + languageName: node + linkType: hard + +"p-locate@npm:^5.0.0": + version: 5.0.0 + resolution: "p-locate@npm:5.0.0" + dependencies: + p-limit: "npm:^3.0.2" + checksum: 10c0/2290d627ab7903b8b70d11d384fee714b797f6040d9278932754a6860845c4d3190603a0772a663c8cb5a7b21d1b16acb3a6487ebcafa9773094edc3dfe6009a + languageName: node + linkType: hard + +"parseurl@npm:^1.3.3, parseurl@npm:~1.3.3": + version: 1.3.3 + resolution: "parseurl@npm:1.3.3" + checksum: 10c0/90dd4760d6f6174adb9f20cf0965ae12e23879b5f5464f38e92fce8073354341e4b3b76fa3d878351efe7d01e617121955284cfd002ab087fba1a0726ec0b4f5 + languageName: node + linkType: hard + +"path-exists@npm:^4.0.0": + version: 4.0.0 + resolution: "path-exists@npm:4.0.0" + checksum: 10c0/8c0bd3f5238188197dc78dced15207a4716c51cc4e3624c44fc97acf69558f5ebb9a2afff486fe1b4ee148e0c133e96c5e11a9aa5c48a3006e3467da070e5e1b + languageName: node + linkType: hard + +"path-key@npm:^3.1.0": + version: 3.1.1 + resolution: "path-key@npm:3.1.1" + checksum: 10c0/748c43efd5a569c039d7a00a03b58eecd1d75f3999f5a28303d75f521288df4823bc057d8784eb72358b2895a05f29a070bc9f1f17d28226cc4e62494cc58c4c + languageName: node + linkType: hard + +"path-to-regexp@npm:^8.0.0": + version: 8.4.2 + resolution: "path-to-regexp@npm:8.4.2" + checksum: 10c0/05b115c49b47ad252ce05faa32930f643f23769c68b8bcfe78ad833545140c48bbffb3266986d6c8d5db13a64cf12e07e0d72d9882cab830efeefa553533ebaf + languageName: node + linkType: hard + +"pathe@npm:^2.0.3": + version: 2.0.3 + resolution: "pathe@npm:2.0.3" + checksum: 10c0/c118dc5a8b5c4166011b2b70608762e260085180bb9e33e80a50dcdb1e78c010b1624f4280c492c92b05fc276715a4c357d1f9edc570f8f1b3d90b6839ebaca1 + languageName: node + linkType: hard + +"picocolors@npm:^1.1.1": + version: 1.1.1 + resolution: "picocolors@npm:1.1.1" + checksum: 10c0/e2e3e8170ab9d7c7421969adaa7e1b31434f789afb9b3f115f6b96d91945041ac3ceb02e9ec6fe6510ff036bcc0bf91e69a1772edc0b707e12b19c0f2d6bcf58 + languageName: node + linkType: hard + +"picomatch@npm:^4.0.3, picomatch@npm:^4.0.4": + version: 4.0.4 + resolution: "picomatch@npm:4.0.4" + checksum: 10c0/e2c6023372cc7b5764719a5ffb9da0f8e781212fa7ca4bd0562db929df8e117460f00dff3cb7509dacfc06b86de924b247f504d0ce1806a37fac4633081466b0 + languageName: node + linkType: hard + +"postcss@npm:^8.5.14": + version: 8.5.14 + resolution: "postcss@npm:8.5.14" + dependencies: + nanoid: "npm:^3.3.11" + picocolors: "npm:^1.1.1" + source-map-js: "npm:^1.2.1" + checksum: 10c0/48138207cf5ef5581be1bfe2cb65ccfe0ac75e43888ba045afc8ed6043d7b56aeb3b9a9fe5b353ff554be943cd0cc15d826ccb991525159175971e5ee8ab0237 + languageName: node + linkType: hard + +"prelude-ls@npm:^1.2.1": + version: 1.2.1 + resolution: "prelude-ls@npm:1.2.1" + checksum: 10c0/b00d617431e7886c520a6f498a2e14c75ec58f6d93ba48c3b639cf241b54232d90daa05d83a9e9b9fef6baa63cb7e1e4602c2372fea5bc169668401eb127d0cd + languageName: node + linkType: hard + +"prettier-linter-helpers@npm:^1.0.1": + version: 1.0.1 + resolution: "prettier-linter-helpers@npm:1.0.1" + dependencies: + fast-diff: "npm:^1.1.2" + checksum: 10c0/91cea965681bc5f62c9d26bd3ca6358b81557261d4802e96ec1cf0acbd99d4b61632d53320cd2c3ec7d7f7805a81345644108a41ef46ddc9688e783a9ac792d1 + languageName: node + linkType: hard + +"prettier@npm:^3.8.3": + version: 3.8.3 + resolution: "prettier@npm:3.8.3" + bin: + prettier: bin/prettier.cjs + checksum: 10c0/754816fd7593eb80f6376d7476d463e832c38a12f32775a82683adb6e35b772b1f484d65f19401507b983a8c8a7cd5a4a9f12006bd56491e8f35503473f77473 + languageName: node + linkType: hard + +"proc-log@npm:^6.0.0": + version: 6.1.0 + resolution: "proc-log@npm:6.1.0" + checksum: 10c0/4f178d4062733ead9d71a9b1ab24ebcecdfe2250916a5b1555f04fe2eda972a0ec76fbaa8df1ad9c02707add6749219d118a4fc46dc56bdfe4dde4b47d80bb82 + languageName: node + linkType: hard + +"proxy-addr@npm:^2.0.7": + version: 2.0.7 + resolution: "proxy-addr@npm:2.0.7" + dependencies: + forwarded: "npm:0.2.0" + ipaddr.js: "npm:1.9.1" + checksum: 10c0/c3eed999781a35f7fd935f398b6d8920b6fb00bbc14287bc6de78128ccc1a02c89b95b56742bf7cf0362cc333c61d138532049c7dedc7a328ef13343eff81210 + languageName: node + linkType: hard + +"punycode@npm:^2.1.0": + version: 2.3.1 + resolution: "punycode@npm:2.3.1" + checksum: 10c0/14f76a8206bc3464f794fb2e3d3cc665ae416c01893ad7a02b23766eb07159144ee612ad67af5e84fa4479ccfe67678c4feb126b0485651b302babf66f04f9e9 + languageName: node + linkType: hard + +"qs@npm:^6.14.0, qs@npm:^6.14.1": + version: 6.15.1 + resolution: "qs@npm:6.15.1" + dependencies: + side-channel: "npm:^1.1.0" + checksum: 10c0/19ee504f0ebff72598503e38cd6d9bd7b52a8ab62ae18b1e6bee3d4db58469bd65871ef1893a881bafb0f80ef2f9ab586e1f255cf25cc8d816c0f5a704721d97 + languageName: node + linkType: hard + +"random-bytes@npm:~1.0.0": + version: 1.0.0 + resolution: "random-bytes@npm:1.0.0" + checksum: 10c0/71e7a600e0976e9ebc269793a0577d47b965fa678fcc9e9623e427f909d1b3669db5b3a178dbf61229f0724ea23dba64db389f0be0ba675c6a6b837c02f29b8f + languageName: node + linkType: hard + +"range-parser@npm:^1.2.1": + version: 1.2.1 + resolution: "range-parser@npm:1.2.1" + checksum: 10c0/96c032ac2475c8027b7a4e9fe22dc0dfe0f6d90b85e496e0f016fbdb99d6d066de0112e680805075bd989905e2123b3b3d002765149294dce0c1f7f01fcc2ea0 + languageName: node + linkType: hard + +"raw-body@npm:^3.0.1": + version: 3.0.2 + resolution: "raw-body@npm:3.0.2" + dependencies: + bytes: "npm:~3.1.2" + http-errors: "npm:~2.0.1" + iconv-lite: "npm:~0.7.0" + unpipe: "npm:~1.0.0" + checksum: 10c0/d266678d08e1e7abea62c0ce5864344e980fa81c64f6b481e9842c5beaed2cdcf975f658a3ccd67ad35fc919c1f6664ccc106067801850286a6cbe101de89f29 + languageName: node + linkType: hard + +"regexp-tree@npm:~0.1.1": + version: 0.1.27 + resolution: "regexp-tree@npm:0.1.27" + bin: + regexp-tree: bin/regexp-tree + checksum: 10c0/f636f44b4a0d93d7d6926585ecd81f63e4ce2ac895bc417b2ead0874cd36b337dcc3d0fedc63f69bf5aaeaa4340f36ca7e750c9687cceaf8087374e5284e843c + languageName: node + linkType: hard + +"retry@npm:^0.12.0": + version: 0.12.0 + resolution: "retry@npm:0.12.0" + checksum: 10c0/59933e8501727ba13ad73ef4a04d5280b3717fd650408460c987392efe9d7be2040778ed8ebe933c5cbd63da3dcc37919c141ef8af0a54a6e4fca5a2af177bfe + languageName: node + linkType: hard + +"rolldown@npm:1.0.0": + version: 1.0.0 + resolution: "rolldown@npm:1.0.0" + dependencies: + "@oxc-project/types": "npm:=0.129.0" + "@rolldown/binding-android-arm64": "npm:1.0.0" + "@rolldown/binding-darwin-arm64": "npm:1.0.0" + "@rolldown/binding-darwin-x64": "npm:1.0.0" + "@rolldown/binding-freebsd-x64": "npm:1.0.0" + "@rolldown/binding-linux-arm-gnueabihf": "npm:1.0.0" + "@rolldown/binding-linux-arm64-gnu": "npm:1.0.0" + "@rolldown/binding-linux-arm64-musl": "npm:1.0.0" + "@rolldown/binding-linux-ppc64-gnu": "npm:1.0.0" + "@rolldown/binding-linux-s390x-gnu": "npm:1.0.0" + "@rolldown/binding-linux-x64-gnu": "npm:1.0.0" + "@rolldown/binding-linux-x64-musl": "npm:1.0.0" + "@rolldown/binding-openharmony-arm64": "npm:1.0.0" + "@rolldown/binding-wasm32-wasi": "npm:1.0.0" + "@rolldown/binding-win32-arm64-msvc": "npm:1.0.0" + "@rolldown/binding-win32-x64-msvc": "npm:1.0.0" + "@rolldown/pluginutils": "npm:1.0.0" + dependenciesMeta: + "@rolldown/binding-android-arm64": + optional: true + "@rolldown/binding-darwin-arm64": + optional: true + "@rolldown/binding-darwin-x64": + optional: true + "@rolldown/binding-freebsd-x64": + optional: true + "@rolldown/binding-linux-arm-gnueabihf": + optional: true + "@rolldown/binding-linux-arm64-gnu": + optional: true + "@rolldown/binding-linux-arm64-musl": + optional: true + "@rolldown/binding-linux-ppc64-gnu": + optional: true + "@rolldown/binding-linux-s390x-gnu": + optional: true + "@rolldown/binding-linux-x64-gnu": + optional: true + "@rolldown/binding-linux-x64-musl": + optional: true + "@rolldown/binding-openharmony-arm64": + optional: true + "@rolldown/binding-wasm32-wasi": + optional: true + "@rolldown/binding-win32-arm64-msvc": + optional: true + "@rolldown/binding-win32-x64-msvc": + optional: true + bin: + rolldown: bin/cli.mjs + checksum: 10c0/8e8c4ebcd80cd6fc051e1e58ad2ffb6578431f6828522788d6e5da6ba6d6e3e92f20e47df5e30034aba5a5af296f497a2b2ff26a21d5ade3c125b620ea958256 + languageName: node + linkType: hard + +"router@npm:^2.2.0": + version: 2.2.0 + resolution: "router@npm:2.2.0" + dependencies: + debug: "npm:^4.4.0" + depd: "npm:^2.0.0" + is-promise: "npm:^4.0.0" + parseurl: "npm:^1.3.3" + path-to-regexp: "npm:^8.0.0" + checksum: 10c0/3279de7450c8eae2f6e095e9edacbdeec0abb5cb7249c6e719faa0db2dba43574b4fff5892d9220631c9abaff52dd3cad648cfea2aaace845e1a071915ac8867 + languageName: node + linkType: hard + +"safe-buffer@npm:^5.0.1, safe-buffer@npm:~5.2.1": + version: 5.2.1 + resolution: "safe-buffer@npm:5.2.1" + checksum: 10c0/6501914237c0a86e9675d4e51d89ca3c21ffd6a31642efeba25ad65720bce6921c9e7e974e5be91a786b25aa058b5303285d3c15dbabf983a919f5f630d349f3 + languageName: node + linkType: hard + +"safe-regex@npm:^2.1.1": + version: 2.1.1 + resolution: "safe-regex@npm:2.1.1" + dependencies: + regexp-tree: "npm:~0.1.1" + checksum: 10c0/53eb5d3ecf4b3c0954dff465eb179af4d2f5f77f74ba7b57489adbc4fa44454c3d391f37379cd28722d9ac6fa5b70be3f4645d4bd25df395fd99b934f6ec9265 + languageName: node + linkType: hard + +"safer-buffer@npm:>= 2.1.2 < 3.0.0, safer-buffer@npm:^2.1.0": + version: 2.1.2 + resolution: "safer-buffer@npm:2.1.2" + checksum: 10c0/7e3c8b2e88a1841c9671094bbaeebd94448111dd90a81a1f606f3f67708a6ec57763b3b47f06da09fc6054193e0e6709e77325415dc8422b04497a8070fa02d4 + languageName: node + linkType: hard + +"semver@npm:^7.3.5, semver@npm:^7.5.4, semver@npm:^7.7.3": + version: 7.8.0 + resolution: "semver@npm:7.8.0" + bin: + semver: bin/semver.js + checksum: 10c0/8f096ca9b80ffd47b308d03f9ce8c873e27e2983f36023c559cdc92c51e8433fc23ebbfe57ec9623fc155636a6961ee989501099841ae4bb1babc8d2b3f048cd + languageName: node + linkType: hard + +"send@npm:^1.1.0, send@npm:^1.2.0": + version: 1.2.1 + resolution: "send@npm:1.2.1" + dependencies: + debug: "npm:^4.4.3" + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + etag: "npm:^1.8.1" + fresh: "npm:^2.0.0" + http-errors: "npm:^2.0.1" + mime-types: "npm:^3.0.2" + ms: "npm:^2.1.3" + on-finished: "npm:^2.4.1" + range-parser: "npm:^1.2.1" + statuses: "npm:^2.0.2" + checksum: 10c0/fbbbbdc902a913d65605274be23f3d604065cfc3ee3d78bf9fc8af1dc9fc82667c50d3d657f5e601ac657bac9b396b50ee97bd29cd55436320cf1cddebdcec72 + languageName: node + linkType: hard + +"serve-static@npm:^2.2.0": + version: 2.2.1 + resolution: "serve-static@npm:2.2.1" + dependencies: + encodeurl: "npm:^2.0.0" + escape-html: "npm:^1.0.3" + parseurl: "npm:^1.3.3" + send: "npm:^1.2.0" + checksum: 10c0/37986096e8572e2dfaad35a3925fa8da0c0969f8814fd7788e84d4d388bc068cf0c06d1658509788e55bed942a6b6d040a8a267fa92bb9ffb1179f8bacde5fd7 + languageName: node + linkType: hard + +"session-file-store@npm:^1.5.0": + version: 1.5.0 + resolution: "session-file-store@npm:1.5.0" + dependencies: + bagpipe: "npm:^0.3.5" + fs-extra: "npm:^8.0.1" + kruptein: "npm:^2.0.4" + object-assign: "npm:^4.1.1" + retry: "npm:^0.12.0" + write-file-atomic: "npm:3.0.3" + checksum: 10c0/85985e949588a5633d970a00a506931b4605fbaa546c494b253e462807179d213965bb4f75385d9cdf8f17af8fa00fab3c5822daa6f9ebb58038a1527c4cfbdd + languageName: node + linkType: hard + +"setprototypeof@npm:~1.2.0": + version: 1.2.0 + resolution: "setprototypeof@npm:1.2.0" + checksum: 10c0/68733173026766fa0d9ecaeb07f0483f4c2dc70ca376b3b7c40b7cda909f94b0918f6c5ad5ce27a9160bdfb475efaa9d5e705a11d8eaae18f9835d20976028bc + languageName: node + linkType: hard + +"sharp@npm:^0.34.5": + version: 0.34.5 + resolution: "sharp@npm:0.34.5" + dependencies: + "@img/colour": "npm:^1.0.0" + "@img/sharp-darwin-arm64": "npm:0.34.5" + "@img/sharp-darwin-x64": "npm:0.34.5" + "@img/sharp-libvips-darwin-arm64": "npm:1.2.4" + "@img/sharp-libvips-darwin-x64": "npm:1.2.4" + "@img/sharp-libvips-linux-arm": "npm:1.2.4" + "@img/sharp-libvips-linux-arm64": "npm:1.2.4" + "@img/sharp-libvips-linux-ppc64": "npm:1.2.4" + "@img/sharp-libvips-linux-riscv64": "npm:1.2.4" + "@img/sharp-libvips-linux-s390x": "npm:1.2.4" + "@img/sharp-libvips-linux-x64": "npm:1.2.4" + "@img/sharp-libvips-linuxmusl-arm64": "npm:1.2.4" + "@img/sharp-libvips-linuxmusl-x64": "npm:1.2.4" + "@img/sharp-linux-arm": "npm:0.34.5" + "@img/sharp-linux-arm64": "npm:0.34.5" + "@img/sharp-linux-ppc64": "npm:0.34.5" + "@img/sharp-linux-riscv64": "npm:0.34.5" + "@img/sharp-linux-s390x": "npm:0.34.5" + "@img/sharp-linux-x64": "npm:0.34.5" + "@img/sharp-linuxmusl-arm64": "npm:0.34.5" + "@img/sharp-linuxmusl-x64": "npm:0.34.5" + "@img/sharp-wasm32": "npm:0.34.5" + "@img/sharp-win32-arm64": "npm:0.34.5" + "@img/sharp-win32-ia32": "npm:0.34.5" + "@img/sharp-win32-x64": "npm:0.34.5" + detect-libc: "npm:^2.1.2" + semver: "npm:^7.7.3" + dependenciesMeta: + "@img/sharp-darwin-arm64": + optional: true + "@img/sharp-darwin-x64": + optional: true + "@img/sharp-libvips-darwin-arm64": + optional: true + "@img/sharp-libvips-darwin-x64": + optional: true + "@img/sharp-libvips-linux-arm": + optional: true + "@img/sharp-libvips-linux-arm64": + optional: true + "@img/sharp-libvips-linux-ppc64": + optional: true + "@img/sharp-libvips-linux-riscv64": + optional: true + "@img/sharp-libvips-linux-s390x": + optional: true + "@img/sharp-libvips-linux-x64": + optional: true + "@img/sharp-libvips-linuxmusl-arm64": + optional: true + "@img/sharp-libvips-linuxmusl-x64": + optional: true + "@img/sharp-linux-arm": + optional: true + "@img/sharp-linux-arm64": + optional: true + "@img/sharp-linux-ppc64": + optional: true + "@img/sharp-linux-riscv64": + optional: true + "@img/sharp-linux-s390x": + optional: true + "@img/sharp-linux-x64": + optional: true + "@img/sharp-linuxmusl-arm64": + optional: true + "@img/sharp-linuxmusl-x64": + optional: true + "@img/sharp-wasm32": + optional: true + "@img/sharp-win32-arm64": + optional: true + "@img/sharp-win32-ia32": + optional: true + "@img/sharp-win32-x64": + optional: true + checksum: 10c0/fd79e29df0597a7d5704b8461c51f944ead91a5243691697be6e8243b966402beda53ddc6f0a53b96ea3cb8221f0b244aa588114d3ebf8734fb4aefd41ab802f + languageName: node + linkType: hard + +"shebang-command@npm:^2.0.0": + version: 2.0.0 + resolution: "shebang-command@npm:2.0.0" + dependencies: + shebang-regex: "npm:^3.0.0" + checksum: 10c0/a41692e7d89a553ef21d324a5cceb5f686d1f3c040759c50aab69688634688c5c327f26f3ecf7001ebfd78c01f3c7c0a11a7c8bfd0a8bc9f6240d4f40b224e4e + languageName: node + linkType: hard + +"shebang-regex@npm:^3.0.0": + version: 3.0.0 + resolution: "shebang-regex@npm:3.0.0" + checksum: 10c0/1dbed0726dd0e1152a92696c76c7f06084eb32a90f0528d11acd764043aacf76994b2fb30aa1291a21bd019d6699164d048286309a278855ee7bec06cf6fb690 + languageName: node + linkType: hard + +"side-channel-list@npm:^1.0.0": + version: 1.0.1 + resolution: "side-channel-list@npm:1.0.1" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.4" + checksum: 10c0/d346c787fd2f9f1c2fdea14f00e8250118db0e7596d85a6cb9faa75f105d31a73a8f7a341c93d7df2a2429098c3d37a77bd3be9e88c37094b8c01807bc77c7a2 + languageName: node + linkType: hard + +"side-channel-map@npm:^1.0.1": + version: 1.0.1 + resolution: "side-channel-map@npm:1.0.1" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + checksum: 10c0/010584e6444dd8a20b85bc926d934424bd809e1a3af941cace229f7fdcb751aada0fb7164f60c2e22292b7fa3c0ff0bce237081fd4cdbc80de1dc68e95430672 + languageName: node + linkType: hard + +"side-channel-weakmap@npm:^1.0.2": + version: 1.0.2 + resolution: "side-channel-weakmap@npm:1.0.2" + dependencies: + call-bound: "npm:^1.0.2" + es-errors: "npm:^1.3.0" + get-intrinsic: "npm:^1.2.5" + object-inspect: "npm:^1.13.3" + side-channel-map: "npm:^1.0.1" + checksum: 10c0/71362709ac233e08807ccd980101c3e2d7efe849edc51455030327b059f6c4d292c237f94dc0685031dd11c07dd17a68afde235d6cf2102d949567f98ab58185 + languageName: node + linkType: hard + +"side-channel@npm:^1.1.0": + version: 1.1.0 + resolution: "side-channel@npm:1.1.0" + dependencies: + es-errors: "npm:^1.3.0" + object-inspect: "npm:^1.13.3" + side-channel-list: "npm:^1.0.0" + side-channel-map: "npm:^1.0.1" + side-channel-weakmap: "npm:^1.0.2" + checksum: 10c0/cb20dad41eb032e6c24c0982e1e5a24963a28aa6122b4f05b3f3d6bf8ae7fd5474ef382c8f54a6a3ab86e0cac4d41a23bd64ede3970e5bfb50326ba02a7996e6 + languageName: node + linkType: hard + +"siginfo@npm:^2.0.0": + version: 2.0.0 + resolution: "siginfo@npm:2.0.0" + checksum: 10c0/3def8f8e516fbb34cb6ae415b07ccc5d9c018d85b4b8611e3dc6f8be6d1899f693a4382913c9ed51a06babb5201639d76453ab297d1c54a456544acf5c892e34 + languageName: node + linkType: hard + +"signal-exit@npm:^3.0.2": + version: 3.0.7 + resolution: "signal-exit@npm:3.0.7" + checksum: 10c0/25d272fa73e146048565e08f3309d5b942c1979a6f4a58a8c59d5fa299728e9c2fcd1a759ec870863b1fd38653670240cd420dad2ad9330c71f36608a6a1c912 + languageName: node + linkType: hard + +"source-map-js@npm:^1.2.1": + version: 1.2.1 + resolution: "source-map-js@npm:1.2.1" + checksum: 10c0/7bda1fc4c197e3c6ff17de1b8b2c20e60af81b63a52cb32ec5a5d67a20a7d42651e2cb34ebe93833c5a2a084377e17455854fee3e21e7925c64a51b6a52b0faf + languageName: node + linkType: hard + +"stackback@npm:0.0.2": + version: 0.0.2 + resolution: "stackback@npm:0.0.2" + checksum: 10c0/89a1416668f950236dd5ac9f9a6b2588e1b9b62b1b6ad8dff1bfc5d1a15dbf0aafc9b52d2226d00c28dffff212da464eaeebfc6b7578b9d180cef3e3782c5983 + languageName: node + linkType: hard + +"statuses@npm:^2.0.1, statuses@npm:^2.0.2, statuses@npm:~2.0.2": + version: 2.0.2 + resolution: "statuses@npm:2.0.2" + checksum: 10c0/a9947d98ad60d01f6b26727570f3bcceb6c8fa789da64fe6889908fe2e294d57503b14bf2b5af7605c2d36647259e856635cd4c49eab41667658ec9d0080ec3f + languageName: node + linkType: hard + +"std-env@npm:^4.0.0-rc.1": + version: 4.1.0 + resolution: "std-env@npm:4.1.0" + checksum: 10c0/2e14b6b490db34cb969a48d9cf7c35bca4a47653914aac2814221baae7b867a5b15940d133625c391621971f98cd2266a5dc7036669960e883f1081db2a56558 + languageName: node + linkType: hard + +"synckit@npm:^0.11.12": + version: 0.11.12 + resolution: "synckit@npm:0.11.12" + dependencies: + "@pkgr/core": "npm:^0.2.9" + checksum: 10c0/cc4d446806688ae0d728ae7bb3f53176d065cf9536647fb85bdd721dcefbd7bf94874df6799ff61580f2b03a392659219b778a9254ad499f9a1f56c34787c235 + languageName: node + linkType: hard + +"tar@npm:^7.5.4": + version: 7.5.15 + resolution: "tar@npm:7.5.15" + dependencies: + "@isaacs/fs-minipass": "npm:^4.0.0" + chownr: "npm:^3.0.0" + minipass: "npm:^7.1.2" + minizlib: "npm:^3.1.0" + yallist: "npm:^5.0.0" + checksum: 10c0/8f039edb1d12fdd7df6c6f9877d125afe9f3da3f5f9317df326fdd090d48793d6998cede1506a1471f3e3a250db270a89dace28005eb5e99c5a9132d704ac956 + languageName: node + linkType: hard + +"tinybench@npm:^2.9.0": + version: 2.9.0 + resolution: "tinybench@npm:2.9.0" + checksum: 10c0/c3500b0f60d2eb8db65250afe750b66d51623057ee88720b7f064894a6cb7eb93360ca824a60a31ab16dab30c7b1f06efe0795b352e37914a9d4bad86386a20c + languageName: node + linkType: hard + +"tinyexec@npm:^1.0.2": + version: 1.1.2 + resolution: "tinyexec@npm:1.1.2" + checksum: 10c0/9e0ef6c001ce54688cf16833a02f70a339276219ca947b88930b124267de2cffc764ff44e87e7369384b1d75ab63491465412cbbdf06f2437956b9ab66ab4491 + languageName: node + linkType: hard + +"tinyglobby@npm:^0.2.12, tinyglobby@npm:^0.2.15, tinyglobby@npm:^0.2.16": + version: 0.2.16 + resolution: "tinyglobby@npm:0.2.16" + dependencies: + fdir: "npm:^6.5.0" + picomatch: "npm:^4.0.4" + checksum: 10c0/f2e09fd93dd95c41e522113b686ff6f7c13020962f8698a864a257f3d7737599afc47722b7ab726e12f8a813f779906187911ff8ee6701ede65072671a7e934b + languageName: node + linkType: hard + +"tinyrainbow@npm:^3.1.0": + version: 3.1.0 + resolution: "tinyrainbow@npm:3.1.0" + checksum: 10c0/f11cf387a26c5c9255bec141a90ac511b26172981b10c3e50053bc6700ea7d2336edcc4a3a21dbb8412fe7c013477d2ba4d7e4877800f3f8107be5105aad6511 + languageName: node + linkType: hard + +"toidentifier@npm:~1.0.1": + version: 1.0.1 + resolution: "toidentifier@npm:1.0.1" + checksum: 10c0/93937279934bd66cc3270016dd8d0afec14fb7c94a05c72dc57321f8bd1fa97e5bea6d1f7c89e728d077ca31ea125b78320a616a6c6cd0e6b9cb94cb864381c1 + languageName: node + linkType: hard + +"tslib@npm:^2.4.0": + version: 2.8.1 + resolution: "tslib@npm:2.8.1" + checksum: 10c0/9c4759110a19c53f992d9aae23aac5ced636e99887b51b9e61def52611732872ff7668757d4e4c61f19691e36f4da981cd9485e869b4a7408d689f6bf1f14e62 + languageName: node + linkType: hard + +"twtxt-lib@npm:^0.10.1": + version: 0.10.1 + resolution: "twtxt-lib@npm:0.10.1" + dependencies: + "@exodus/blakejs": "npm:^1.1.1-exodus.0" + base32.js: "npm:^0.1.0" + dayjs: "npm:^1.11.20" + checksum: 10c0/6892e2e320111e060ca24bb6f69b81c404aea81e96a73cdd4c91141502e3628aa67d10522bf9489090be119ffd17afaf028ab4b793381f27921f70f20ac4326c + languageName: node + linkType: hard + +"type-check@npm:^0.4.0, type-check@npm:~0.4.0": + version: 0.4.0 + resolution: "type-check@npm:0.4.0" + dependencies: + prelude-ls: "npm:^1.2.1" + checksum: 10c0/7b3fd0ed43891e2080bf0c5c504b418fbb3e5c7b9708d3d015037ba2e6323a28152ec163bcb65212741fa5d2022e3075ac3c76440dbd344c9035f818e8ecee58 + languageName: node + linkType: hard + +"type-is@npm:^2.0.1": + version: 2.0.1 + resolution: "type-is@npm:2.0.1" + dependencies: + content-type: "npm:^1.0.5" + media-typer: "npm:^1.1.0" + mime-types: "npm:^3.0.0" + checksum: 10c0/7f7ec0a060b16880bdad36824ab37c26019454b67d73e8a465ed5a3587440fbe158bc765f0da68344498235c877e7dbbb1600beccc94628ed05599d667951b99 + languageName: node + linkType: hard + +"typedarray-to-buffer@npm:^3.1.5": + version: 3.1.5 + resolution: "typedarray-to-buffer@npm:3.1.5" + dependencies: + is-typedarray: "npm:^1.0.0" + checksum: 10c0/4ac5b7a93d604edabf3ac58d3a2f7e07487e9f6e98195a080e81dbffdc4127817f470f219d794a843b87052cedef102b53ac9b539855380b8c2172054b7d5027 + languageName: node + linkType: hard + +"typescript@npm:^6.0.3": + version: 6.0.3 + resolution: "typescript@npm:6.0.3" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/4a25ff5045b984370f48f196b3a0120779b1b343d40b9a68d114ea5e5fff099809b2bb777576991a63a5cd59cf7bffd96ff6fe10afcefbcb8bd6fb96ad4b6606 + languageName: node + linkType: hard + +"typescript@patch:typescript@npm%3A^6.0.3#optional!builtin": + version: 6.0.3 + resolution: "typescript@patch:typescript@npm%3A6.0.3#optional!builtin::version=6.0.3&hash=5786d5" + bin: + tsc: bin/tsc + tsserver: bin/tsserver + checksum: 10c0/2f25c74e65663c248fa1ade2b8459d9ce5372ff9dad07067310f132966ebec1d93f6c42f0baf77a6b6a7a91460463f708e6887013aaade22111037457c6b25df + languageName: node + linkType: hard + +"uid-safe@npm:~2.1.5": + version: 2.1.5 + resolution: "uid-safe@npm:2.1.5" + dependencies: + random-bytes: "npm:~1.0.0" + checksum: 10c0/ec96862e859fd12175f3da7fda9d1359a2cf412fd521e10837cbdc6d554774079ce252f366981df9401283841c8924782f6dbee8f82a3a81f805ed8a8584595d + languageName: node + linkType: hard + +"undici-types@npm:~7.21.0": + version: 7.21.0 + resolution: "undici-types@npm:7.21.0" + checksum: 10c0/c3b4ae5f066c398acb1962505b56214ecd72843f7d7827fcc2df7a48a63d1639d3608c580ac09f836253d21fa7ba8f1a04440569ed9d332474ad01b8a010db87 + languageName: node + linkType: hard + +"undici@npm:^6.25.0": + version: 6.25.0 + resolution: "undici@npm:6.25.0" + checksum: 10c0/2597cc6689bdb02c210c557b1f85febbfda65becae6e6fc1061508e2f33734d25207f81cd8af56ada9956329eb3a7bd7431e87dcfeceba20ee87059b57dcf985 + languageName: node + linkType: hard + +"universalify@npm:^0.1.0": + version: 0.1.2 + resolution: "universalify@npm:0.1.2" + checksum: 10c0/e70e0339f6b36f34c9816f6bf9662372bd241714dc77508d231d08386d94f2c4aa1ba1318614f92015f40d45aae1b9075cd30bd490efbe39387b60a76ca3f045 + languageName: node + linkType: hard + +"unpipe@npm:~1.0.0": + version: 1.0.0 + resolution: "unpipe@npm:1.0.0" + checksum: 10c0/193400255bd48968e5c5383730344fbb4fa114cdedfab26e329e50dd2d81b134244bb8a72c6ac1b10ab0281a58b363d06405632c9d49ca9dfd5e90cbd7d0f32c + languageName: node + linkType: hard + +"uri-js@npm:^4.2.2": + version: 4.4.1 + resolution: "uri-js@npm:4.4.1" + dependencies: + punycode: "npm:^2.1.0" + checksum: 10c0/4ef57b45aa820d7ac6496e9208559986c665e49447cb072744c13b66925a362d96dd5a46c4530a6b8e203e5db5fe849369444440cb22ecfc26c679359e5dfa3c + languageName: node + linkType: hard + +"uuid@npm:^14.0.0": + version: 14.0.0 + resolution: "uuid@npm:14.0.0" + bin: + uuid: dist-node/bin/uuid + checksum: 10c0/a57ae7794c45005c1a9208989196c5baf79a7679c30f43c1bee9033a2c4d113a2cea216fa6fcc9663b08b0d55635df1a7c6eb7e7f3d21c3e50688c698fa39a50 + languageName: node + linkType: hard + +"vary@npm:^1.1.2": + version: 1.1.2 + resolution: "vary@npm:1.1.2" + checksum: 10c0/f15d588d79f3675135ba783c91a4083dcd290a2a5be9fcb6514220a1634e23df116847b1cc51f66bfb0644cf9353b2abb7815ae499bab06e46dd33c1a6bf1f4f + languageName: node + linkType: hard + +"vite@npm:^6.0.0 || ^7.0.0 || ^8.0.0": + version: 8.0.12 + resolution: "vite@npm:8.0.12" + dependencies: + fsevents: "npm:~2.3.3" + lightningcss: "npm:^1.32.0" + picomatch: "npm:^4.0.4" + postcss: "npm:^8.5.14" + rolldown: "npm:1.0.0" + tinyglobby: "npm:^0.2.16" + peerDependencies: + "@types/node": ^20.19.0 || >=22.12.0 + "@vitejs/devtools": ^0.1.18 + esbuild: ^0.27.0 || ^0.28.0 + jiti: ">=1.21.0" + less: ^4.0.0 + sass: ^1.70.0 + sass-embedded: ^1.70.0 + stylus: ">=0.54.8" + sugarss: ^5.0.0 + terser: ^5.16.0 + tsx: ^4.8.1 + yaml: ^2.4.2 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + "@vitejs/devtools": + optional: true + esbuild: + optional: true + jiti: + optional: true + less: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + tsx: + optional: true + yaml: + optional: true + bin: + vite: bin/vite.js + checksum: 10c0/4711efaa2a7a07755a8bed38cc8753fe3bd51d9cbe8e684a47a1a60dc752eddd2eefa5b88f7b6d7edfab9c0ed9d558ca4d1ae162e60fb64e21a9924c7771047b + languageName: node + linkType: hard + +"vitest@npm:^4.1.5": + version: 4.1.6 + resolution: "vitest@npm:4.1.6" + dependencies: + "@vitest/expect": "npm:4.1.6" + "@vitest/mocker": "npm:4.1.6" + "@vitest/pretty-format": "npm:4.1.6" + "@vitest/runner": "npm:4.1.6" + "@vitest/snapshot": "npm:4.1.6" + "@vitest/spy": "npm:4.1.6" + "@vitest/utils": "npm:4.1.6" + es-module-lexer: "npm:^2.0.0" + expect-type: "npm:^1.3.0" + magic-string: "npm:^0.30.21" + obug: "npm:^2.1.1" + pathe: "npm:^2.0.3" + picomatch: "npm:^4.0.3" + std-env: "npm:^4.0.0-rc.1" + tinybench: "npm:^2.9.0" + tinyexec: "npm:^1.0.2" + tinyglobby: "npm:^0.2.15" + tinyrainbow: "npm:^3.1.0" + vite: "npm:^6.0.0 || ^7.0.0 || ^8.0.0" + why-is-node-running: "npm:^2.3.0" + peerDependencies: + "@edge-runtime/vm": "*" + "@opentelemetry/api": ^1.9.0 + "@types/node": ^20.0.0 || ^22.0.0 || >=24.0.0 + "@vitest/browser-playwright": 4.1.6 + "@vitest/browser-preview": 4.1.6 + "@vitest/browser-webdriverio": 4.1.6 + "@vitest/coverage-istanbul": 4.1.6 + "@vitest/coverage-v8": 4.1.6 + "@vitest/ui": 4.1.6 + happy-dom: "*" + jsdom: "*" + vite: ^6.0.0 || ^7.0.0 || ^8.0.0 + peerDependenciesMeta: + "@edge-runtime/vm": + optional: true + "@opentelemetry/api": + optional: true + "@types/node": + optional: true + "@vitest/browser-playwright": + optional: true + "@vitest/browser-preview": + optional: true + "@vitest/browser-webdriverio": + optional: true + "@vitest/coverage-istanbul": + optional: true + "@vitest/coverage-v8": + optional: true + "@vitest/ui": + optional: true + happy-dom: + optional: true + jsdom: + optional: true + vite: + optional: false + bin: + vitest: vitest.mjs + checksum: 10c0/1da4c23f02cd39cb20a857d48462d1d6100eeb4644fc0defc7c6eef9d481f85d2598b72d39eb4a8d271fafa8328ac3ffcca11b27865385e88d9d65c8b29b8091 + languageName: node + linkType: hard + +"which@npm:^2.0.1": + version: 2.0.2 + resolution: "which@npm:2.0.2" + dependencies: + isexe: "npm:^2.0.0" + bin: + node-which: ./bin/node-which + checksum: 10c0/66522872a768b60c2a65a57e8ad184e5372f5b6a9ca6d5f033d4b0dc98aff63995655a7503b9c0a2598936f532120e81dd8cc155e2e92ed662a2b9377cc4374f + languageName: node + linkType: hard + +"which@npm:^6.0.0": + version: 6.0.1 + resolution: "which@npm:6.0.1" + dependencies: + isexe: "npm:^4.0.0" + bin: + node-which: bin/which.js + checksum: 10c0/7e710e54ea36d2d6183bee2f9caa27a3b47b9baf8dee55a199b736fcf85eab3b9df7556fca3d02b50af7f3dfba5ea3a45644189836df06267df457e354da66d5 + languageName: node + linkType: hard + +"why-is-node-running@npm:^2.3.0": + version: 2.3.0 + resolution: "why-is-node-running@npm:2.3.0" + dependencies: + siginfo: "npm:^2.0.0" + stackback: "npm:0.0.2" + bin: + why-is-node-running: cli.js + checksum: 10c0/1cde0b01b827d2cf4cb11db962f3958b9175d5d9e7ac7361d1a7b0e2dc6069a263e69118bd974c4f6d0a890ef4eedfe34cf3d5167ec14203dbc9a18620537054 + languageName: node + linkType: hard + +"word-wrap@npm:^1.2.5": + version: 1.2.5 + resolution: "word-wrap@npm:1.2.5" + checksum: 10c0/e0e4a1ca27599c92a6ca4c32260e8a92e8a44f4ef6ef93f803f8ed823f486e0889fc0b93be4db59c8d51b3064951d25e43d434e95dc8c960cc3a63d65d00ba20 + languageName: node + linkType: hard + +"wrappy@npm:1": + version: 1.0.2 + resolution: "wrappy@npm:1.0.2" + checksum: 10c0/56fece1a4018c6a6c8e28fbc88c87e0fbf4ea8fd64fc6c63b18f4acc4bd13e0ad2515189786dd2c30d3eec9663d70f4ecf699330002f8ccb547e4a18231fc9f0 + languageName: node + linkType: hard + +"write-file-atomic@npm:3.0.3": + version: 3.0.3 + resolution: "write-file-atomic@npm:3.0.3" + dependencies: + imurmurhash: "npm:^0.1.4" + is-typedarray: "npm:^1.0.0" + signal-exit: "npm:^3.0.2" + typedarray-to-buffer: "npm:^3.1.5" + checksum: 10c0/7fb67affd811c7a1221bed0c905c26e28f0041e138fb19ccf02db57a0ef93ea69220959af3906b920f9b0411d1914474cdd90b93a96e5cd9e8368d9777caac0e + languageName: node + linkType: hard + +"yallist@npm:^5.0.0": + version: 5.0.0 + resolution: "yallist@npm:5.0.0" + checksum: 10c0/a499c81ce6d4a1d260d4ea0f6d49ab4da09681e32c3f0472dee16667ed69d01dae63a3b81745a24bd78476ec4fcf856114cb4896ace738e01da34b2c42235416 + languageName: node + linkType: hard + +"yocto-queue@npm:^0.1.0": + version: 0.1.0 + resolution: "yocto-queue@npm:0.1.0" + checksum: 10c0/dceb44c28578b31641e13695d200d34ec4ab3966a5729814d5445b194933c096b7ced71494ce53a0e8820685d1d010df8b2422e5bf2cdea7e469d97ffbea306f + languageName: node + linkType: hard + +"zod@npm:^4.4.3": + version: 4.4.3 + resolution: "zod@npm:4.4.3" + checksum: 10c0/7ea31b558e88f9faf44f31dd185e2e1cbf51fed3081787fb96cc2534749b50c0acfc6da7f0922a7353ed092dd358c7d50c28ea96c94d04af64191bd33152eca3 + languageName: node + linkType: hard