diff --git a/README.md b/README.md
index 9a2fcaa..3967864 100644
--- a/README.md
+++ b/README.md
@@ -13,7 +13,7 @@ For instance, it converts quotes like `"these"` to `βtheseβ`, which are typo
Additionally, you can convert text into more than 40 different font styles and casing changes.
You can enable and disable any features in the options and adjust more settings regarding the behavior of the add-on.
-This extension works with modern Firefox v112 or higher, Chromium/Chrome and Thunderbird v112 or higher.
+This extension works with modern Firefox v125 or higher, Chromium/Chrome and Thunderbird v125 or higher.
## Download
diff --git a/assets/texts/en/amoDescription.html b/assets/texts/en/amoDescription.html
index 07c2bef..0f1fe7b 100644
--- a/assets/texts/en/amoDescription.html
+++ b/assets/texts/en/amoDescription.html
@@ -65,7 +65,7 @@
The add-on is free/libre open-source software and developed on GitHub. Fork it on GitHub and contribute.
There are some easy issues to start with.
-This extension works with modern Firefox and Thunderbird v112 or higher.
+This extension works with modern Firefox and Thunderbird v125 or higher.
πββοΈ Contribute πββοΈ
diff --git a/assets/texts/en/atnDescription.html b/assets/texts/en/atnDescription.html
index 8a67bfa..83b5eaf 100644
--- a/assets/texts/en/atnDescription.html
+++ b/assets/texts/en/atnDescription.html
@@ -60,7 +60,7 @@
The add-on is free/libre open-source software and developed on GitHub. Fork it on GitHub and contribute.
There are some easy issues to start with.
-This extension works with modern Firefox and Thunderbird v112 or higher.
+This extension works with modern Firefox and Thunderbird v125 or higher.
Contribute
diff --git a/scripts/manifests/dev.json b/scripts/manifests/dev.json
index f78baaf..e9a7f7f 100644
--- a/scripts/manifests/dev.json
+++ b/scripts/manifests/dev.json
@@ -45,7 +45,7 @@
"browser_specific_settings": {
"gecko": {
"id": "unicodify@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 99a1e0a..31c4cb4 100644
--- a/scripts/manifests/firefox.json
+++ b/scripts/manifests/firefox.json
@@ -43,7 +43,7 @@
"browser_specific_settings": {
"gecko": {
"id": "unicodify@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 02ff3f5..479f379 100644
--- a/scripts/manifests/thunderbirdmanifest.json
+++ b/scripts/manifests/thunderbirdmanifest.json
@@ -47,7 +47,7 @@
"browser_specific_settings": {
"gecko": {
"id": "unicodify@rugk.github.io",
- "strict_min_version": "112.0"
+ "strict_min_version": "125.0"
}
}
}
diff --git a/src/_locales/en/messages.json b/src/_locales/en/messages.json
index 1c2b4d6..5376527 100644
--- a/src/_locales/en/messages.json
+++ b/src/_locales/en/messages.json
@@ -122,6 +122,10 @@
"message": "Change casing",
"description": "An entry in the context menu. This is an entry for the case."
},
+ "menuCaseSentenceCase": {
+ "message": "Sentence case.",
+ "description": "An entry in the context menu. This is an entry for the case."
+ },
"menuCaseLowercase": {
"message": "Lowercase",
"description": "An entry in the context menu. This is an entry for the case."
diff --git a/src/background/modules/AutocorrectHandler.js b/src/background/modules/AutocorrectHandler.js
index bd1de93..d718a15 100644
--- a/src/background/modules/AutocorrectHandler.js
+++ b/src/background/modules/AutocorrectHandler.js
@@ -44,14 +44,14 @@ 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 === 0)) {
+ if (LEAF in atree && Object.keys(atree).length === 0) {
+ characterClass.push(escaptedChar);
+ } else {
const recurse = createRegEx(atree);
alternatives.push(recurse + escaptedChar);
- } else {
- characterClass.push(escaptedChar);
}
}
}
@@ -139,7 +139,7 @@ function applySettings() {
continue;
}
const aindex = x.indexOf(y);
- if (aindex >= 0) {
+ if (aindex !== -1) {
if (aindex < index) {
index = aindex;
length = y.length;
@@ -235,7 +235,7 @@ export async function init() {
setSettings(autocorrect);
// Thunderbird
- // Remove if part 3 of https://bugzilla.mozilla.org/show_bug.cgi?id=1630786#c4 is ever done
+ // Cannot register scripts in manifest.json file: https://bugzilla.mozilla.org/show_bug.cgi?id=1902843
if (browser.composeScripts) {
browser.composeScripts.register({
js: [
diff --git a/src/common/modules/UnicodeTransformationHandler.js b/src/common/modules/UnicodeTransformationHandler.js
index 467f4e9..d8c1a8f 100644
--- a/src/common/modules/UnicodeTransformationHandler.js
+++ b/src/common/modules/UnicodeTransformationHandler.js
@@ -1,5 +1,9 @@
import { fontLetters, formats, CASE_ID_PREFIX, CODE_CASE_ID_PREFIX, FONT_ID_PREFIX, FORMAT_ID_PREFIX, TRANSFORMATION_TYPE } from "/common/modules/data/Fonts.js";
+const segmenter = new Intl.Segmenter();
+const segmenter1 = new Intl.Segmenter([], { granularity: "word" });
+const segmenter2 = new Intl.Segmenter([], { granularity: "sentence" });
+
/**
* Transforms the given text according to the given transformation.
*
@@ -67,11 +71,23 @@ export function getTransformationType(transformationId) {
* @returns {string}
*/
function capitalizeEachWord(text) {
- // Regular expression Unicode property escapes and lookbehind assertions require Firefox/Thunderbird 78
- // see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#bcd:javascript.builtins.RegExp
- // Intl.Segmenter is not yet supported by Firefox/Thunderbird: https://bugzilla.mozilla.org/show_bug.cgi?id=1423593
- // \p{Alphabetic}
- return text.replaceAll(/(?<=^|\P{Alpha})\p{Alpha}\S*/gu, ([h, ...t]) => h.toLocaleUpperCase() + t.join(""));
+ return Array.from(segmenter1.segment(text), ({ segment, isWordLike }) => {
+ if (isWordLike) {
+ const [h, ...t] = segment;
+ return h.toLocaleUpperCase() + t.join("");
+ }
+ return segment;
+ }).join("");
+}
+
+/**
+ * Sentence Case.
+ *
+ * @param {string} text
+ * @returns {string}
+ */
+function sentenceCase(text) {
+ return Array.from(segmenter2.segment(text), ({ segment: [h, ...t] }) => h.toLocaleUpperCase() + t.join("")).join("");
}
/**
@@ -132,7 +148,7 @@ function changeFormat(text, chosenFormat) {
throw new Error(`Format ${chosenFormat} could not be processed.`);
}
- return Array.from(text, (letter) => letter + format).join("");
+ return Array.from(segmenter.segment(text), ({ segment }) => segment + format).join("");
}
/**
@@ -166,6 +182,7 @@ function toggleCase(atext) {
* @type {Object.}
*/
const changeCase = Object.freeze({
+ SentenceCase: (str) => sentenceCase(str.toLocaleLowerCase()),
Lowercase: (str) => str.toLocaleLowerCase(),
Uppercase: (str) => str.toLocaleUpperCase(),
CapitalizeEachWord: (str) => capitalizeEachWord(str.toLocaleLowerCase()),
diff --git a/src/common/modules/data/Fonts.js b/src/common/modules/data/Fonts.js
index 13d4319..e752405 100644
--- a/src/common/modules/data/Fonts.js
+++ b/src/common/modules/data/Fonts.js
@@ -132,6 +132,7 @@ export const menuStructure = Object.freeze({
},
[TRANSFORMATION_TYPE.CASING]: {
[`${CASE_ID_PREFIX}Casing`]: [
+ `${CASE_ID_PREFIX}SentenceCase`,
`${CASE_ID_PREFIX}Lowercase`,
`${CASE_ID_PREFIX}Uppercase`,
`${CASE_ID_PREFIX}CapitalizeEachWord`,
diff --git a/src/content_scripts/autocorrect.js b/src/content_scripts/autocorrect.js
index 34ecd30..0f59e51 100644
--- a/src/content_scripts/autocorrect.js
+++ b/src/content_scripts/autocorrect.js
@@ -31,6 +31,8 @@ const constants = Object.freeze({
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
@@ -65,7 +67,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;
}
@@ -77,7 +83,6 @@ function getCaretPosition(target) {
return caretposition;
}
// input and textarea fields
-
if (target.selectionStart !== target.selectionEnd) {
return null;
}
@@ -135,22 +140,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("\u200D");
- 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;
}
/**
diff --git a/src/manifest.json b/src/manifest.json
index f78baaf..e9a7f7f 100644
--- a/src/manifest.json
+++ b/src/manifest.json
@@ -45,7 +45,7 @@
"browser_specific_settings": {
"gecko": {
"id": "unicodify@rugk.github.io",
- "strict_min_version": "112.0"
+ "strict_min_version": "125.0"
}
}
}