diff --git a/.github/workflows/webext-lint.yml b/.github/workflows/webext-lint.yml index 9065ffb..4cdc07e 100644 --- a/.github/workflows/webext-lint.yml +++ b/.github/workflows/webext-lint.yml @@ -13,8 +13,8 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 - + - uses: actions/checkout@v4 + - name: "web-ext lint" uses: kewisch/action-web-ext@v1 with: diff --git a/README.md b/README.md index e4502e9..7201304 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ It uses up-to-date Emojis and lets you access your Emojis in different styles yo It is based on the awesome [emoji-mart](https://missive.github.io/emoji-mart/). You can test many features there already, before installing it. -This extension works with Firefox v74 or higher, Chromium/Chrome and Thunderbird v91 or higher. +This extension works with Firefox v125 or higher, Chromium/Chrome and Thunderbird v125 or higher. The development of this add-on was also triggered, because the development of another add-on called [“Emoji Helper” or “Emoji Cheatsheet” stalled](https://github.com/johannhof/emoji-helper/issues/127). diff --git a/assets/texts/en/amoDescription.html b/assets/texts/en/amoDescription.html index 5509072..bb91eaa 100644 --- a/assets/texts/en/amoDescription.html +++ b/assets/texts/en/amoDescription.html @@ -9,7 +9,7 @@ It will remember your recently used emojis across sites. Additionally it may often be faster than the emoji picker on the website itself. It is based on the awesome project emoji-mart. You can test many features on the website there already, without installing it. -This extension only works with Firefox v74 or higher and Thunderbird v91 or higher. +This extension only works with Firefox and Thunderbird v125 or higher. It has an effective built-in search, so you can use it as an “emoji cheat sheet”. Find exactly the emoji you wanted to find with your search term! diff --git a/assets/texts/en/atnDescription.html b/assets/texts/en/atnDescription.html index 43270eb..418449c 100644 --- a/assets/texts/en/atnDescription.html +++ b/assets/texts/en/atnDescription.html @@ -9,7 +9,7 @@ It will remember your recently used emojis across e-mails. It is based on the awesome project emoji-mart. You can test many features on the website there already, without installing it. -This extension only works with Firefox v74 or higher and Thunderbird v91 or higher. +This extension only works with Firefox and Thunderbird v125 or higher. It has an effective built-in search, so you can use it as an “emoji cheat sheet”. Find exactly the emoji you wanted to find with your search term! diff --git a/scripts/manifests/dev.json b/scripts/manifests/dev.json index d2a1c68..e493570 100644 --- a/scripts/manifests/dev.json +++ b/scripts/manifests/dev.json @@ -74,7 +74,7 @@ "browser_specific_settings": { "gecko": { "id": "awesome-emoji-picker@rugk.github.io", - "strict_min_version": "112.0" + "strict_min_version": "125.0" } } } diff --git a/scripts/manifests/firefox.json b/scripts/manifests/firefox.json index 38333d0..3672434 100644 --- a/scripts/manifests/firefox.json +++ b/scripts/manifests/firefox.json @@ -73,7 +73,7 @@ "browser_specific_settings": { "gecko": { "id": "awesome-emoji-picker@rugk.github.io", - "strict_min_version": "112.0" + "strict_min_version": "125.0" } } } diff --git a/scripts/manifests/thunderbirdmanifest.json b/scripts/manifests/thunderbirdmanifest.json index ad6f573..0bcd22e 100644 --- a/scripts/manifests/thunderbirdmanifest.json +++ b/scripts/manifests/thunderbirdmanifest.json @@ -62,7 +62,7 @@ "browser_specific_settings": { "gecko": { "id": "awesome-emoji-picker@rugk.github.io", - "strict_min_version": "112.0" + "strict_min_version": "125.0" } } } diff --git a/src/background/modules/ContextMenu.js b/src/background/modules/ContextMenu.js index 5513173..5e4c7eb 100644 --- a/src/background/modules/ContextMenu.js +++ b/src/background/modules/ContextMenu.js @@ -5,7 +5,7 @@ import { isMobile } from "/common/modules/MobileHelper.js"; import { COMMUNICATION_MESSAGE_TYPE } from "/common/modules/data/BrowserCommunicationTypes.js"; // Thunderbird -const IS_THUNDERBIRD = typeof messenger !== "undefined"; +const IS_THUNDERBIRD = Boolean(globalThis.messenger); // Chrome const IS_CHROME = Object.getPrototypeOf(browser) !== Object.prototype; diff --git a/src/background/modules/OmniboxSearch.js b/src/background/modules/OmniboxSearch.js index 146f35c..5698380 100644 --- a/src/background/modules/OmniboxSearch.js +++ b/src/background/modules/OmniboxSearch.js @@ -72,7 +72,7 @@ function openTabUrl(url, disposition) { * @see {@link https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/omnibox/onInputChanged} */ export function triggerOmnixboxSuggestion(text, suggest) { - const searchResult = window.emojiMart.emojiIndex.search(text); + const searchResult = globalThis.emojiMart.emojiIndex.search(text); // if none are found, return… if (!searchResult) { @@ -143,14 +143,14 @@ export async function triggerOmnixboxDisabledSearch(text, disposition) { */ export async function triggerOmnixboxSearch(text, disposition) { text = text.trim(); - const searchResult = window.emojiMart.emojiIndex.search(text); + const searchResult = globalThis.emojiMart.emojiIndex.search(text); const emojiSearch = await AddonSettings.get("emojiSearch"); // if a single emoji is selected or searched for, detect this and return // emoji data try { - const foundEmoji = window.emojiMart.getEmojiDataFromNative(text); + const foundEmoji = globalThis.emojiMart.getEmojiDataFromNative(text); if (foundEmoji) { searchResult.push(foundEmoji); @@ -203,7 +203,7 @@ export async function triggerOmnixboxSearch(text, disposition) { */ async function toggleEnabledStatus(toEnable) { // Thunderbird - if (typeof messenger !== "undefined") { + if (!browser.omnibox) { return; } @@ -235,7 +235,9 @@ async function toggleEnabledStatus(toEnable) { browser.i18n.getMessage("extensionName") ]) }); - } else if (!toEnable) { + } else if (toEnable) { + throw new TypeError("isEnabled must be boolean!"); + } else { browser.omnibox.onInputEntered.addListener(triggerOmnixboxDisabledSearch); browser.omnibox.setDefaultSuggestion({ @@ -243,8 +245,6 @@ async function toggleEnabledStatus(toEnable) { browser.i18n.getMessage("extensionName") ]) }); - } else { - throw new TypeError("isEnabled must be boolean!"); } } diff --git a/src/common/modules/AutocorrectHandler.js b/src/common/modules/AutocorrectHandler.js index 9c47f39..2dd4d7f 100644 --- a/src/common/modules/AutocorrectHandler.js +++ b/src/common/modules/AutocorrectHandler.js @@ -49,15 +49,15 @@ function createRegEx(tree) { for (const char in tree) { if (char) { - const escaptedChar = char.replace(regExSpecialChars, "\\$&"); + const escaptedChar = RegExp.escape ? RegExp.escape(char) : char.replaceAll(regExSpecialChars, String.raw`\$&`); const atree = tree[char]; - if (!(LEAF in atree && Object.keys(atree).length === 1)) { + if (LEAF in atree && Object.keys(atree).length === 1) { + characterClass.push(escaptedChar); + } else { const recurse = createRegEx(atree); alternatives.push(recurse + escaptedChar); // alternatives.push(escaptedChar + recurse); - } else { - characterClass.push(escaptedChar); } } } @@ -149,7 +149,7 @@ function applySettings() { continue; } const aindex = x.indexOf(y); - if (aindex >= 0) { + if (aindex !== -1) { if (aindex < index) { index = aindex; length = y.length; @@ -244,10 +244,10 @@ export async function init() { const autocorrect = await AddonSettings.get("autocorrect"); for (const emoji of Object.values(emojiMart.emojiIndex.emojis)) { - if (!emoji.native) { - emojiShortcodes[emoji[1].colons] = emoji[1].native; - } else { + if (emoji.native) { emojiShortcodes[emoji.colons] = emoji.native; + } else { + emojiShortcodes[emoji[1].colons] = emoji[1].native; } } @@ -255,28 +255,9 @@ export async function init() { setSettings(autocorrect); - browser.runtime.onMessage.addListener((message, sender) => { - // console.log(message); - if (message.type === COMMUNICATION_MESSAGE_TYPE.AUTOCORRECT_CONTENT) { - const response = { - type: COMMUNICATION_MESSAGE_TYPE.AUTOCORRECT_CONTENT, - enabled: settings.enabled, - autocomplete: settings.autocomplete, - autocompleteSelect: settings.autocompleteSelect, - autocorrections, - longest, - symbolpatterns: IS_CHROME ? symbolpatterns.source : symbolpatterns, - antipatterns: IS_CHROME ? antipatterns.source : antipatterns, - emojiShortcodes - }; - // console.log(response); - return Promise.resolve(response); - } - }); - // Thunderbird - // Remove if part 3 of https://bugzilla.mozilla.org/show_bug.cgi?id=1630786#c4 is ever done - if (typeof messenger !== "undefined") { + // Cannot register scripts in manifest.json file: https://bugzilla.mozilla.org/show_bug.cgi?id=1902843 + if (browser.composeScripts) { browser.composeScripts.register({ js: [ { file: "/content_scripts/autocorrect.js" } @@ -291,3 +272,22 @@ BrowserCommunication.addListener(COMMUNICATION_MESSAGE_TYPE.AUTOCORRECT_BACKGROU return sendSettings(request.optionValue); }); + +browser.runtime.onMessage.addListener((message, sender) => { + // console.log(message); + if (message.type === COMMUNICATION_MESSAGE_TYPE.AUTOCORRECT_CONTENT) { + const response = { + type: COMMUNICATION_MESSAGE_TYPE.AUTOCORRECT_CONTENT, + enabled: settings.enabled, + autocomplete: settings.autocomplete, + autocompleteSelect: settings.autocompleteSelect, + autocorrections, + longest, + symbolpatterns: IS_CHROME ? symbolpatterns.source : symbolpatterns, + antipatterns: IS_CHROME ? antipatterns.source : antipatterns, + emojiShortcodes + }; + // console.log(response); + return Promise.resolve(response); + } +}); diff --git a/src/common/modules/IconHandler.js b/src/common/modules/IconHandler.js index e8140e9..68aba81 100644 --- a/src/common/modules/IconHandler.js +++ b/src/common/modules/IconHandler.js @@ -23,7 +23,7 @@ function setPopupIcon(icon) { } // Thunderbird - const browserAction = typeof messenger !== "undefined" ? browser.composeAction : browser.browserAction; + const browserAction = globalThis.messenger ? browser.composeAction : browser.browserAction; // ignore request if API is not available if (!browserAction.setIcon) { diff --git a/src/common/modules/data/Tips.js b/src/common/modules/data/Tips.js index 8ef5216..1dfaced 100644 --- a/src/common/modules/data/Tips.js +++ b/src/common/modules/data/Tips.js @@ -80,7 +80,7 @@ import { getBrowserValue } from "../BrowserCompat.js"; // Thunderbird // https://bugzilla.mozilla.org/show_bug.cgi?id=1641573 -const IS_THUNDERBIRD = typeof messenger !== "undefined"; +const IS_THUNDERBIRD = Boolean(globalThis.messenger); const DEFAULT_POPUP_HOT_KEY = "Ctrl+Shift+Period"; diff --git a/src/content_scripts/autocorrect.js b/src/content_scripts/autocorrect.js index ed7da3d..6b60194 100644 --- a/src/content_scripts/autocorrect.js +++ b/src/content_scripts/autocorrect.js @@ -5,6 +5,8 @@ const AUTOCORRECT_CONTENT = "autocorrectContent"; const INSERT = "insert"; +const segmenter = new Intl.Segmenter(); + let insertedText; // Last insert text let deletedText; // Last deleted text let lastTarget; // Last target @@ -41,7 +43,11 @@ function getCaretPosition(target) { // ContentEditable elements if (target.isContentEditable || document.designMode === "on") { target.focus(); - const _range = document.getSelection().getRangeAt(0); + const selection = document.getSelection(); + if (selection.rangeCount !== 1) { + return null; + } + const _range = selection.getRangeAt(0); if (!_range.collapsed) { return null; } @@ -76,7 +82,7 @@ function insertAtCaret(target, atext) { } // Firefox input and textarea fields: https://bugzilla.mozilla.org/show_bug.cgi?id=1220696 - if (typeof target.setRangeText === "function") { + if (target.setRangeText) { const start = target.selectionStart; const end = target.selectionEnd; @@ -130,22 +136,13 @@ function insertIntoPage(atext) { /** * Count Unicode characters. * Adapted from: https://blog.jonnew.com/posts/poo-dot-length-equals-two - * Intl.Segmenter is not yet supported by Firefox/Thunderbird: https://bugzilla.mozilla.org/show_bug.cgi?id=1423593 * * @param {string} str * @returns {number} */ function countChars(str) { // removing the joiners - const split = str.split("\u{200D}"); - let count = 0; - - for (const s of split) { - // removing the variation selectors - count += Array.from(s.replaceAll(/[\uFE00-\uFE0F]/gu, "")).length; - } - - return count; + return Array.from(segmenter.segment(str.replaceAll("\u200D", ""))).length; } /** @@ -165,7 +162,7 @@ function deleteCaret(target, atext) { } } // Firefox input and textarea fields: https://bugzilla.mozilla.org/show_bug.cgi?id=1220696 - else if (typeof target.setRangeText === "function") { + else if (target.setRangeText) { const start = target.selectionStart; target.selectionStart = start - atext.length; @@ -198,9 +195,9 @@ function autocorrect(event) { return; } running = true; - const target = event.target; + const { target } = event; const caretposition = getCaretPosition(target); - if (caretposition) { + if (caretposition != null) { const value = target.value || target.innerText; let deletecount = 0; let insert = ["insertLineBreak", "insertParagraph"].includes(event.inputType) ? "\n" : event.data; @@ -213,8 +210,7 @@ function autocorrect(event) { const length = longest - 1; const text = value.slice(caretposition < length ? 0 : caretposition - length, caretposition) + inserted; const aregexResult = symbolpatterns.exec(text); - const aaregexResult = antipatterns.exec(text); - if (!aaregexResult && (!aregexResult || (caretposition <= longest ? regexResult.index < aregexResult.index : regexResult.index <= aregexResult.index))) { + if (!antipatterns.test(text) && (!aregexResult || (caretposition <= longest ? regexResult.index < aregexResult.index : regexResult.index <= aregexResult.index))) { const [autocorrection] = regexResult; insert = autocorrections[autocorrection] + inserted; deletecount = autocorrection.length; @@ -288,9 +284,9 @@ function undoAutocorrect(event) { return; } running = true; - const target = event.target; + const { target } = event; const caretposition = getCaretPosition(target); - if (caretposition) { + if (caretposition != null) { if (target === lastTarget && caretposition === lastCaretPosition) { event.preventDefault(); diff --git a/src/manifest.json b/src/manifest.json index 5a96c5e..6fb61b7 100644 --- a/src/manifest.json +++ b/src/manifest.json @@ -74,7 +74,7 @@ "browser_specific_settings": { "gecko": { "id": "awesome-emoji-picker@rugk.github.io", - "strict_min_version": "112.0" + "strict_min_version": "125.0" } } } diff --git a/src/options/modules/ColorSchemeModeHelper.js b/src/options/modules/ColorSchemeModeHelper.js index c2e5405..d3e3903 100644 --- a/src/options/modules/ColorSchemeModeHelper.js +++ b/src/options/modules/ColorSchemeModeHelper.js @@ -23,7 +23,7 @@ function changeScreenshotTheme(darkQuery) { * @returns {void} */ export function init() { - const dark = window.matchMedia("(prefers-color-scheme: dark)"); + const dark = globalThis.matchMedia("(prefers-color-scheme: dark)"); dark.addEventListener("change", changeScreenshotTheme); diff --git a/src/options/modules/CustomOptionTriggers.js b/src/options/modules/CustomOptionTriggers.js index 9bd033e..d7f7483 100644 --- a/src/options/modules/CustomOptionTriggers.js +++ b/src/options/modules/CustomOptionTriggers.js @@ -24,7 +24,7 @@ const MESSAGE_TABS_PERMISSION = "tabsPermissionInfo"; // Thunderbird // https://bugzilla.mozilla.org/show_bug.cgi?id=1641573 -const IS_THUNDERBIRD = typeof messenger !== "undefined"; +const IS_THUNDERBIRD = Boolean(globalThis.messenger); /** * Adjust UI if QR code size option is changed. @@ -101,15 +101,15 @@ function applyAutocorrectPermissions(optionValue, option, event) { let retPromise; - if (!PermissionRequest.isPermissionGranted(TABS_PERMISSION) // and not already granted + if (PermissionRequest.isPermissionGranted(TABS_PERMISSION) // and not already granted ) { + PermissionRequest.cancelPermissionPrompt(TABS_PERMISSION, MESSAGE_TABS_PERMISSION); + } else { retPromise = PermissionRequest.requestPermission( TABS_PERMISSION, MESSAGE_TABS_PERMISSION, event ); - } else { - PermissionRequest.cancelPermissionPrompt(TABS_PERMISSION, MESSAGE_TABS_PERMISSION); } // trigger update for current session @@ -219,7 +219,7 @@ function getPluralForm(language, optionValue) { return optionValue > 1 ? "optionEmojisPerLineStatusPlural" : "optionEmojisPerLineStatusSingular"; // en, de default: - return optionValue !== 1 ? "optionEmojisPerLineStatusPlural" : "optionEmojisPerLineStatusSingular"; + return optionValue === 1 ? "optionEmojisPerLineStatusSingular" : "optionEmojisPerLineStatusPlural"; } } diff --git a/src/popup/module/EmojiPicker.js b/src/popup/module/EmojiPicker.js index 3d03601..2f948c4 100644 --- a/src/popup/module/EmojiPicker.js +++ b/src/popup/module/EmojiPicker.js @@ -107,7 +107,7 @@ export function init(settings) { console.debug("Using these emoji-mart settings:", initProperties); - const promiseCreateElement = window.emojiMart.definePicker("emoji-picker", initProperties); + const promiseCreateElement = globalThis.emojiMart.definePicker("emoji-picker", initProperties); return promiseCreateElement.then(() => { emojiPicker = document.createElement("emoji-picker"); diff --git a/src/popup/module/EmojiSelect.js b/src/popup/module/EmojiSelect.js index 30c8159..51cfc4a 100644 --- a/src/popup/module/EmojiSelect.js +++ b/src/popup/module/EmojiSelect.js @@ -114,9 +114,7 @@ export async function triggerOnSelect(emoji) { const messageToBeShown = getUserMessageForResult(isInserted, isCopied); - if (!messageToBeShown) { - CommonMessages.showError("couldNotDoAction", true); - } else { + if (messageToBeShown) { // if no error happened, show confirmation message if (showConfirmationMessage) { await ConfirmationHint.show(clickedEmoji, messageToBeShown); @@ -125,6 +123,8 @@ export async function triggerOnSelect(emoji) { if (closePopup) { window.close(); } + } else { + CommonMessages.showError("couldNotDoAction", true); } } diff --git a/src/popup/module/EmojiSettings.js b/src/popup/module/EmojiSettings.js index a3f7c07..a38a8e8 100644 --- a/src/popup/module/EmojiSettings.js +++ b/src/popup/module/EmojiSettings.js @@ -42,7 +42,7 @@ export async function initEmojiMartStorage() { // get saved values emojiMartStorage = await AddonSettings.get("emojiMart"); - window.emojiMart.setDataStore({ + globalThis.emojiMart.setDataStore({ getter: (key) => { return emojiMartStorage[key]; },