Snapshot of main at 9f39a6e1e (2026-11-02)

This commit is contained in:
Ronald Huynen committed 2026-11-02 10:41:47 +01:00
commit 6ccf1792d7
2580 files changed
+1040202

No files matched your search

+202
View File
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2020 Nolan Lawson
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,257 @@
{
"schemaVersion": "1.0.0",
"readme": "",
"modules": [
{
"kind": "javascript-module",
"path": "picker.js",
"declarations": [
{
"kind": "class",
"description": "Lightweight emoji picker distributed as a web component",
"name": "Picker",
"superclass": {
"name": "HTMLElement"
},
"tagName": "emoji-picker",
"customElement": true,
"attributes": [
{
"name": "locale",
"description": "Locale string",
"type": "string",
"default": "\"en\""
},
{
"name": "data-source",
"description": "URL to fetch the emoji data from",
"type": "string",
"default": "\"https://cdn.jsdelivr.net/npm/emoji-picker-element-data@^1/en/emojibase/data.json\""
},
{
"name": "skin-tone-emoji",
"description": "The emoji to use for the skin tone picker",
"type": "string",
"default": "\"🖐\""
},
{
"name": "emoji-version",
"description": "Maximum supported emoji version as a number (e.g. `14.0` or `13.1`). Setting this disables the default emoji support detection.",
"type": "string",
"default": null
}
],
"members": [
{
"name": "locale",
"description": "Locale string",
"kind": "field",
"default": "\"en\""
},
{
"name": "dataSource",
"description": "URL to fetch the emoji data from",
"kind": "field",
"default": "\"https://cdn.jsdelivr.net/npm/emoji-picker-element-data@^1/en/emojibase/data.json\""
},
{
"name": "skinToneEmoji",
"description": "The emoji to use for the skin tone picker",
"kind": "field",
"default": "\"🖐\""
},
{
"name": "i18n",
"description": "i18n object",
"kind": "field"
},
{
"name": "customEmoji",
"description": "Array of custom emoji",
"kind": "field"
},
{
"name": "customCategorySorting",
"description": "Function to sort custom category strings (sorted alphabetically by default)",
"kind": "field"
},
{
"name": "emojiVersion",
"description": "Maximum supported emoji version as a number (e.g. `14.0` or `13.1`). Setting this disables the default emoji support detection.",
"kind": "field"
}
],
"events": [
{
"name": "skin-tone-change",
"description": "This event is fired whenever the user selects a new skin tone."
},
{
"name": "emoji-click",
"description": "The `emoji-click` event is fired when an emoji is selected by the user."
},
{
"name": "emoji-click-sync",
"description": "The `emoji-click-sync` event is fired synchronously when an emoji is selected by the user. Use this when copying data to the clipboard using the Clipboard API to work around a Safari bug."
}
],
"cssProperties": [
{
"name": "--background",
"description": "Background of the entire `<emoji-picker>` (default: `#fff`, dark default: `#222`)",
"default": "\"#fff\""
},
{
"name": "--border-color",
"description": "(default: `#e0e0e0`, dark default: `#444`)",
"default": "\"#e0e0e0\""
},
{
"name": "--border-radius",
"description": "Border radius of the entire picker (default: `0`)",
"default": "\"0\""
},
{
"name": "--border-size",
"description": "Width of border used in most of the picker (default: `1px`)",
"default": "\"1px\""
},
{
"name": "--button-active-background",
"description": "Background of an active button (default: `#e6e6e6`, dark default: `#555555`)",
"default": "\"#e6e6e6\""
},
{
"name": "--button-hover-background",
"description": "Background of a hovered button (default: `#d9d9d9`, dark default: `#484848`)",
"default": "\"#d9d9d9\""
},
{
"name": "--category-emoji-padding",
"description": "Vertical/horizontal padding on category emoji, if you want it to be different from `--emoji-padding` (default: `var(--emoji-padding)`)",
"default": "\"var(--emoji-padding)\""
},
{
"name": "--category-emoji-size",
"description": "Width/height of category emoji, if you want it to be different from `--emoji-size` (default: `var(--emoji-size)`)",
"default": "\"var(--emoji-size)\""
},
{
"name": "--category-font-color",
"description": "Font color of custom emoji category headings (default: `#111`, dark default: `#efefef`)",
"default": "\"#111\""
},
{
"name": "--category-font-size",
"description": "Font size of custom emoji category headings (default: `1rem`)",
"default": "\"1rem\""
},
{
"name": "--emoji-font-family",
"description": "Font family for a custom emoji font (as opposed to native emoji) (default: `\"Twemoji Mozilla\",\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\",\"Noto Color Emoji\",\"EmojiOne Color\",\"Android Emoji\",sans-serif`)",
"default": "\"\\\"Twemoji Mozilla\\\",\\\"Apple Color Emoji\\\",\\\"Segoe UI Emoji\\\",\\\"Segoe UI Symbol\\\",\\\"Noto Color Emoji\\\",\\\"EmojiOne Color\\\",\\\"Android Emoji\\\",sans-serif\""
},
{
"name": "--emoji-padding",
"description": "Vertical and horizontal padding on emoji (default: `0.5rem`)",
"default": "\"0.5rem\""
},
{
"name": "--emoji-size",
"description": "Width and height of all emoji (default: `1.375rem`)",
"default": "\"1.375rem\""
},
{
"name": "--indicator-color",
"description": "Color of the nav indicator (default: `#385ac1`, dark default: `#5373ec`)",
"default": "\"#385ac1\""
},
{
"name": "--indicator-height",
"description": "Height of the nav indicator (default: `3px`)",
"default": "\"3px\""
},
{
"name": "--input-border-color",
"description": "(default: `#999`, dark default: `#ccc`)",
"default": "\"#999\""
},
{
"name": "--input-border-radius",
"description": "(default: `0.5rem`)",
"default": "\"0.5rem\""
},
{
"name": "--input-border-size",
"description": "(default: `1px`)",
"default": "\"1px\""
},
{
"name": "--input-font-color",
"description": "(default: `#111`, dark default: `#efefef`)",
"default": "\"#111\""
},
{
"name": "--input-font-size",
"description": "(default: `1rem`)",
"default": "\"1rem\""
},
{
"name": "--input-line-height",
"description": "(default: `1.5`)",
"default": "\"1.5\""
},
{
"name": "--input-padding",
"description": "(default: `0.25rem`)",
"default": "\"0.25rem\""
},
{
"name": "--input-placeholder-color",
"description": "(default: `#999`, dark default: `#ccc`)",
"default": "\"#999\""
},
{
"name": "--num-columns",
"description": "How many columns to display in the emoji grid (default: `8`)",
"default": "\"8\""
},
{
"name": "--outline-color",
"description": "Focus outline color (default: `#999`, dark default: `#fff`)",
"default": "\"#999\""
},
{
"name": "--outline-size",
"description": "Focus outline width (default: `2px`)",
"default": "\"2px\""
},
{
"name": "--skintone-border-radius",
"description": "Border radius of the skintone dropdown (default: `1rem`)",
"default": "\"1rem\""
}
]
}
],
"exports": [
{
"kind": "custom-element-definition",
"name": "emoji-picker",
"declaration": {
"name": "Picker",
"module": "picker.js"
}
},
{
"kind": "js",
"name": "default",
"declaration": {
"name": "Picker",
"module": "picker.js"
}
}
]
}
]
}
+108
View File
@@ -0,0 +1,108 @@
import { Emoji, DatabaseConstructorOptions, SkinTone, CustomEmoji, NativeEmoji } from "./shared.js";
export default class Database {
/**
* Create a new Database.
*
* Note that multiple Databases pointing to the same locale will share the
* same underlying IndexedDB connection and database.
*
* @param dataSource - URL to fetch the emoji data from
* @param locale - Locale string
* @param customEmoji - Array of custom emoji
*/
constructor({ dataSource, locale, customEmoji }?: DatabaseConstructorOptions);
/**
* Resolves when the Database is ready, or throws an error if
* the Database could not initialize.
*
* Note that you don't need to do this before calling other APIs – they will
* all wait for this promise to resolve before doing anything.
*/
ready(): Promise<void>;
/**
* Returns all emoji belonging to a group, ordered by `order`. Only returns native emoji;
* custom emoji don't belong to a group.
*
* Non-numbers throw an error.
* @param group - the group number
*/
getEmojiByGroup(group: number): Promise<NativeEmoji[]>;
/**
* Returns all emoji matching the given search query, ordered by `order`.
*
* Empty/null strings throw an error.
*
* @param query - search query string
*/
getEmojiBySearchQuery(query: string): Promise<Emoji[]>;
/**
* Return a single emoji matching the shortcode, or null if not found.
*
* The colons around the shortcode should not be included when querying, e.g.
* use "slight_smile", not ":slight_smile:". Uppercase versus lowercase
* does not matter. Empty/null strings throw an error.
* @param shortcode
*/
getEmojiByShortcode(shortcode: string): Promise<Emoji | null>;
/**
* Return a single native emoji matching the unicode string, or
* a custom emoji matching the name, or null if not found.
*
* In the case of native emoji, the unicode string can be either the
* main unicode string, or the unicode of one of the skin tone variants.
*
* Empty/null strings throw an error.
* @param unicodeOrName - unicode (native emoji) or name (custom emoji)
*/
getEmojiByUnicodeOrName(unicodeOrName: string): Promise<Emoji | null>;
/**
* Get the user's preferred skin tone. Returns 0 if not found.
*/
getPreferredSkinTone(): Promise<SkinTone>;
/**
* Set the user's preferred skin tone. Non-numbers throw an error.
*
* @param skinTone - preferred skin tone
*/
setPreferredSkinTone(skinTone: SkinTone): Promise<void>;
/**
* Increment the favorite count for an emoji by one. The unicode string must be non-empty. It should
* correspond to the base (non-skin-tone) unicode string from the emoji object, or in the case of
* custom emoji, it should be the name.
*
* @param unicodeOrName - unicode of a native emoji, or name of a custom emoji
*/
incrementFavoriteEmojiCount(unicodeOrName: string): Promise<void>;
/**
* Get the top favorite emoji in descending order. If there are no favorite emoji yet, returns an empty array.
* @param limit - maximum number of results to return
*/
getTopFavoriteEmoji(limit: number): Promise<Emoji[]>;
/**
* Set the custom emoji for this database. Throws an error if custom emoji are not in the correct format.
*
*
* @param customEmoji
*/
set customEmoji(customEmoji: CustomEmoji[]);
/**
* Return the custom emoji associated with this Database, or the empty array if none.
*/
get customEmoji(): CustomEmoji[];
/**
* Closes the underlying IndexedDB connection. The Database is not usable after that (or any other Databases
* with the same locale).
*
* Note that as soon as any other non-close/delete method is called, the database will automatically reopen.
*
*/
close(): Promise<void>;
/**
* Deletes the underlying IndexedDB database. The Database is not usable after that (or any other Databases
* with the same locale).
*
* Note that as soon as any other non-close/delete method is called, the database will be recreated.
*
*/
delete(): Promise<void>;
}
File diff suppressed because it is too large. Load diff
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"database.js","sources":["src/database/utils/assertNonEmptyString.js","src/database/utils/assertNumber.js","src/database/constants.js","src/shared/uniqBy.js","src/database/utils/uniqEmoji.js","src/database/migrations.js","src/database/databaseLifecycle.js","src/database/utils/extractTokens.js","src/shared/constants.js","src/database/utils/normalizeTokens.js","src/database/utils/transformEmojiData.js","src/database/idbUtil.js","src/database/utils/minBy.js","src/database/utils/findCommonMembers.js","src/database/idbInterface.js","src/database/utils/trie.js","src/database/utils/assertCustomEmojis.js","src/database/customEmojiIndex.js","src/database/utils/cleanEmoji.js","src/database/utils/warnETag.js","src/database/utils/requiredKeys.js","src/database/utils/assertEmojiData.js","src/database/utils/ajax.js","node_modules/.pnpm/blob-util@2.0.2/node_modules/blob-util/dist/blob-util.es.js","src/database/utils/jsonChecksum.js","src/database/dataLoading.js","src/database/Database.js"],"sourcesContent":["export function assertNonEmptyString (str) {\n if (typeof str !== 'string' || !str) {\n throw new Error('expected a non-empty string, got: ' + str)\n }\n}\n","export function assertNumber (number) {\n if (typeof number !== 'number') {\n throw new Error('expected a number, got: ' + number)\n }\n}\n","export const DB_VERSION_CURRENT = 1\nexport const DB_VERSION_INITIAL = 1\nexport const STORE_EMOJI = 'emoji'\nexport const STORE_KEYVALUE = 'keyvalue'\nexport const STORE_FAVORITES = 'favorites'\nexport const FIELD_TOKENS = 'tokens'\nexport const INDEX_TOKENS = 'tokens'\nexport const FIELD_UNICODE = 'unicode'\nexport const INDEX_COUNT = 'count'\nexport const FIELD_GROUP = 'group'\nexport const FIELD_ORDER = 'order'\nexport const INDEX_GROUP_AND_ORDER = 'group-order'\nexport const KEY_ETAG = 'eTag'\nexport const KEY_URL = 'url'\nexport const KEY_PREFERRED_SKINTONE = 'skinTone'\nexport const MODE_READONLY = 'readonly'\nexport const MODE_READWRITE = 'readwrite'\nexport const INDEX_SKIN_UNICODE = 'skinUnicodes'\nexport const FIELD_SKIN_UNICODE = 'skinUnicodes'\n\nexport const DEFAULT_DATA_SOURCE = 'https://cdn.jsdelivr.net/npm/emoji-picker-element-data@^1/en/emojibase/data.json'\nexport const DEFAULT_LOCALE = 'en'\n","// like lodash's uniqBy but much smaller\nexport function uniqBy (arr, func) {\n const set = new Set()\n const res = []\n for (const item of arr) {\n const key = func(item)\n if (!set.has(key)) {\n set.add(key)\n res.push(item)\n }\n }\n return res\n}\n","import { uniqBy } from '../../shared/uniqBy'\n\nexport function uniqEmoji (emojis) {\n return uniqBy(emojis, _ => _.unicode)\n}\n","import {\n FIELD_GROUP, FIELD_ORDER, FIELD_UNICODE,\n FIELD_TOKENS,\n INDEX_GROUP_AND_ORDER,\n STORE_EMOJI,\n STORE_KEYVALUE,\n STORE_FAVORITES,\n INDEX_TOKENS, INDEX_COUNT, INDEX_SKIN_UNICODE, FIELD_SKIN_UNICODE\n} from './constants'\n\nfunction initialMigration (db) {\n function createObjectStore (name, keyPath, indexes) {\n const store = keyPath\n ? db.createObjectStore(name, { keyPath })\n : db.createObjectStore(name)\n if (indexes) {\n for (const [indexName, [keyPath, multiEntry]] of Object.entries(indexes)) {\n store.createIndex(indexName, keyPath, { multiEntry })\n }\n }\n return store\n }\n\n createObjectStore(STORE_KEYVALUE)\n createObjectStore(STORE_EMOJI, /* keyPath */ FIELD_UNICODE, {\n [INDEX_TOKENS]: [FIELD_TOKENS, /* multiEntry */ true],\n [INDEX_GROUP_AND_ORDER]: [[FIELD_GROUP, FIELD_ORDER]],\n [INDEX_SKIN_UNICODE]: [FIELD_SKIN_UNICODE, /* multiEntry */ true]\n })\n createObjectStore(STORE_FAVORITES, undefined, {\n [INDEX_COUNT]: ['']\n })\n}\n\nexport { initialMigration }\n","import { initialMigration } from './migrations'\nimport { DB_VERSION_INITIAL, DB_VERSION_CURRENT } from './constants'\n\nexport const openIndexedDBRequests = {}\nconst databaseCache = {}\nconst onCloseListeners = {}\n\nfunction handleOpenOrDeleteReq (resolve, reject, req) {\n // These things are almost impossible to test with fakeIndexedDB sadly\n /* istanbul ignore next */\n req.onerror = () => reject(req.error)\n /* istanbul ignore next */\n req.onblocked = () => reject(new Error('IDB blocked'))\n req.onsuccess = () => resolve(req.result)\n}\n\nasync function createDatabase (dbName) {\n performance.mark('createDatabase')\n const db = await new Promise((resolve, reject) => {\n const req = indexedDB.open(dbName, DB_VERSION_CURRENT)\n openIndexedDBRequests[dbName] = req\n req.onupgradeneeded = e => {\n // Technically there is only one version, so we don't need this `if` check\n // But if an old version of the JS is in another browser tab\n // and it gets upgraded in the future and we have a new DB version, well...\n // better safe than sorry.\n /* istanbul ignore else */\n if (e.oldVersion < DB_VERSION_INITIAL) {\n initialMigration(req.result)\n }\n }\n handleOpeLine truncated
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'الفئات',
emojiUnsupportedMessage: 'متصفحك لا يدعم رموز المشاعر الملونة.',
favoritesLabel: 'المفضلة',
loadingMessage: 'جارٍ التحميل…',
networkErrorMessage: 'تعذر تحميل رمز مشاعر.',
regionLabel: 'منتقي رموز المشاعر',
searchDescription: 'عندما تكون نتائج البحث متاحة، اضغط السهم لأعلى أو لأسفل للتحديد واضغط enter للاختيار.',
searchLabel: 'بحث',
searchResultsLabel: 'نتائج البحث',
skinToneDescription: 'عند توسيع النتائج، اضغط السهم لأعلى أو لأسفل للتحديد واضغط enter للاختيار.',
skinToneLabel: 'اختر درجة لون البشرة (حاليًا {skinTone})',
skinTonesLabel: 'درجات لون البشرة',
skinTones: [
'افتراضي',
'فاتح',
'فاتح متوسط',
'متوسط',
'داكن متوسط',
'داكن'
],
categories: {
custom: 'مخصص',
'smileys-emotion': 'الوجوه الضاحكة ورموز المشاعر',
'people-body': 'الأشخاص والجسد',
'animals-nature': 'الحيوانات والطبيعة',
'food-drink': 'الطعام والشراب',
'travel-places': 'السفر والأماكن',
activities: 'الأنشطة',
objects: 'الأشياء',
symbols: 'الرموز',
flags: 'الأعلام'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Kategorien',
emojiUnsupportedMessage: 'Dein Browser unterstützt keine farbigen Emojis.',
favoritesLabel: 'Favoriten',
loadingMessage: 'Wird geladen…',
networkErrorMessage: 'Konnte Emoji nicht laden.',
regionLabel: 'Emoji auswählen',
searchDescription: 'Wenn Suchergebnisse verfügbar sind, wähle sie mit Pfeil rauf und runter, dann Eingabetaste, aus.',
searchLabel: 'Suchen',
searchResultsLabel: 'Suchergebnisse',
skinToneDescription: 'Wenn angezeigt, nutze Pfeiltasten rauf und runter zum Auswählen, Eingabe zum Akzeptieren.',
skinToneLabel: 'Wähle einen Hautton (aktuell {skinTone})',
skinTonesLabel: 'Hauttöne',
skinTones: [
'Standard',
'Hell',
'Mittel-hell',
'Mittel',
'Mittel-dunkel',
'Dunkel'
],
categories: {
custom: 'Benutzerdefiniert',
'smileys-emotion': 'Smileys und Emoticons',
'people-body': 'Menschen und Körper',
'animals-nature': 'Tiere und Natur',
'food-drink': 'Essen und Trinken',
'travel-places': 'Reisen und Orte',
activities: 'Aktivitäten',
objects: 'Objekte',
symbols: 'Symbole',
flags: 'Flaggen'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Categories',
emojiUnsupportedMessage: 'Your browser does not support color emoji.',
favoritesLabel: 'Favorites',
loadingMessage: 'Loading…',
networkErrorMessage: 'Could not load emoji.',
regionLabel: 'Emoji picker',
searchDescription: 'When search results are available, press up or down to select and enter to choose.',
searchLabel: 'Search',
searchResultsLabel: 'Search results',
skinToneDescription: 'When expanded, press up or down to select and enter to choose.',
skinToneLabel: 'Choose a skin tone (currently {skinTone})',
skinTonesLabel: 'Skin tones',
skinTones: [
'Default',
'Light',
'Medium-Light',
'Medium',
'Medium-Dark',
'Dark'
],
categories: {
custom: 'Custom',
'smileys-emotion': 'Smileys and emoticons',
'people-body': 'People and body',
'animals-nature': 'Animals and nature',
'food-drink': 'Food and drink',
'travel-places': 'Travel and places',
activities: 'Activities',
objects: 'Objects',
symbols: 'Symbols',
flags: 'Flags'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Categorías',
emojiUnsupportedMessage: 'El navegador no admite emojis de color.',
favoritesLabel: 'Favoritos',
loadingMessage: 'Cargando…',
networkErrorMessage: 'No se pudo cargar el emoji.',
regionLabel: 'Selector de emojis',
searchDescription: 'Cuando estén disponibles los resultados, pulsa la tecla hacia arriba o hacia abajo para seleccionar y la tecla intro para elegir.',
searchLabel: 'Buscar',
searchResultsLabel: 'Resultados de búsqueda',
skinToneDescription: 'Cuando se abran las opciones, pulsa la tecla hacia arriba o hacia abajo para seleccionar y la tecla intro para elegir.',
skinToneLabel: 'Elige un tono de piel ({skinTone} es el actual)',
skinTonesLabel: 'Tonos de piel',
skinTones: [
'Predeterminado',
'Claro',
'Claro medio',
'Medio',
'Oscuro medio',
'Oscuro'
],
categories: {
custom: 'Personalizado',
'smileys-emotion': 'Emojis y emoticones',
'people-body': 'Personas y partes del cuerpo',
'animals-nature': 'Animales y naturaleza',
'food-drink': 'Comida y bebida',
'travel-places': 'Viajes y lugares',
activities: 'Actividades',
objects: 'Objetos',
symbols: 'Símbolos',
flags: 'Banderas'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'دسته‌بندی‌ها',
emojiUnsupportedMessage: 'مرورگر شما از ایموجی‌های رنگی پشتیبانی نمی‌کند.',
favoritesLabel: 'محبوب‌ها',
loadingMessage: 'در حال بارگذاری…',
networkErrorMessage: 'بارگذاری ایموجی‌ها با مشکل مواجه شد.',
regionLabel: 'انتخاب‌کننده ایموجی',
searchDescription: 'در صورت موجود بودن نتایج جستجو، با کلیدهای بالا یا پایین برای انتخاب و اینتر برای تأیید استفاده کنید.',
searchLabel: 'جستجو',
searchResultsLabel: 'نتایج جستجو',
skinToneDescription: 'در حالت باز شده، با کلیدهای بالا یا پایین انتخاب کرده و با اینتر تأیید کنید.',
skinToneLabel: 'انتخاب رنگ پوست (در حال حاضر {skinTone})',
skinTonesLabel: 'رنگ‌های پوست',
skinTones: [
'پیش‌فرض',
'روشن',
'روشن متوسط',
'متوسط',
'تیره متوسط',
'تیره'
],
categories: {
custom: 'دلخواه',
'smileys-emotion': 'لبخندها و احساسات',
'people-body': 'افراد و بدن',
'animals-nature': 'حیوانات و طبیعت',
'food-drink': 'غذا و نوشیدنی',
'travel-places': 'سفر و مکان‌ها',
activities: 'فعالیت‌ها',
objects: 'اشیاء',
symbols: 'نمادها',
flags: 'پرچم‌ها'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Catégories',
emojiUnsupportedMessage: 'Votre navigateur ne supporte pas les emojis en couleur.',
favoritesLabel: 'Favoris',
loadingMessage: 'Chargement en cours…',
networkErrorMessage: 'Impossible de charger les emojis.',
regionLabel: 'Choisir un emoji',
searchDescription: 'Lorsque les résultats sont affichés, utilisez les flèches haut/bas pour naviguer et la touche entrée pour sélectionner.',
searchLabel: 'Rechercher',
searchResultsLabel: 'Résultats',
skinToneDescription: 'Quand disponible, utilisez les flèches haut/bas pour naviguer et la touche entrée pour sélectionner.',
skinToneLabel: 'Choisir une couleur de peau (actuellement {skinTone})',
skinTonesLabel: 'Couleurs de peau',
skinTones: [
'Par défaut',
'Clair',
'Moyennement clair',
'Moyen',
'Moyennement sombre',
'Sombre'
],
categories: {
custom: 'Personnalisé',
'smileys-emotion': 'Émoticônes',
'people-body': 'Corps et métiers',
'animals-nature': 'Animaux et nature',
'food-drink': 'Nourriture et boissons',
'travel-places': 'Voyages et lieux',
activities: 'Activités',
objects: 'Objets',
symbols: 'Symboles',
flags: 'Drapeaux'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'श्रेणियाँ',
emojiUnsupportedMessage: 'आपका ब्राउज़र कलर इमोजी का समर्थन नहीं करता।',
favoritesLabel: 'पसंदीदा',
loadingMessage: 'लोड हो रहा है...',
networkErrorMessage: 'इमोजी लोड नहीं हो सके।',
regionLabel: 'इमोजी चुननेवाला',
searchDescription: 'जब खोज परिणाम उपलब्ध हों तो चयन करने के लिए ऊपर या नीचे दबाएं और चुनने के लिए एंटर दबाएं।',
searchLabel: 'खोज',
searchResultsLabel: 'खोज के परिणाम',
skinToneDescription: 'जब विस्तृत किया जाता है तो चयन करने के लिए ऊपर या नीचे दबाएं और चुनने के लिए एंटर दबाएं।',
skinToneLabel: 'त्वचा का रंग चुनें (वर्तमान में {skinTone})',
skinTonesLabel: 'त्वचा के रंग',
skinTones: [
'डिफॉल्ट',
'हल्का',
'मध्यम हल्का',
'मध्यम',
'मध्यम गहरा',
'गहरा'
],
categories: {
custom: 'कस्टम',
'smileys-emotion': 'स्माइली और इमोटिकॉन्स',
'people-body': 'लोग और शरीर',
'animals-nature': 'पशु और प्रकृति',
'food-drink': 'खाद्य और पेय',
'travel-places': 'यात्रा और स्थान',
activities: 'गतिविधियां',
objects: 'वस्तुएं',
symbols: 'प्रतीक',
flags: 'झंडे'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Kategori',
emojiUnsupportedMessage: 'Browser Anda tidak mendukung emoji warna.',
favoritesLabel: 'Favorit',
loadingMessage: 'Memuat...',
networkErrorMessage: 'Tidak dapat memuat emoji.',
regionLabel: 'Pemilih emoji',
searchDescription: 'Ketika hasil pencarian tersedia, tekan atas atau bawah untuk menyeleksi dan enter untuk memilih.',
searchLabel: 'Cari',
searchResultsLabel: 'Hasil Pencarian',
skinToneDescription: 'Saat diperluas tekan atas atau bawah untuk menyeleksi dan enter untuk memilih.',
skinToneLabel: 'Pilih warna skin (saat ini {skinTone})',
skinTonesLabel: 'Warna skin',
skinTones: [
'Default',
'Light',
'Medium light',
'Medium',
'Medium dark',
'Dark'
],
categories: {
custom: 'Kustom',
'smileys-emotion': 'Smiley dan emoticon',
'people-body': 'Orang dan bagian tubuh',
'animals-nature': 'Hewan dan tumbuhan',
'food-drink': 'Makanan dan minuman',
'travel-places': 'Rekreasi dan tempat',
activities: 'Aktivitas',
objects: 'Objek',
symbols: 'Simbol',
flags: 'Bendera'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Categorie',
emojiUnsupportedMessage: 'Il tuo browser non supporta le emoji colorate.',
favoritesLabel: 'Preferiti',
loadingMessage: 'Caricamento...',
networkErrorMessage: 'Impossibile caricare le emoji.',
regionLabel: 'Selezione emoji',
searchDescription: 'Quando i risultati della ricerca sono disponibili, premi su o giù per selezionare e invio per scegliere.',
searchLabel: 'Cerca',
searchResultsLabel: 'Risultati di ricerca',
skinToneDescription: 'Quando espanso, premi su o giù per selezionare e invio per scegliere.',
skinToneLabel: 'Scegli una tonalità della pelle (corrente {skinTone})',
skinTonesLabel: 'Tonalità della pelle',
skinTones: [
'Predefinita',
'Chiara',
'Medio-Chiara',
'Media',
'Medio-Scura',
'Scura'
],
categories: {
custom: 'Personalizzata',
'smileys-emotion': 'Faccine ed emozioni',
'people-body': 'Persone e corpi',
'animals-nature': 'Animali e natura',
'food-drink': 'Cibi e bevande',
'travel-places': 'Viaggi e luoghi',
activities: 'Attività',
objects: 'Oggetti',
symbols: 'Simboli',
flags: 'Bandiere'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'カテゴリー',
emojiUnsupportedMessage: 'このブラウザではカラー絵文字を表示できません。',
favoritesLabel: 'お気に入り',
loadingMessage: '読込中…',
networkErrorMessage: '絵文字を読み込めませんでした。',
regionLabel: '絵文字を追加',
searchDescription: '検索結果を矢印キーで選択し、エンターキーで決定できます。',
searchLabel: '検索',
searchResultsLabel: '検索結果',
skinToneDescription: 'メニューを開いて矢印キーで選択し、エンターキーで決定できます。',
skinToneLabel: '肌の色を選択 (選択中の色: {skinTone})',
skinTonesLabel: '肌の色',
skinTones: [
'デフォルト',
'明るい',
'やや明るい',
'中間',
'やや暗い',
'暗い'
],
categories: {
custom: 'カスタム',
'smileys-emotion': '顔文字',
'people-body': '人・身体',
'animals-nature': '動物・自然',
'food-drink': '食べ物・飲み物',
'travel-places': '旅行・場所',
activities: 'アクティビティ',
objects: 'オブジェクト',
symbols: '記号',
flags: '旗'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Kategori',
emojiUnsupportedMessage: 'Penyemak imbas anda tidak menyokong emoji warna.',
favoritesLabel: 'Kegemaran',
loadingMessage: 'Memuat…',
networkErrorMessage: 'Tidak dapat memuatkan emoji.',
regionLabel: 'Pemilih emoji',
searchDescription: 'Apabila hasil carian tersedia, tekan atas atau bawah untuk memilih dan tekan masukkan untuk memilih.',
searchLabel: 'Cari',
searchResultsLabel: 'Hasil carian',
skinToneDescription: 'Apabila dikembangkan, tekan atas atau bawah untuk memilih dan tekan masukkan untuk memilih.',
skinToneLabel: 'Pilih warna kulit (pada masa ini {skinTone})',
skinTonesLabel: 'Warna kulit',
skinTones: [
'Lalai',
'Cerah',
'Kuning langsat',
'Sederhana cerah',
'Sawo matang',
'Gelap'
],
categories: {
custom: 'Tersuai',
'smileys-emotion': 'Smiley dan emotikon',
'people-body': 'Orang dan badan',
'animals-nature': 'Haiwan dan alam semula jadi',
'food-drink': 'Makanan dan minuman',
'travel-places': 'Perjalanan dan tempat',
activities: 'Aktiviti',
objects: 'Objek',
symbols: 'Simbol',
flags: 'Bendera'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Categorieën',
emojiUnsupportedMessage: 'Uw browser ondersteunt geen kleurenemoji.',
favoritesLabel: 'Favorieten',
loadingMessage: 'Bezig met laden…',
networkErrorMessage: 'Kan emoji niet laden.',
regionLabel: 'Emoji-kiezer',
searchDescription: 'Als er zoekresultaten beschikbaar zijn, drukt u op omhoog of omlaag om te selecteren en op enter om te kiezen.',
searchLabel: 'Zoeken',
searchResultsLabel: 'Zoekresultaten',
skinToneDescription: 'Wanneer uitgevouwen, druk omhoog of omlaag om te selecteren en enter om te kiezen.',
skinToneLabel: 'Kies een huidskleur (momenteel {skinTone})',
skinTonesLabel: 'Huidskleuren',
skinTones: [
'Standaard',
'Licht',
'Medium-Licht',
'Medium',
'Middeldonker',
'Donker'
],
categories: {
custom: 'Aangepast',
'smileys-emotion': 'Smileys en emoticons',
'people-body': 'Mensen en lichaam',
'animals-nature': 'Dieren en natuur',
'food-drink': 'Eten en drinken',
'travel-places': 'Reizen en plaatsen',
activities: 'Activiteiten',
objects: 'Voorwerpen',
symbols: 'Symbolen',
flags: 'Vlaggen'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Kategorie',
emojiUnsupportedMessage: 'Twoja przeglądarka nie wspiera kolorowych emotikon.',
favoritesLabel: 'Ulubione',
loadingMessage: 'Ładuję…',
networkErrorMessage: 'Nie można załadować emoji.',
regionLabel: 'Selektor emoji',
searchDescription: 'Kiedy wyniki wyszukiwania będą dostępne, wciśnij góra lub dół aby wybrać oraz enter aby zatwierdzić wybór.',
searchLabel: 'Wyszukaj',
searchResultsLabel: 'Wyniki wyszukiwania',
skinToneDescription: 'Po rozwinięciu wciśnij góra lub dół aby wybrać oraz enter aby zatwierdzić wybór.',
skinToneLabel: 'Wybierz odcień skóry (aktualnie {skinTone})',
skinTonesLabel: 'Odcienie skóry',
skinTones: [
'Domyślna',
'Jasna',
'Średnio-jasna',
'Średnia',
'Średnio-ciemna',
'Ciemna'
],
categories: {
custom: 'Własne',
'smileys-emotion': 'Uśmiechy',
'people-body': 'Ludzie',
'animals-nature': 'Zwierzęta i natura',
'food-drink': 'Żywność i napoje',
'travel-places': 'Podróże i miejsca',
activities: 'Aktywności',
objects: 'Obiekty',
symbols: 'Symbole',
flags: 'Flagi'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Categorias',
emojiUnsupportedMessage: 'Seu navegador não suporta emojis coloridos.',
favoritesLabel: 'Favoritos',
loadingMessage: 'Carregando…',
networkErrorMessage: 'Não foi possível carregar o emoji.',
regionLabel: 'Seletor de emoji',
searchDescription: 'Quando os resultados da pesquisa estiverem disponíveis, pressione para cima ou para baixo para selecionar e “enter” para escolher.',
searchLabel: 'Procurar',
searchResultsLabel: 'Resultados da pesquisa',
skinToneDescription: 'Quando expandido, pressione para cima ou para baixo para selecionar e “enter” para escolher.',
skinToneLabel: 'Escolha um tom de pele (atualmente {skinTone})',
skinTonesLabel: 'Tons de pele',
skinTones: [
'Padrão',
'Claro',
'Claro médio',
'Médio',
'Escuro médio',
'Escuro'
],
categories: {
custom: 'Personalizar',
'smileys-emotion': 'Carinhas e emoticons',
'people-body': 'Pessoas e corpo',
'animals-nature': 'Animais e natureza',
'food-drink': 'Alimentos e bebidas',
'travel-places': 'Viagem e lugares',
activities: 'Atividades',
objects: 'Objetos',
symbols: 'Símbolos',
flags: 'Bandeiras'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Categorias',
emojiUnsupportedMessage: 'O seu browser não suporta emojis.',
favoritesLabel: 'Favoritos',
loadingMessage: 'A Carregar…',
networkErrorMessage: 'Não foi possível carregar o emoji.',
regionLabel: 'Emoji picker',
searchDescription: 'Quando os resultados da pesquisa estiverem disponíveis, pressione para cima ou para baixo para selecionar e digite para escolher.',
searchLabel: 'Procurar',
searchResultsLabel: 'Resultados da procura',
skinToneDescription: 'Quando expandido, pressione para cima ou para baixo para selecionar e digite para escolher.',
skinToneLabel: 'Escolha um tom de pele (atual {skinTone})',
skinTonesLabel: 'Tons de pele',
skinTones: [
'Pré-definido',
'Claro',
'Médio-Claro',
'Médio',
'Médio-Escuro',
'Escuro'
],
categories: {
custom: 'Personalizados',
'smileys-emotion': 'Smileys e emoticons',
'people-body': 'Pessoas e corpo',
'animals-nature': 'Animais e natureza',
'food-drink': 'Comida e bebida',
'travel-places': 'Viagens e locais',
activities: 'Atividades',
objects: 'Objetos',
symbols: 'Símbolos',
flags: 'Bandeiras'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Категории',
emojiUnsupportedMessage: 'Ваш браузер не поддерживает цветные эмодзи.',
favoritesLabel: 'Избранное',
loadingMessage: 'Загрузка…',
networkErrorMessage: 'Не удалось загрузить эмодзи. Попробуйте перезагрузить страницу.',
regionLabel: 'Выберите эмодзи',
searchDescription: 'Когда результаты поиска станут доступны, выберите их с помощью стрелок вверх и вниз, затем нажмите для подтверждения.',
searchLabel: 'Искать',
searchResultsLabel: 'Результаты поиска',
skinToneDescription: 'При отображении используйте клавиши со стрелками вверх и вниз для выбора, нажмите для подтверждения.',
skinToneLabel: 'Выберите оттенок кожи (текущий {skinTone})',
skinTonesLabel: 'Оттенки кожи',
skinTones: [
'Стандартный',
'Светлый',
'Средне-светлый',
'Средний',
'Средне-темный',
'Темный'
],
categories: {
custom: 'Пользовательский',
'smileys-emotion': 'Смайлики и Эмотиконы',
'people-body': 'Люди и Тела',
'animals-nature': 'Животные и Природа',
'food-drink': 'Еда и Напитки',
'travel-places': 'Путешествия и Места',
activities: 'Виды деятельности',
objects: 'Объекты',
symbols: 'Символы',
flags: 'Флаги'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Kategoriler',
emojiUnsupportedMessage: 'Tarayıcınız renkli emojiyi desteklemiyor.',
favoritesLabel: 'Favoriler',
loadingMessage: 'Yükleniyor…',
networkErrorMessage: 'Emoji yüklenemedi.',
regionLabel: 'Emoji seçici',
searchDescription: 'Arama sonuçları mevcut olduğunda seçmek için yukarı veya aşağı basın ve seçmek için girin.',
searchLabel: 'Arama',
searchResultsLabel: 'Arama sonuçları',
skinToneDescription: 'Genişletildiğinde seçmek için yukarı veya aşağı basın ve seçmek için girin.',
skinToneLabel: 'Cilt tonu seçin (şu anda {skinTone})',
skinTonesLabel: 'Cilt tonları',
skinTones: [
'Varsayılan',
'Işık',
'Orta ışık',
'Orta',
'Orta koyu',
'Karanlık'
],
categories: {
custom: 'Gelenek',
'smileys-emotion': 'Suratlar ve ifadeler',
'people-body': 'İnsanlar ve vücut',
'animals-nature': 'Hayvanlar ve doğa',
'food-drink': 'Yiyecek ve içecek',
'travel-places': 'Seyahat ve yerler',
activities: 'Aktiviteler',
objects: 'Nesneler',
symbols: 'Semboller',
flags: 'Bayraklar'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+34
View File
@@ -0,0 +1,34 @@
export default {
categoriesLabel: 'Danh mục',
emojiUnsupportedMessage: 'Trình duyệt của bạn không hỗ trợ emoji màu.',
favoritesLabel: 'Yêu thích',
loadingMessage: 'Đang tải…',
networkErrorMessage: 'Không thể tải emoji.',
regionLabel: 'Chọn emoji',
searchDescription: 'Khi có kết quả tìm kiếm, nhấn lên hoặc xuống để chọn và nhấn Enter để chọn.',
searchLabel: 'Tìm kiếm',
searchResultsLabel: 'Kết quả tìm kiếm',
skinToneDescription: 'Khi mở rộng, nhấn lên hoặc xuống để chọn và nhấn Enter để chọn.',
skinToneLabel: 'Chọn tông màu da (hiện tại {skinTone})',
skinTonesLabel: 'Tông màu da',
skinTones: [
'Mặc định',
'Sáng',
'Sáng vừa',
'Trung bình',
'Tối vừa',
'Tối'
],
categories: {
custom: 'Tùy chỉnh',
'smileys-emotion': 'Mặt cười và cảm xúc',
'people-body': 'Người và cơ thể',
'animals-nature': 'Động vật và thiên nhiên',
'food-drink': 'Thức ăn và đồ uống',
'travel-places': 'Du lịch và địa điểm',
activities: 'Hoạt động',
objects: 'Đồ vật',
symbols: 'Biểu tượng',
flags: 'Cờ'
}
}
+3
View File
@@ -0,0 +1,3 @@
import { I18n } from "../shared";
declare const _default: I18n;
export default _default;
+27
View File
@@ -0,0 +1,27 @@
export default {
categoriesLabel: '类别',
emojiUnsupportedMessage: '您的浏览器不支持彩色表情符号。',
favoritesLabel: '收藏夹',
loadingMessage: '正在加载…',
networkErrorMessage: '无法加载表情符号。',
regionLabel: '表情符号选择器',
searchDescription: '当搜索结果可用时,按向上或向下选择并输入选择。',
searchLabel: '搜索',
searchResultsLabel: '搜索结果',
skinToneDescription: '展开时,按向上或向下键进行选择,按回车键进行选择。',
skinToneLabel: '选择肤色(当前为 {skinTone})',
skinTonesLabel: '肤色',
skinTones: ['默认', '明亮', '微亮', '中等', '微暗', '暗'],
categories: {
custom: '自定义',
'smileys-emotion': '笑脸和表情',
'people-body': '人物和身体',
'animals-nature': '动物与自然',
'food-drink': '食品饮料',
'travel-places': '旅行和地方',
activities: '活动',
objects: '物体',
symbols: '符号',
flags: '旗帜'
}
}
+7
View File
@@ -0,0 +1,7 @@
import Picker from './picker.js'
import Database from './database.js'
export {
Picker,
Database
}
+3
View File
@@ -0,0 +1,3 @@
import Picker from './picker.js?v=local'
import Database from './database.js?v=local'
export { Picker, Database }
+191
View File
@@ -0,0 +1,191 @@
{
"name": "emoji-picker-element",
"version": "1.28.1",
"description": "Lightweight emoji picker distributed as a web component",
"main": "index.js",
"module": "index.js",
"types": "index.d.ts",
"type": "module",
"customElements": "custom-elements.json",
"files": [
"/database.js*",
"/index.js*",
"/picker.js*",
"/trimEmojiData.*",
"/svelte.js*",
"/*.d.ts",
"/custom-elements.json",
"/i18n/*"
],
"scripts": {
"prepare": "run-s build && husky",
"build": "run-s build:rollup build:i18n build:css-docs build:i18n-docs build:toc",
"build:rollup": "cross-env NODE_ENV=production rollup -c",
"build:css-docs": "node ./bin/generateCssDocs",
"build:i18n-docs": "node ./bin/generateI18nDocs",
"build:toc": "node ./bin/generateTOC",
"build:i18n": "node ./bin/buildI18n",
"benchmark:runtime": "run-s build:rollup benchmark:runtime:setup benchmark:runtime:test",
"benchmark:runtime:setup": "node ./bin/setupTachometerConfigs.js",
"benchmark:runtime:test": "for config in ./test/benchmark/*.tachometer.json; do echo \"${config}\"; tach --config \"${config}\"; done",
"benchmark:bundlesize": "run-s build:rollup benchmark:bundle benchmark:run-bundlesize",
"benchmark:bundle": "rollup -c ./test/bundlesize/rollup.config.js",
"benchmark:memory": "run-s build:rollup benchmark:bundle && run-p --race benchmark:memory:server benchmark:memory:test",
"benchmark:memory:server": "node ./test/memory/server.js",
"benchmark:memory:test": "node ./test/memory/test.js",
"benchmark:run-bundlesize": "node ./bin/bundlesize.js",
"benchmark:storage": "cross-env PERF=1 run-s build:rollup && run-p --race test:adhoc benchmark:storage:test",
"benchmark:storage:test": "node ./test/storage/test.js",
"test:leak": "run-p --race test:leak:server test:leak:test",
"test:leak:server": "node ./test/leak/server.js",
"test:leak:test": "node ./test/leak/test.js",
"dev": "run-p --race dev:rollup dev:server",
"dev:rollup": "cross-env NODE_ENV=development rollup -c -w",
"dev:server": "node ./test/adhoc/server.js",
"lint": "standard && stylelint '**/*.scss'",
"lint:fix": "standard --fix && stylelint --fix '**/*.scss'",
"test": "vitest",
"test:adhoc": "node ./test/adhoc/server.js",
"cover": "vitest --coverage",
"docs": "node bin/processCustomEmoji.js",
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
"version": "run-s changelog docs && git add CHANGELOG.md docs"
},
"repository": {
"type": "git",
"url": "git+https://github.com/nolanlawson/emoji-picker-element.git"
},
"keywords": [
"emoji",
"picker",
"IndexedDB",
"custom",
"element",
"web",
"component"
],
"author": "Nolan Lawson <nolan@nolanlawson.com>",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/nolanlawson/emoji-picker-element/issues"
},
"homepage": "https://github.com/nolanlawson/emoji-picker-element#readme",
"//": {
"@nolanlawson/emoji-picker-element-for-tachometer": [
"Placeholder package for Tachometer to swap correctly, see https://github.com/nolanlawson/emoji-picker-element/pull/439/",
"Note the @nolanlawson scope to avoid any accidental dependency confusion vulnerability"
]
},
"devDependencies": {
"@nolanlawson/emoji-picker-element-for-tachometer": "file:.",
"@rollup/plugin-commonjs": "^28.0.6",
"@rollup/plugin-inject": "^5.0.5",
"@rollup/plugin-node-resolve": "^16.0.1",
"@rollup/plugin-replace": "^6.0.2",
"@rollup/plugin-strip": "^3.0.4",
"@rollup/plugin-terser": "^0.4.4",
"@testing-library/dom": "^10.4.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/user-event": "^14.6.1",
"@vitest/coverage-istanbul": "^3.2.4",
"@vitest/ui": "^3.2.4",
"blob-util": "^2.0.2",
"compression": "^1.8.0",
"conventional-changelog-cli": "^5.0.0",
"cross-env": "^7.0.3",
"csso": "^5.0.5",
"emoji-picker-element-data": "^1.8.0",
"emojibase-data": "^5.1.1",
"express": "^5.1.0",
"fake-indexeddb": "^6.2.2",
"fast-glob": "^3.3.3",
"fetch-mock": "^11.1.5",
"flat-color-icons": "^1.1.0",
"get-folder-size": "^5.0.0",
"husky": "^9.1.7",
"jsdom": "^26.1.0",
"lint-staged": "^16.1.2",
"lodash-es": "^4.17.21",
"markdown-table": "^3.0.4",
"markdown-toc": "^1.2.0",
"minify-html-literals": "^1.3.5",
"npm-run-all": "^4.1.5",
"playwright": "^1.54.1",
"postcss": "^8.5.6",
"pretty-bytes": "^7.0.0",
"puppeteer": "^24.12.1",
"recursive-readdir": "^2.2.3",
"rollup": "^4.45.0",
"rollup-plugin-analyzer": "^4.0.0",
"sass": "^1.89.2",
"standard": "^17.1.2",
"stylelint": "^16.21.1",
"stylelint-config-recommended-scss": "^15.0.1",
"stylelint-scss": "^6.12.1",
"svgo": "^4.0.0",
"tachometer": "^0.7.2",
"terser": "^5.43.1",
"vitest": "^3.2.4"
},
"standard": {
"ignore": [
"/database.js",
"/index.js",
"/picker.js",
"/trimEmojiData.js",
"/trimEmojiData.cjs",
"/svelte.js",
"/docs"
],
"global": [
"btoa",
"crypto",
"customElements",
"CSS",
"CustomEvent",
"Event",
"fetch",
"getComputedStyle",
"Element",
"indexedDB",
"IDBKeyRange",
"IntersectionObserver",
"Headers",
"HTMLElement",
"matchMedia",
"Node",
"NodeFilter",
"performance",
"ResizeObserver",
"Response",
"requestAnimationFrame",
"requestIdleCallback",
"test",
"expect",
"beforeAll",
"afterAll",
"beforeEach",
"afterEach",
"describe"
]
},
"stylelint": {
"extends": "stylelint-config-recommended-scss",
"rules": {
"selector-type-no-unknown": [
true,
{
"ignoreTypes": [
"emoji-picker"
]
}
],
"no-descending-specificity": null
}
},
"lint-staged": {
"*.js": "standard --fix",
"*.(css|scss)": "stylelint --fix '**/*.scss'"
},
"packageManager": "pnpm@10.22.0+sha512.bf049efe995b28f527fd2b41ae0474ce29186f7edcb3bf545087bd61fbbebb2bf75362d1307fda09c2d288e1e499787ac12d4fcb617a974718a6051f2eee741c"
}
+30
View File
@@ -0,0 +1,30 @@
import { I18n, PickerConstructorOptions, EmojiPickerEventMap, CustomEmoji } from "./shared.js";
export default class Picker extends HTMLElement {
dataSource: string;
locale: string;
i18n: I18n;
skinToneEmoji: string;
customEmoji?: CustomEmoji[];
customCategorySorting?: (a: string, b: string) => number;
/**
*
* @param dataSource - URL to fetch the emoji data from (`data-source` when used as an attribute).
* @param locale - Locale string.
* @param i18n - i18n object (see below for details).
* @param skinToneEmoji - The emoji to use for the skin tone picker (`skin-tone-emoji` when used as an attribute).
* @param customEmoji - Array of custom emoji.
* @param customCategorySorting - Function to sort custom category strings (sorted alphabetically by default).
* @param emojiVersion - Maximum supported emoji version as a number (e.g. `14.0` or `13.1`). Setting this disables the default emoji support detection.
*/
constructor({ dataSource, locale, i18n, skinToneEmoji, customEmoji, customCategorySorting, emojiVersion }?: PickerConstructorOptions);
addEventListener<K extends keyof EmojiPickerEventMap>(type: K, listener: (this: Picker, ev: EmojiPickerEventMap[K]) => any, options?: boolean | AddEventListenerOptions): void;
addEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | AddEventListenerOptions): void;
removeEventListener<K extends keyof EmojiPickerEventMap>(type: K, listener: (this: Picker, ev: EmojiPickerEventMap[K]) => any, options?: boolean | EventListenerOptions): void;
removeEventListener(type: string, listener: EventListenerOrEventListenerObject, options?: boolean | EventListenerOptions): void;
}
declare global {
interface HTMLElementTagNameMap {
"emoji-picker": Picker;
}
}
File diff suppressed because it is too large. Load diff
+1
View File
@@ -0,0 +1 @@
{"version":3,"file":"picker.js","sources":["src/picker/groups.js","src/shared/constants.js","src/picker/utils/requestIdleCallback.js","src/picker/utils/hasZwj.js","bin/versionsAndTestEmoji.js","src/picker/constants.js","src/picker/utils/testColorEmojiSupported.js","src/picker/utils/determineEmojiSupportLevel.js","src/picker/utils/emojiSupport.js","src/picker/utils/applySkinTone.js","src/picker/utils/halt.js","src/picker/utils/incrementOrDecrement.js","src/shared/uniqBy.js","src/picker/utils/summarizeEmojisForUI.js","src/picker/utils/requestAnimationFrame.js","src/picker/utils/resizeObserverAction.js","src/picker/utils/calculateTextWidth.js","src/picker/utils/checkZwjSupport.js","src/picker/utils/requestPostAnimationFrame.js","src/shared/uniq.js","src/picker/utils/resetScrollTopIfPossible.js","src/picker/components/Picker/utils.js","src/picker/components/Picker/framework.js","src/picker/components/Picker/PickerTemplate.js","src/picker/utils/queueMicrotask.js","src/picker/components/Picker/reactivity.js","src/picker/utils/arraysAreEqualByFunction.js","src/picker/utils/intersectionObserverAction.js","src/picker/components/Picker/Picker.js","src/database/constants.js","src/picker/i18n/en.js","src/picker/styles/picker.scss","src/picker/PickerElement.js"],"sourcesContent":["// via https://unpkg.com/browse/emojibase-data@6.0.0/meta/groups.json\nexport const allGroups = [\n [-1, '✨', 'custom'],\n [0, '😀', 'smileys-emotion'],\n [1, '👋', 'people-body'],\n [3, '🐱', 'animals-nature'],\n [4, '🍎', 'food-drink'],\n [5, '🏠️', 'travel-places'],\n [6, '⚽', 'activities'],\n [7, '📝', 'objects'],\n [8, '⛔️', 'symbols'],\n [9, '🏁', 'flags']\n].map(([id, emoji, name]) => ({ id, emoji, name }))\n\nexport const groups = allGroups.slice(1)\n","export const MIN_SEARCH_TEXT_LENGTH = 2\nexport const NUM_SKIN_TONES = 6\n","/* istanbul ignore next */\nconst rIC = typeof requestIdleCallback === 'function' ? requestIdleCallback : setTimeout\n\nexport { rIC as requestIdleCallback }\n","// check for ZWJ (zero width joiner) character\nexport function hasZwj (emoji) {\n return emoji.unicode.includes('\\u200d')\n}\n","// Find one good representative emoji from each version to test by checking its color.\n// Ideally it should have color in the center. For some inspiration, see:\n// https://about.gitlab.com/blog/2018/05/30/journey-in-native-unicode-emoji/\n//\n// Note that for certain versions (12.1, 13.1), there is no point in testing them explicitly, because\n// all the emoji from this version are compound-emoji from previous versions. So they would pass a color\n// test, even in browsers that display them as double emoji. (E.g. \"face in clouds\" might render as\n// \"face without mouth\" plus \"fog\".) These emoji can only be filtered using the width test,\n// which happens in checkZwjSupport.js.\nexport const versionsAndTestEmoji = {\n '🫪': 17, // distorted face\n '🫩': 16, // face with bags under eyes\n '🫨': 15.1, // shaking head, technically from v15 but see note above\n '🫠': 14,\n '🥲': 13.1, // smiling face with tear, technically from v13 but see note above\n '🥻': 12.1, // sari, technically from v12 but see note above\n '🥰': 11,\n '🤩': 5,\n '👱‍♀️': 4,\n '🤣': 3,\n '👁️‍🗨️': 2,\n '😀': 1,\n '😐️': 0.7,\n '😃': 0.6\n}\n","export const TIMEOUT_BEFORE_LOADING_MESSAGE = 1000 // 1 second\nexport const DEFAULT_SKIN_TONE_EMOJI = '🖐️'\nexport const DEFAULT_NUM_COLUMNS = 8\n\n// Based on https://fivethirtyeight.com/features/the-100-most-used-emojis/ and\n// https://blog.emojipedia.org/facebook-reveals-most-and-least-used-emojis/ with\n// a bit of my own curation. (E.g. avoid the \"OK\" gesture because of connotations:\n// https://emojipedia.org/ok-hand/)\nexport const MOST_COMMONLY_USED_EMOJI = [\n '😊',\n '😒',\n '❤️',\n '👍️',\n '😍',\n '😂',\n '😭',\n '☺️',\n '😔',\n '😩',\n '😏',\n '💕',\n '🙌',\n '😘'\n]\n\n// It's important to list Twemoji Mozilla before everything else, because Mozilla bundles their\n// own font on some platforms (notably Windows and Linux as of this writing). Typically, Mozilla\n// updates faster than the underlying OS, and we don't want to render older emoji in one font and\n// newer emoji in another font:\n// https://github.com/nolanlawson/emoji-picker-element/pull/268#issuecomment-1073347283\nexport const FONT_FAMILY = '\"Twemoji Mozilla\",\"Apple Color Emoji\",\"Segoe UI Emoji\",\"Segoe UI Symbol\",' +\n '\"Noto Color Emoji\",\"EmojiOne Color\",\"Android Emoji\",sans-serif'\n\n/* istanbul ignore next */\nexport const DEFAULT_CATEGORY_SORTING = (a, b) => a < b ? -1 : a > b ? 1 : 0\n","// Test if an emoji is supported by rendering it to canvas and checking that the color is not black\n// See https://about.gitlab.com/blog/2018/05/30/journey-in-native-unicode-emoji/\n// and https://www.npmjs.com/package/if-emoji for inspiration\n// This implementation is largely Line truncated
+99
View File
@@ -0,0 +1,99 @@
export declare enum SkinTone {
Default = 0,
Light = 1,
MediumLight = 2,
Medium = 3,
MediumDark = 4,
Dark = 5
}
export interface NativeEmoji {
annotation: string;
emoticon?: string;
group: number;
name: string;
order: number;
shortcodes?: string[];
tags?: string[];
version: number;
unicode: string;
skins?: EmojiSkin[];
}
export interface EmojiSkin {
tone: SkinTone;
unicode: string;
version: number;
}
export interface DatabaseConstructorOptions {
dataSource?: string;
locale?: string;
customEmoji?: CustomEmoji[];
}
export interface PickerConstructorOptions {
dataSource?: string;
locale?: string;
i18n?: I18n;
skinToneEmoji?: string;
customEmoji?: CustomEmoji[];
customCategorySorting?: (a: string, b: string) => number;
emojiVersion?: number;
}
export interface I18n {
emojiUnsupportedMessage: string;
loadingMessage: string;
networkErrorMessage: string;
regionLabel: string;
searchLabel: string;
skinToneLabel: string;
searchResultsLabel: string;
categoriesLabel: string;
categories: I18nCategories;
skinTonesLabel: string;
skinTones: string[];
searchDescription: string;
skinToneDescription: string;
favoritesLabel: string;
}
export interface I18nCategories {
custom: string;
'smileys-emotion': string;
'people-body': string;
'animals-nature': string;
'food-drink': string;
'travel-places': string;
activities: string;
objects: string;
symbols: string;
flags: string;
}
export interface EmojiClickEventDetail {
emoji: Emoji;
skinTone: SkinTone;
unicode?: string;
name?: string;
}
export interface SkinToneChangeEventDetail {
skinTone: SkinTone;
}
declare type Modify<T, R> = Omit<T, keyof R> & R;
export declare type EmojiClickEvent = Modify<UIEvent, {
detail: EmojiClickEventDetail;
}>;
export declare type EmojiClickSyncEvent = Modify<UIEvent, {
detail: Promise<EmojiClickEventDetail>;
}>;
export declare type SkinToneChangeEvent = Modify<UIEvent, {
detail: SkinToneChangeEventDetail;
}>;
export interface EmojiPickerEventMap {
"emoji-click": EmojiClickEvent;
"emoji-click-sync": EmojiClickSyncEvent;
"skin-tone-change": SkinToneChangeEvent;
}
export interface CustomEmoji {
name: string;
shortcodes?: string[];
url: string;
category?: string;
}
export declare type Emoji = NativeEmoji | CustomEmoji;
export {};
+4
View File
@@ -0,0 +1,4 @@
console.warn('Importing emoji-picker-element from "emoji-picker-element/svelte" is deprecated. ' +
'Instead, import from "emoji-picker-element" or "emoji-picker-element/picker".')
import picker from './picker.js'
export default picker
+54
View File
@@ -0,0 +1,54 @@
'use strict';
const requiredKeys = [
'annotation',
'emoji',
'group',
'order',
'version'
];
function assertEmojiData (emojiData) {
if (!emojiData ||
!Array.isArray(emojiData) ||
!emojiData[0] ||
(typeof emojiData[0] !== 'object') ||
requiredKeys.some(key => (!(key in emojiData[0])))) {
throw new Error('Emoji data is in the wrong format')
}
}
const optionalKeys = ['skins', 'emoticon', 'shortcodes', 'tags'];
const allKeys = [...requiredKeys, ...optionalKeys];
const allSkinsKeys = ['tone', 'emoji', 'version'];
function trimEmojiData (emojiData) {
console.warn('trimEmojiData() is deprecated and may be removed eventually. ' +
'If you use emoji-picker-element-data instead of emojibase-data, there is no need for trimEmojiData(). ' +
'For details, see: ' +
'https://github.com/nolanlawson/emoji-picker-element/blob/master/README.md#trimming-the-emoji-data-deprecated'
);
assertEmojiData(emojiData);
return emojiData.map(emoji => {
const res = {};
for (const key of allKeys) {
if (key in emoji) {
if (key === 'skins') { // trim skins even further
res[key] = emoji[key].map(skin => {
const skinRes = {};
for (const skinKey of allSkinsKeys) {
skinRes[skinKey] = skin[skinKey];
}
return skinRes
});
} else {
res[key] = emoji[key];
}
}
}
return res
})
}
module.exports = trimEmojiData;
@@ -0,0 +1 @@
{"version":3,"file":"trimEmojiData.cjs","sources":["src/database/utils/requiredKeys.js","src/database/utils/assertEmojiData.js","src/trimEmojiData.js"],"sourcesContent":["export const requiredKeys = [\n 'annotation',\n 'emoji',\n 'group',\n 'order',\n 'version'\n]\n","import { requiredKeys } from './requiredKeys'\n\nexport function assertEmojiData (emojiData) {\n if (!emojiData ||\n !Array.isArray(emojiData) ||\n !emojiData[0] ||\n (typeof emojiData[0] !== 'object') ||\n requiredKeys.some(key => (!(key in emojiData[0])))) {\n throw new Error('Emoji data is in the wrong format')\n }\n}\n","import { assertEmojiData } from './database/utils/assertEmojiData'\nimport { requiredKeys } from './database/utils/requiredKeys'\n\nconst optionalKeys = ['skins', 'emoticon', 'shortcodes', 'tags']\nconst allKeys = [...requiredKeys, ...optionalKeys]\n\nconst allSkinsKeys = ['tone', 'emoji', 'version']\n\nexport default function trimEmojiData (emojiData) {\n console.warn('trimEmojiData() is deprecated and may be removed eventually. ' +\n 'If you use emoji-picker-element-data instead of emojibase-data, there is no need for trimEmojiData(). ' +\n 'For details, see: ' +\n 'https://github.com/nolanlawson/emoji-picker-element/blob/master/README.md#trimming-the-emoji-data-deprecated'\n )\n assertEmojiData(emojiData)\n return emojiData.map(emoji => {\n const res = {}\n for (const key of allKeys) {\n if (key in emoji) {\n if (key === 'skins') { // trim skins even further\n res[key] = emoji[key].map(skin => {\n const skinRes = {}\n for (const skinKey of allSkinsKeys) {\n skinRes[skinKey] = skin[skinKey]\n }\n return skinRes\n })\n } else {\n res[key] = emoji[key]\n }\n }\n }\n return res\n })\n};\n"],"names":[],"mappings":";;AAAO,MAAM,YAAY,GAAG;AAC5B,EAAE,YAAY;AACd,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE;AACF;;ACJO,SAAS,eAAe,EAAE,SAAS,EAAE;AAC5C,EAAE,IAAI,CAAC,SAAS;AAChB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;AAC7B,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;AACjB,KAAK,OAAO,SAAS,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;AACtC,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,KAAK,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACxD,IAAI,MAAM,IAAI,KAAK,CAAC,mCAAmC;AACvD,EAAE;AACF;;ACPA,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM;AAC/D,MAAM,OAAO,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,YAAY;;AAEjD,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS;;AAEjC,SAAS,aAAa,EAAE,SAAS,EAAE;AAClD,EAAE,OAAO,CAAC,IAAI,CAAC,+DAA+D;AAC9E,IAAI,wGAAwG;AAC5G,IAAI,oBAAoB;AACxB,IAAI;AACJ;AACA,EAAE,eAAe,CAAC,SAAS;AAC3B,EAAE,OAAO,SAAS,CAAC,GAAG,CAAC,KAAK,IAAI;AAChC,IAAI,MAAM,GAAG,GAAG;AAChB,IAAI,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE;AAC/B,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE;AACxB,QAAQ,IAAI,GAAG,KAAK,OAAO,EAAE;AAC7B,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI;AAC5C,YAAY,MAAM,OAAO,GAAG;AAC5B,YAAY,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE;AAChD,cAAc,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO;AAC7C,YAAY;AACZ,YAAY,OAAO;AACnB,UAAU,CAAC;AACX,QAAQ,CAAC,MAAM;AACf,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG;AAC9B,QAAQ;AACR,MAAM;AACN,IAAI;AACJ,IAAI,OAAO;AACX,EAAE,CAAC;AACH;;;;"}
@@ -0,0 +1,8 @@
import { Emoji } from "./shared.js";
/**
* Given an array of emoji (e.g. emojibase-data/en/data.json), extract out only the data
* needed for emoji-picker-element, resulting in a smaller object.
* @param emojiData
* @deprecated - Not required when using emoji-picker-element-data rather than emojibase-data
*/
export default function trimEmojiData(emojiData: Emoji[]): Emoji[];
+52
View File
@@ -0,0 +1,52 @@
const requiredKeys = [
'annotation',
'emoji',
'group',
'order',
'version'
];
function assertEmojiData (emojiData) {
if (!emojiData ||
!Array.isArray(emojiData) ||
!emojiData[0] ||
(typeof emojiData[0] !== 'object') ||
requiredKeys.some(key => (!(key in emojiData[0])))) {
throw new Error('Emoji data is in the wrong format')
}
}
const optionalKeys = ['skins', 'emoticon', 'shortcodes', 'tags'];
const allKeys = [...requiredKeys, ...optionalKeys];
const allSkinsKeys = ['tone', 'emoji', 'version'];
function trimEmojiData (emojiData) {
console.warn('trimEmojiData() is deprecated and may be removed eventually. ' +
'If you use emoji-picker-element-data instead of emojibase-data, there is no need for trimEmojiData(). ' +
'For details, see: ' +
'https://github.com/nolanlawson/emoji-picker-element/blob/master/README.md#trimming-the-emoji-data-deprecated'
);
assertEmojiData(emojiData);
return emojiData.map(emoji => {
const res = {};
for (const key of allKeys) {
if (key in emoji) {
if (key === 'skins') { // trim skins even further
res[key] = emoji[key].map(skin => {
const skinRes = {};
for (const skinKey of allSkinsKeys) {
skinRes[skinKey] = skin[skinKey];
}
return skinRes
});
} else {
res[key] = emoji[key];
}
}
}
return res
})
}
export { trimEmojiData as default };
@@ -0,0 +1 @@
{"version":3,"file":"trimEmojiData.js","sources":["src/database/utils/requiredKeys.js","src/database/utils/assertEmojiData.js","src/trimEmojiData.js"],"sourcesContent":["export const requiredKeys = [\n 'annotation',\n 'emoji',\n 'group',\n 'order',\n 'version'\n]\n","import { requiredKeys } from './requiredKeys'\n\nexport function assertEmojiData (emojiData) {\n if (!emojiData ||\n !Array.isArray(emojiData) ||\n !emojiData[0] ||\n (typeof emojiData[0] !== 'object') ||\n requiredKeys.some(key => (!(key in emojiData[0])))) {\n throw new Error('Emoji data is in the wrong format')\n }\n}\n","import { assertEmojiData } from './database/utils/assertEmojiData'\nimport { requiredKeys } from './database/utils/requiredKeys'\n\nconst optionalKeys = ['skins', 'emoticon', 'shortcodes', 'tags']\nconst allKeys = [...requiredKeys, ...optionalKeys]\n\nconst allSkinsKeys = ['tone', 'emoji', 'version']\n\nexport default function trimEmojiData (emojiData) {\n console.warn('trimEmojiData() is deprecated and may be removed eventually. ' +\n 'If you use emoji-picker-element-data instead of emojibase-data, there is no need for trimEmojiData(). ' +\n 'For details, see: ' +\n 'https://github.com/nolanlawson/emoji-picker-element/blob/master/README.md#trimming-the-emoji-data-deprecated'\n )\n assertEmojiData(emojiData)\n return emojiData.map(emoji => {\n const res = {}\n for (const key of allKeys) {\n if (key in emoji) {\n if (key === 'skins') { // trim skins even further\n res[key] = emoji[key].map(skin => {\n const skinRes = {}\n for (const skinKey of allSkinsKeys) {\n skinRes[skinKey] = skin[skinKey]\n }\n return skinRes\n })\n } else {\n res[key] = emoji[key]\n }\n }\n }\n return res\n })\n};\n"],"names":[],"mappings":"AAAO,MAAM,YAAY,GAAG;AAC5B,EAAE,YAAY;AACd,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE,OAAO;AACT,EAAE;AACF;;ACJO,SAAS,eAAe,EAAE,SAAS,EAAE;AAC5C,EAAE,IAAI,CAAC,SAAS;AAChB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC;AAC7B,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;AACjB,KAAK,OAAO,SAAS,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC;AACtC,IAAI,YAAY,CAAC,IAAI,CAAC,GAAG,KAAK,EAAE,GAAG,IAAI,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE;AACxD,IAAI,MAAM,IAAI,KAAK,CAAC,mCAAmC;AACvD,EAAE;AACF;;ACPA,MAAM,YAAY,GAAG,CAAC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM;AAC/D,MAAM,OAAO,GAAG,CAAC,GAAG,YAAY,EAAE,GAAG,YAAY;;AAEjD,MAAM,YAAY,GAAG,CAAC,MAAM,EAAE,OAAO,EAAE,SAAS;;AAEjC,SAAS,aAAa,EAAE,SAAS,EAAE;AAClD,EAAE,OAAO,CAAC,IAAI,CAAC,+DAA+D;AAC9E,IAAI,wGAAwG;AAC5G,IAAI,oBAAoB;AACxB,IAAI;AACJ;AACA,EAAE,eAAe,CAAC,SAAS;AAC3B,EAAE,OAAO,SAAS,CAAC,GAAG,CAAC,KAAK,IAAI;AAChC,IAAI,MAAM,GAAG,GAAG;AAChB,IAAI,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE;AAC/B,MAAM,IAAI,GAAG,IAAI,KAAK,EAAE;AACxB,QAAQ,IAAI,GAAG,KAAK,OAAO,EAAE;AAC7B,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI;AAC5C,YAAY,MAAM,OAAO,GAAG;AAC5B,YAAY,KAAK,MAAM,OAAO,IAAI,YAAY,EAAE;AAChD,cAAc,OAAO,CAAC,OAAO,CAAC,GAAG,IAAI,CAAC,OAAO;AAC7C,YAAY;AACZ,YAAY,OAAO;AACnB,UAAU,CAAC;AACX,QAAQ,CAAC,MAAM;AACf,UAAU,GAAG,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG;AAC9B,QAAQ;AACR,MAAM;AACN,IAAI;AACJ,IAAI,OAAO;AACX,EAAE,CAAC;AACH;;;;"}