From 60d1aac72e0ac78fc62a8ea26fd7fffdaab5bad6 Mon Sep 17 00:00:00 2001 From: Miodec Date: Wed, 26 Nov 2025 17:52:24 +0100 Subject: [PATCH 01/15] fix: composition update not making sounds --- frontend/src/ts/test/test-ui.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/src/ts/test/test-ui.ts b/frontend/src/ts/test/test-ui.ts index e2ee27190b5f..a56078b923a9 100644 --- a/frontend/src/ts/test/test-ui.ts +++ b/frontend/src/ts/test/test-ui.ts @@ -1641,7 +1641,7 @@ function afterAnyTestInput( type: "textInput" | "delete" | "compositionUpdate", correctInput: boolean | null ): void { - if (type === "textInput") { + if (type === "textInput" || type === "compositionUpdate") { if ( correctInput === true || Config.playSoundOnError === "off" || From dcc4e405294591dd66b665760336b20565c7d31b Mon Sep 17 00:00:00 2001 From: Aquaduckd Date: Wed, 26 Nov 2025 16:32:07 -0500 Subject: [PATCH 02/15] fix(layout): pine v4 (#7110) the K key should be lowercase on the main layer --- frontend/static/layouts/pine_v4.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/static/layouts/pine_v4.json b/frontend/static/layouts/pine_v4.json index adf150630ade..2578b7ff68e1 100644 --- a/frontend/static/layouts/pine_v4.json +++ b/frontend/static/layouts/pine_v4.json @@ -22,7 +22,7 @@ ["l", "L"], ["c", "C"], ["m", "M"], - ["K", "K"], + ["k", "K"], ["'", "\""], ["f", "F"], ["u", "U"], From ddd5eb40d7911185138b2006c5c604823987face Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20Roquet?= Date: Wed, 26 Nov 2025 22:32:51 +0100 Subject: [PATCH 03/15] fix(language): add missing ligatures in french_10k (@Arkanosis) (#7111) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some words, only the ligature was missing; in others, the letters were too. Missing ligature only: - cœur - œil - œuvre Missing letters as well: - manœuvres - manœuvre - chœur - nœud - coup d'œil - blanc d'œuf --- frontend/static/languages/french_10k.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/frontend/static/languages/french_10k.json b/frontend/static/languages/french_10k.json index 7248077ab148..22dd85f18bce 100644 --- a/frontend/static/languages/french_10k.json +++ b/frontend/static/languages/french_10k.json @@ -230,7 +230,7 @@ "claire", "classe", "clef", - "coeur", + "cœur", "coin", "colère", "colline", @@ -859,8 +859,8 @@ "occasion", "occuper", "odeur", - "oeil", - "oeuvre", + "œil", + "œuvre", "officier", "offrir", "oh", @@ -2498,7 +2498,7 @@ "terroriste", "bercez", "ôter", - "manuvres", + "manœuvres", "domine", "aristocrate", "universités", @@ -4918,7 +4918,7 @@ "termes", "pommes", "semi", - "manuvre", + "manœuvre", "aquilon", "collègue", "matérielles", @@ -6309,7 +6309,7 @@ "soudoyer", "recenser", "recherché", - "rancurs", + "rancœurs", "nombrilisme", "huilerie", "pullulation", @@ -6916,7 +6916,7 @@ "légaux", "voyons", "vaccins", - "chur", + "chœur", "tombait", "tournés", "timoré", @@ -7083,7 +7083,7 @@ "dividendes", "bougies", "dispose", - "nud", + "nœud", "différé", "gaulliste", "sens unique", @@ -7787,7 +7787,7 @@ "unanimement", "nuance", "étudiés", - "crève-cur", + "crève-cœur", "créateurs", "variations", "pébroc", @@ -8523,7 +8523,7 @@ "arrêté", "cornu", "acrobatie", - "coup d'il", + "coup d'œil", "demandent", "sonnerie", "bambins", @@ -9807,7 +9807,7 @@ "pétulant", "nutrition", "marches", - "blanc d'uf", + "blanc d'œuf", "ambiguë", "land", "jarousse", From e8339f0a1f4de6f00b21906092bbb4683ec61378 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Wed, 26 Nov 2025 23:40:10 +0200 Subject: [PATCH 04/15] feat(funbox): Add rot13 funbox (@Leonabcd123) (#7116) ### Description Added a new funbox mode that implements the rot13 cipher, shifting each character over by 13 places. I'm not really sure which properties fit best with this... Implements #6565 --- .../src/ts/test/funbox/funbox-functions.ts | 24 +++++++++++++++++++ packages/funbox/src/list.ts | 8 +++++++ packages/schemas/src/configs.ts | 1 + 3 files changed, 33 insertions(+) diff --git a/frontend/src/ts/test/funbox/funbox-functions.ts b/frontend/src/ts/test/funbox/funbox-functions.ts index d26512871475..f461fe6b37e1 100644 --- a/frontend/src/ts/test/funbox/funbox-functions.ts +++ b/frontend/src/ts/test/funbox/funbox-functions.ts @@ -332,6 +332,30 @@ const list: Partial> = { return randomcaseword; }, }, + rot13: { + alterText(word: string): string { + let alphabet = "abcdefghijklmnopqrstuvwxyz"; + + let rot13Word = ""; + + for (let ch of word) { + let chIndex = alphabet.indexOf(ch.toLowerCase()); + if (chIndex === -1) { + rot13Word += ch; + continue; + } + + let rot13Ch = (chIndex + 13) % 26; + if (ch.toUpperCase() === ch) { + rot13Word += alphabet[rot13Ch]?.toUpperCase(); + } else { + rot13Word += alphabet[rot13Ch]; + } + } + + return rot13Word; + }, + }, backwards: { alterText(word: string): string { return word.split("").reverse().join(""); diff --git a/packages/funbox/src/list.ts b/packages/funbox/src/list.ts index 84aab9025a9f..3c18199824ec 100644 --- a/packages/funbox/src/list.ts +++ b/packages/funbox/src/list.ts @@ -460,6 +460,14 @@ const list: Record = { name: "asl", cssModifications: ["words"], }, + rot13: { + description: "Vg znl abg or frpher, ohg vg vf sha gb glcr!", + canGetPb: true, + difficultyLevel: 1, + properties: [], + frontendFunctions: ["alterText"], + name: "rot13", + }, no_quit: { description: "You can't restart the test.", canGetPb: true, diff --git a/packages/schemas/src/configs.ts b/packages/schemas/src/configs.ts index 3007b5435f4c..e7a88b2ccf87 100644 --- a/packages/schemas/src/configs.ts +++ b/packages/schemas/src/configs.ts @@ -304,6 +304,7 @@ export const FunboxNameSchema = z.enum([ "ALL_CAPS", "polyglot", "asl", + "rot13", "no_quit", ]); export type FunboxName = z.infer; From 31e07e28abcfcece7deba140850c61cd614e6f78 Mon Sep 17 00:00:00 2001 From: 28Zapper <28Zapperonlist@gmail.com> Date: Wed, 26 Nov 2025 22:40:56 +0100 Subject: [PATCH 05/15] impr(quotes): add quote to the english repository (@28Zapper) (#7113) impr(quotes): Added a quote from UNDERTALE to `./frontend/static/quotes/english.json`. (@28Zapper) --------- Co-authored-by: Miodec <13181393+Miodec@users.noreply.github.com> --- frontend/static/quotes/english.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/frontend/static/quotes/english.json b/frontend/static/quotes/english.json index c73fcd5f26cd..dc1c8a50c0e8 100644 --- a/frontend/static/quotes/english.json +++ b/frontend/static/quotes/english.json @@ -39081,6 +39081,12 @@ "source": "End Credits", "id": 7726, "length": 336 + }, + { + "text": "Haven't I done a great job at protecting you? I mean, look at yourself. You haven't died a single time.", + "source": "Undertale", + "id": 7727, + "length": 103 } ] } From f54c8a8cd8871249fc855ae542637aa354cc8153 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Wed, 26 Nov 2025 23:51:08 +0200 Subject: [PATCH 06/15] impr(practice-words): Add option to practice missed and slow words from commandline (@Leonabcd123) (#7125) ### Description Added an option to practice both missed and slow words from the command line by doing esc -> Practice words -> both. Implements #5753 --- frontend/src/ts/commandline/lists/result-screen.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frontend/src/ts/commandline/lists/result-screen.ts b/frontend/src/ts/commandline/lists/result-screen.ts index 7688b2d0a465..60207281b555 100644 --- a/frontend/src/ts/commandline/lists/result-screen.ts +++ b/frontend/src/ts/commandline/lists/result-screen.ts @@ -33,6 +33,16 @@ const practiceSubgroup: CommandsSubgroup = { }); }, }, + { + id: "practiseWordsBoth", + display: "both", + exec: (): void => { + PractiseWords.init("words", true); + TestLogic.restart({ + practiseMissed: true, + }); + }, + }, { id: "practiseWordsCustom", display: "custom...", From c99f504f3b9cf04ba0f11ee69de2a2d822d319d3 Mon Sep 17 00:00:00 2001 From: Lodun Coombs Date: Wed, 26 Nov 2025 14:02:35 -0800 Subject: [PATCH 07/15] fix(keymap): prevent tilde key from highlighting entire keymap (@LodunCoombs) (#7128) --- frontend/src/ts/elements/keymap.ts | 42 +++++++++++++++--------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/frontend/src/ts/elements/keymap.ts b/frontend/src/ts/elements/keymap.ts index 2ba5d4f93d21..2234c66cfd49 100644 --- a/frontend/src/ts/elements/keymap.ts +++ b/frontend/src/ts/elements/keymap.ts @@ -17,7 +17,7 @@ import { areSortedArraysEqual } from "../utils/arrays"; import { LayoutObject } from "@monkeytype/schemas/layouts"; import { animate } from "animejs"; -export const keyDataDelimiter = "~~"; +export const keyDataDelimiter = "\uE000"; const stenoKeys: LayoutObject = { keymapShowTopRow: true, @@ -58,27 +58,30 @@ const stenoKeys: LayoutObject = { }, }; +function findKeyElements(char: string): JQuery { + if (char === " ") { + return $("#keymap .keySpace"); + } + + if (char === '"') { + return $(`#keymap .keymapKey[data-key*='${char}']`); + } + + return $(`#keymap .keymapKey[data-key*="${char}"]`); +} + function highlightKey(currentKey: string): void { if (Config.mode === "zen") return; if (currentKey === "") currentKey = " "; try { $(".activeKey").removeClass("activeKey"); - let highlightKey; if (Config.language.startsWith("korean")) { currentKey = Hangul.disassemble(currentKey)[0] ?? currentKey; } - if (currentKey === " ") { - highlightKey = "#keymap .keySpace"; - } else if (currentKey === '"') { - highlightKey = `#keymap .keymapKey[data-key*='${currentKey}']`; - } else { - highlightKey = `#keymap .keymapKey[data-key*="${currentKey}"]`; - } - - // console.log("highlighting", highlightKey); - $(highlightKey).addClass("activeKey"); + const $target = findKeyElements(currentKey); + $target.addClass("activeKey"); } catch (e) { if (e instanceof Error) { console.log("could not update highlighted keymap key: " + e.message); @@ -88,14 +91,11 @@ function highlightKey(currentKey: string): void { async function flashKey(key: string, correct?: boolean): Promise { if (key === undefined) return; - //console.log("key", key); - if (key === " ") { - key = "#keymap .keySpace"; - } else if (key === '"') { - key = `#keymap .keymapKey[data-key*='${key}']`; - } else { - key = `#keymap .keymapKey[data-key*="${key}"]`; - } + + const $target = findKeyElements(key); + + const elements = $target.toArray(); + if (elements.length === 0) return; const themecolors = await ThemeColors.getAll(); @@ -120,7 +120,7 @@ async function flashKey(key: string, correct?: boolean): Promise { }; } - animate(key, { + animate(elements, { color: [startingStyle.color, themecolors.sub], backgroundColor: [startingStyle.backgroundColor, themecolors.subAlt], borderColor: [startingStyle.borderColor, themecolors.sub], From b7ddb26000783e2b139330a0a7a71f6cb09c45ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20BERSAC?= <542613+bersace@users.noreply.github.com> Date: Wed, 26 Nov 2025 23:03:18 +0100 Subject: [PATCH 08/15] =?UTF-8?q?fix(language):=20replace=20oe=20with=20?= =?UTF-8?q?=C5=93=20where=20relevant=20(@bersace)=20(#7130)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description Fix more ligatures on French. Supersedes #7111 ### Checks - [x] Check if any open issues are related to this PR; if so, be sure to tag them below. - [x] Make sure the PR title follows the Conventional Commits standard. (https://www.conventionalcommits.org for more info) - [x] Make sure to include your GitHub username prefixed with @ inside parentheses at the end of the PR title. --- frontend/static/languages/french_1k.json | 6 +- frontend/static/languages/french_2k.json | 6 +- frontend/static/languages/french_600k.json | 1746 ++++++++++---------- 3 files changed, 879 insertions(+), 879 deletions(-) diff --git a/frontend/static/languages/french_1k.json b/frontend/static/languages/french_1k.json index 3a509508dc23..c24c0459a345 100644 --- a/frontend/static/languages/french_1k.json +++ b/frontend/static/languages/french_1k.json @@ -228,7 +228,7 @@ "claire", "classe", "clef", - "coeur", + "cœur", "coin", "colère", "colline", @@ -851,8 +851,8 @@ "occasion", "occuper", "odeur", - "oeil", - "oeuvre", + "œil", + "œuvre", "officier", "offrir", "oh", diff --git a/frontend/static/languages/french_2k.json b/frontend/static/languages/french_2k.json index 333e5142ac05..ad0c86481809 100644 --- a/frontend/static/languages/french_2k.json +++ b/frontend/static/languages/french_2k.json @@ -230,7 +230,7 @@ "claire", "classe", "clef", - "coeur", + "cœur", "coin", "colère", "colline", @@ -859,8 +859,8 @@ "occasion", "occuper", "odeur", - "oeil", - "oeuvre", + "œil", + "œuvre", "officier", "offrir", "oh", diff --git a/frontend/static/languages/french_600k.json b/frontend/static/languages/french_600k.json index 25047c03a9ed..2edaf2675946 100644 --- a/frontend/static/languages/french_600k.json +++ b/frontend/static/languages/french_600k.json @@ -5730,10 +5730,10 @@ "acnés", "acochlidiidé", "acochlidiidés", - "acoele", - "acoeles", - "acoelomate", - "acoelomates", + "acœle", + "acœles", + "acœlomate", + "acœlomates", "acolytat", "acolytats", "acolyte", @@ -16296,8 +16296,8 @@ "allodialité", "allodialités", "allodiaux", - "alloeocoele", - "alloeocoeles", + "alloeocœle", + "alloeocœles", "alloesthésie", "alloesthésies", "allogame", @@ -31192,7 +31192,7 @@ "archontats", "archonte", "archontes", - "archontophoenix", + "archontophœnix", "archosaurien", "archosauriens", "archère", @@ -57551,10 +57551,10 @@ "bioclimats", "bioclinique", "biocliniques", - "biocoenose", - "biocoenoses", - "biocoenotique", - "biocoenotiques", + "biocœnose", + "biocœnoses", + "biocœnotique", + "biocœnotiques", "biocompatibilité", "biocompatibilités", "biocompatible", @@ -60047,12 +60047,12 @@ "blastiques", "blastocladiale", "blastocladiales", - "blastocoele", - "blastocoeles", - "blastocoelien", - "blastocoelienne", - "blastocoeliennes", - "blastocoeliens", + "blastocœle", + "blastocœles", + "blastocœlien", + "blastocœlienne", + "blastocœliennes", + "blastocœliens", "blastocyste", "blastocystes", "blastocyte", @@ -61277,10 +61277,10 @@ "boettée", "boettées", "boettés", - "boeuf", - "boeufs", - "boeutier", - "boeutiers", + "bœuf", + "bœufs", + "bœutier", + "bœutiers", "bof", "boffuma", "boffumer", @@ -94426,8 +94426,8 @@ "choerocampe", "choerocampes", "choesels", - "choeur", - "choeurs", + "chœur", + "chœurs", "chogramme", "chogrammes", "choie", @@ -103757,60 +103757,60 @@ "codétenus", "codéthyline", "codéthylines", - "coeco", - "coecosigmoïdostomie", - "coecosigmoïdostomies", - "coecostomie", - "coecostomies", + "cœco", + "cœcosigmoïdostomie", + "cœcosigmoïdostomies", + "cœcostomie", + "cœcostomies", "coefficient", "coefficients", - "coelacanthe", - "coelacanthes", - "coelentéré", - "coelentérés", - "coeliakie", - "coeliakies", - "coelialgie", - "coelialgies", - "coeliaque", - "coeliaques", - "coelifère", - "coelifères", - "coeliochirurgie", - "coeliochirurgies", - "coeliome", - "coeliomes", - "coelioscope", - "coelioscopes", - "coelioscopie", - "coelioscopies", - "coelioscopique", - "coelioscopiques", - "coeliotomie", - "coeliotomies", - "coelioxys", - "coelodendridé", - "coelodendridés", - "coelomate", - "coelomates", - "coelome", - "coelomes", - "coelomique", - "coelomiques", - "coelonychie", - "coelonychies", - "coelope", - "coelopes", - "coelosomie", - "coelosomien", - "coelosomienne", - "coelosomiennes", - "coelosomiens", - "coelosomies", - "coelothéliome", - "coelothéliomes", - "coelurosaure", - "coelurosaures", + "cœlacanthe", + "cœlacanthes", + "cœlentéré", + "cœlentérés", + "cœliakie", + "cœliakies", + "cœlialgie", + "cœlialgies", + "cœliaque", + "cœliaques", + "cœlifère", + "cœlifères", + "cœliochirurgie", + "cœliochirurgies", + "cœliome", + "cœliomes", + "cœlioscope", + "cœlioscopes", + "cœlioscopie", + "cœlioscopies", + "cœlioscopique", + "cœlioscopiques", + "cœliotomie", + "cœliotomies", + "cœlioxys", + "cœlodendridé", + "cœlodendridés", + "cœlomate", + "cœlomates", + "cœlome", + "cœlomes", + "cœlomique", + "cœlomiques", + "cœlonychie", + "cœlonychies", + "cœlope", + "cœlopes", + "cœlosomie", + "cœlosomien", + "cœlosomienne", + "cœlosomiennes", + "cœlosomiens", + "cœlosomies", + "cœlothéliome", + "cœlothéliomes", + "cœlurosaure", + "cœlurosaures", "coempereur", "coempereurs", "coendou", @@ -103819,12 +103819,12 @@ "coenesthésies", "coengagement", "coengagements", - "coenomyie", - "coenomyies", - "coenonympha", - "coenonymphas", - "coenothécale", - "coenothécales", + "cœnomyie", + "cœnomyies", + "cœnonympha", + "cœnonymphas", + "cœnothécale", + "cœnothécales", "coentraîneur", "coentraîneurs", "coentraînrice", @@ -103856,8 +103856,8 @@ "coerébidés", "coesre", "coesres", - "coeur", - "coeurs", + "cœur", + "cœurs", "coexista", "coexister", "coexistai", @@ -106159,8 +106159,8 @@ "colpidiums", "colpo", "colpocléisis", - "colpocoeliotomie", - "colpocoeliotomies", + "colpocœliotomie", + "colpocœliotomies", "colpocystographie", "colpocystographies", "colpocystopexie", @@ -113597,8 +113597,8 @@ "consistâtes", "consistèrent", "consisté", - "consoeur", - "consoeurs", + "consœur", + "consœurs", "consol", "consola", "consoler", @@ -116142,8 +116142,8 @@ "contrechâssis", "contreclef", "contreclefs", - "contrecoeur", - "contrecoeurs", + "contrecœur", + "contrecœurs", "contrecolla", "contrecoller", "contrecollage", @@ -135394,8 +135394,8 @@ "dendrochronologiques", "dendroclimatologie", "dendroclimatologies", - "dendrocoelum", - "dendrocoelums", + "dendrocœlum", + "dendrocœlums", "dendrocolapte", "dendrocolaptes", "dendroctone", @@ -139157,8 +139157,8 @@ "dicranomyias", "dicranure", "dicranures", - "dicrocoeliose", - "dicrocoelioses", + "dicrocœliose", + "dicrocœlioses", "dicroloma", "dicrolomas", "dicrote", @@ -139324,8 +139324,8 @@ "diencéphalo", "diencéphalopathie", "diencéphalopathies", - "dienoestrol", - "dienoestrols", + "dienœstrol", + "dienœstrols", "dientamoebidé", "dientamoebidés", "dieppois", @@ -140984,7 +140984,7 @@ "dioeciques", "dioecète", "dioecètes", - "dioestrus", + "diœstrus", "diogenes", "diogène", "diogènes", @@ -144890,8 +144890,8 @@ "diéthyliques", "diéthylmalonylurée", "diéthylmalonylurées", - "diéthylstilboestrol", - "diéthylstilboestrols", + "diéthylstilbœstrol", + "diéthylstilbœstrols", "diéthyltoluamide", "diéthyltoluamides", "diéthylèneglycol", @@ -160174,47 +160174,47 @@ "décodée", "décodées", "décodés", - "décoeura", - "décoeurer", - "décoeurage", - "décoeurages", - "décoeurai", - "décoeuraient", - "décoeurais", - "décoeurait", - "décoeurant", - "décoeuras", - "décoeurasse", - "décoeurassent", - "décoeurasses", - "décoeurassiez", - "décoeurassions", - "décoeure", - "décoeurent", - "décoeurera", - "décoeurerai", - "décoeureraient", - "décoeurerais", - "décoeurerait", - "décoeureras", - "décoeurerez", - "décoeureriez", - "décoeurerions", - "décoeurerons", - "décoeureront", - "décoeures", - "décoeurez", - "décoeuriez", - "décoeurions", - "décoeurons", - "décoeurâmes", - "décoeurât", - "décoeurâtes", - "décoeurèrent", - "décoeuré", - "décoeurée", - "décoeurées", - "décoeurés", + "décœura", + "décœurer", + "décœurage", + "décœurages", + "décœurai", + "décœuraient", + "décœurais", + "décœurait", + "décœurant", + "décœuras", + "décœurasse", + "décœurassent", + "décœurasses", + "décœurassiez", + "décœurassions", + "décœure", + "décœurent", + "décœurera", + "décœurerai", + "décœureraient", + "décœurerais", + "décœurerait", + "décœureras", + "décœurerez", + "décœureriez", + "décœurerions", + "décœurerons", + "décœureront", + "décœures", + "décœurez", + "décœuriez", + "décœurions", + "décœurons", + "décœurâmes", + "décœurât", + "décœurâtes", + "décœurèrent", + "décœuré", + "décœurée", + "décœurées", + "décœurés", "décoffra", "décoffrer", "décoffrage", @@ -204065,47 +204065,47 @@ "désodée", "désodées", "désodés", - "désoeuvra", - "désoeuvrer", - "désoeuvrai", - "désoeuvraient", - "désoeuvrais", - "désoeuvrait", - "désoeuvrant", - "désoeuvras", - "désoeuvrasse", - "désoeuvrassent", - "désoeuvrasses", - "désoeuvrassiez", - "désoeuvrassions", - "désoeuvre", - "désoeuvrement", - "désoeuvrements", - "désoeuvrent", - "désoeuvrera", - "désoeuvrerai", - "désoeuvreraient", - "désoeuvrerais", - "désoeuvrerait", - "désoeuvreras", - "désoeuvrerez", - "désoeuvreriez", - "désoeuvrerions", - "désoeuvrerons", - "désoeuvreront", - "désoeuvres", - "désoeuvrez", - "désoeuvriez", - "désoeuvrions", - "désoeuvrons", - "désoeuvrâmes", - "désoeuvrât", - "désoeuvrâtes", - "désoeuvrèrent", - "désoeuvré", - "désoeuvrée", - "désoeuvrées", - "désoeuvrés", + "désœuvra", + "désœuvrer", + "désœuvrai", + "désœuvraient", + "désœuvrais", + "désœuvrait", + "désœuvrant", + "désœuvras", + "désœuvrasse", + "désœuvrassent", + "désœuvrasses", + "désœuvrassiez", + "désœuvrassions", + "désœuvre", + "désœuvrement", + "désœuvrements", + "désœuvrent", + "désœuvrera", + "désœuvrerai", + "désœuvreraient", + "désœuvrerais", + "désœuvrerait", + "désœuvreras", + "désœuvrerez", + "désœuvreriez", + "désœuvrerions", + "désœuvrerons", + "désœuvreront", + "désœuvres", + "désœuvrez", + "désœuvriez", + "désœuvrions", + "désœuvrons", + "désœuvrâmes", + "désœuvrât", + "désœuvrâtes", + "désœuvrèrent", + "désœuvré", + "désœuvrée", + "désœuvrées", + "désœuvrés", "désofficialisa", "désofficialiser", "désofficialisai", @@ -212576,8 +212576,8 @@ "ectoplasmies", "ectoplasmique", "ectoplasmiques", - "ectopoesophage", - "ectopoesophages", + "ectopœsophage", + "ectopœsophages", "ectoprocte", "ectoproctes", "ectosome", @@ -257888,28 +257888,28 @@ "focus", "foehn", "foehns", - "foetal", - "foetale", - "foetales", - "foetalisation", - "foetalisations", - "foetaux", - "foeticide", - "foeticides", - "foeticulture", - "foeticultures", - "foeto", - "foetographie", - "foetographies", - "foetologie", - "foetologies", - "foetopathie", - "foetopathies", - "foetoscope", - "foetoscopes", - "foetoscopie", - "foetoscopies", - "foetus", + "fœtal", + "fœtale", + "fœtales", + "fœtalisation", + "fœtalisations", + "fœtaux", + "fœticide", + "fœticides", + "fœticulture", + "fœticultures", + "fœto", + "fœtographie", + "fœtographies", + "fœtologie", + "fœtologies", + "fœtopathie", + "fœtopathies", + "fœtoscope", + "fœtoscopes", + "fœtoscopie", + "fœtoscopies", + "fœtus", "fofolle", "foufou", "fofollement", @@ -261660,8 +261660,8 @@ "framboesias", "framboeside", "framboesides", - "framboesome", - "framboesomes", + "frambœsome", + "frambœsomes", "framboisa", "framboiser", "framboisai", @@ -294620,16 +294620,16 @@ "hypernéphromes", "hyperoctanoatémie", "hyperoctanoatémies", - "hyperoestrogénie", - "hyperoestrogénies", - "hyperoestrogénisme", - "hyperoestrogénismes", - "hyperoestrogénémie", - "hyperoestrogénémies", - "hyperoestroïdie", - "hyperoestroïdies", - "hyperoestroïdurie", - "hyperoestroïduries", + "hyperœstrogénie", + "hyperœstrogénies", + "hyperœstrogénisme", + "hyperœstrogénismes", + "hyperœstrogénémie", + "hyperœstrogénémies", + "hyperœstroïdie", + "hyperœstroïdies", + "hyperœstroïdurie", + "hyperœstroïduries", "hyperolius", "hyperonyme", "hyperonymes", @@ -312607,7 +312607,7 @@ "interoculaires", "interocéanique", "interocéaniques", - "interoestrus", + "interœstrus", "interolivaire", "interolivaires", "interoperculaire", @@ -334225,8 +334225,8 @@ "lymphodermies", "lymphodialyse", "lymphodialyses", - "lymphoedème", - "lymphoedèmes", + "lymphœdème", + "lymphœdèmes", "lymphogenèse", "lymphogenèses", "lymphogonie", @@ -339671,56 +339671,56 @@ "manodétendeurs", "manodétenteur", "manodétenteurs", - "manoeuvra", - "manoeuvrer", - "manoeuvrabilité", - "manoeuvrabilités", - "manoeuvrable", - "manoeuvrables", - "manoeuvrai", - "manoeuvraient", - "manoeuvrais", - "manoeuvrait", - "manoeuvrant", - "manoeuvrante", - "manoeuvrantes", - "manoeuvrants", - "manoeuvras", - "manoeuvrasse", - "manoeuvrassent", - "manoeuvrasses", - "manoeuvrassiez", - "manoeuvrassions", - "manoeuvre", - "manoeuvrent", - "manoeuvrera", - "manoeuvrerai", - "manoeuvreraient", - "manoeuvrerais", - "manoeuvrerait", - "manoeuvreras", - "manoeuvrerez", - "manoeuvreriez", - "manoeuvrerions", - "manoeuvrerons", - "manoeuvreront", - "manoeuvres", - "manoeuvrez", - "manoeuvrier", - "manoeuvriers", - "manoeuvriez", - "manoeuvrions", - "manoeuvrière", - "manoeuvrières", - "manoeuvrons", - "manoeuvrâmes", - "manoeuvrât", - "manoeuvrâtes", - "manoeuvrèrent", - "manoeuvré", - "manoeuvrée", - "manoeuvrées", - "manoeuvrés", + "manœuvra", + "manœuvrer", + "manœuvrabilité", + "manœuvrabilités", + "manœuvrable", + "manœuvrables", + "manœuvrai", + "manœuvraient", + "manœuvrais", + "manœuvrait", + "manœuvrant", + "manœuvrante", + "manœuvrantes", + "manœuvrants", + "manœuvras", + "manœuvrasse", + "manœuvrassent", + "manœuvrasses", + "manœuvrassiez", + "manœuvrassions", + "manœuvre", + "manœuvrent", + "manœuvrera", + "manœuvrerai", + "manœuvreraient", + "manœuvrerais", + "manœuvrerait", + "manœuvreras", + "manœuvrerez", + "manœuvreriez", + "manœuvrerions", + "manœuvrerons", + "manœuvreront", + "manœuvres", + "manœuvrez", + "manœuvrier", + "manœuvriers", + "manœuvriez", + "manœuvrions", + "manœuvrière", + "manœuvrières", + "manœuvrons", + "manœuvrâmes", + "manœuvrât", + "manœuvrâtes", + "manœuvrèrent", + "manœuvré", + "manœuvrée", + "manœuvrées", + "manœuvrés", "manographe", "manographes", "manographie", @@ -344634,7 +344634,7 @@ "melette", "melettes", "melianthus", - "meliboeus", + "melibœus", "melitta", "melkite", "melkites", @@ -350833,7 +350833,7 @@ "moeres", "moeritherium", "moeritheriums", - "moeurs", + "mœurs", "mofette", "mofettes", "moffla", @@ -359319,8 +359319,8 @@ "myomètres", "myonécrose", "myonécroses", - "myooedème", - "myooedèmes", + "myoœdème", + "myoœdèmes", "myopathe", "myopathes", "myopathia", @@ -359842,11 +359842,11 @@ "myxobactériées", "myxochondrome", "myxochondromes", - "myxoedème", - "myxoedèmes", - "myxoedémateuse", - "myxoedémateux", - "myxoedémateuses", + "myxœdème", + "myxœdèmes", + "myxœdémateuse", + "myxœdémateux", + "myxœdémateuses", "myxomatose", "myxomatoses", "myxome", @@ -369273,8 +369273,8 @@ "nodulose", "noduloses", "nodus", - "noeud", - "noeuds", + "nœud", + "nœuds", "noie", "noyer", "noient", @@ -375274,458 +375274,458 @@ "odyssées", "odéon", "odéons", - "oecanthe", - "oecanthes", - "oecologie", - "oecologies", - "oecologique", - "oecologiques", - "oecophylle", - "oecophylles", - "oecuménicité", - "oecuménicités", - "oecuménique", - "oecuméniquement", - "oecuméniques", - "oecuménisme", - "oecuménismes", - "oecuméniste", - "oecuménistes", - "oeda", - "oedas", - "oedicnème", - "oedicnèmes", - "oedipe", - "oedipianisa", - "oedipianiser", - "oedipianisai", - "oedipianisaient", - "oedipianisais", - "oedipianisait", - "oedipianisant", - "oedipianisas", - "oedipianisasse", - "oedipianisassent", - "oedipianisasses", - "oedipianisassiez", - "oedipianisassions", - "oedipianisation", - "oedipianisations", - "oedipianise", - "oedipianisent", - "oedipianisera", - "oedipianiserai", - "oedipianiseraient", - "oedipianiserais", - "oedipianiserait", - "oedipianiseras", - "oedipianiserez", - "oedipianiseriez", - "oedipianiserions", - "oedipianiserons", - "oedipianiseront", - "oedipianises", - "oedipianisez", - "oedipianisiez", - "oedipianisions", - "oedipianisons", - "oedipianisâmes", - "oedipianisât", - "oedipianisâtes", - "oedipianisèrent", - "oedipianisé", - "oedipianisée", - "oedipianisées", - "oedipianisés", - "oedipien", - "oedipienne", - "oedipiennes", - "oedipiens", - "oedipisme", - "oedipismes", - "oedipode", - "oedipodes", - "oedomètre", - "oedomètres", - "oedométrie", - "oedométries", - "oedométrique", - "oedométriques", - "oedème", - "oedèmes", - "oedémagène", - "oedémagènes", - "oedémateuse", - "oedémateux", - "oedémateuses", - "oedématia", - "oedématier", - "oedématiai", - "oedématiaient", - "oedématiais", - "oedématiait", - "oedématiant", - "oedématias", - "oedématiasse", - "oedématiassent", - "oedématiasses", - "oedématiassiez", - "oedématiassions", - "oedématie", - "oedématient", - "oedématiera", - "oedématierai", - "oedématieraient", - "oedématierais", - "oedématierait", - "oedématieras", - "oedématierez", - "oedématieriez", - "oedématierions", - "oedématierons", - "oedématieront", - "oedématies", - "oedématiez", - "oedématiiez", - "oedématiions", - "oedémations", - "oedématisa", - "oedématiser", - "oedématisai", - "oedématisaient", - "oedématisais", - "oedématisait", - "oedématisant", - "oedématisas", - "oedématisasse", - "oedématisassent", - "oedématisasses", - "oedématisassiez", - "oedématisassions", - "oedématise", - "oedématisent", - "oedématisera", - "oedématiserai", - "oedématiseraient", - "oedématiserais", - "oedématiserait", - "oedématiseras", - "oedématiserez", - "oedématiseriez", - "oedématiserions", - "oedématiserons", - "oedématiseront", - "oedématises", - "oedématisez", - "oedématisiez", - "oedématisions", - "oedématisons", - "oedématisâmes", - "oedématisât", - "oedématisâtes", - "oedématisèrent", - "oedématisé", - "oedématisée", - "oedématisées", - "oedématisés", - "oedématiâmes", - "oedématiât", - "oedématiâtes", - "oedématièrent", - "oedématié", - "oedématiée", - "oedématiées", - "oedématiés", - "oeil", - "oeillada", - "oeillader", - "oeilladai", - "oeilladaient", - "oeilladais", - "oeilladait", - "oeilladant", - "oeilladas", - "oeilladasse", - "oeilladassent", - "oeilladasses", - "oeilladassiez", - "oeilladassions", - "oeillade", - "oeilladent", - "oeilladera", - "oeilladerai", - "oeilladeraient", - "oeilladerais", - "oeilladerait", - "oeilladeras", - "oeilladerez", - "oeilladeriez", - "oeilladerions", - "oeilladerons", - "oeilladeront", - "oeillades", - "oeilladez", - "oeilladiez", - "oeilladions", - "oeilladons", - "oeilladâmes", - "oeilladât", - "oeilladâtes", - "oeilladèrent", - "oeilladé", - "oeilladée", - "oeilladées", - "oeilladés", - "oeillard", - "oeillards", - "oeillet", - "oeilleteuse", - "oeilleteuses", - "oeilleton", - "oeilletonna", - "oeilletonner", - "oeilletonnage", - "oeilletonnages", - "oeilletonnai", - "oeilletonnaient", - "oeilletonnais", - "oeilletonnait", - "oeilletonnant", - "oeilletonnas", - "oeilletonnasse", - "oeilletonnassent", - "oeilletonnasses", - "oeilletonnassiez", - "oeilletonnassions", - "oeilletonne", - "oeilletonnent", - "oeilletonnera", - "oeilletonnerai", - "oeilletonneraient", - "oeilletonnerais", - "oeilletonnerait", - "oeilletonneras", - "oeilletonnerez", - "oeilletonneriez", - "oeilletonnerions", - "oeilletonnerons", - "oeilletonneront", - "oeilletonnes", - "oeilletonnez", - "oeilletonniez", - "oeilletonnions", - "oeilletonnons", - "oeilletonnâmes", - "oeilletonnât", - "oeilletonnâtes", - "oeilletonnèrent", - "oeilletonné", - "oeilletonnée", - "oeilletonnées", - "oeilletonnés", - "oeilletons", - "oeillets", - "oeillette", - "oeillettes", - "oeillère", - "oeillères", - "oeillé", - "oeillée", - "oeillées", - "oeillés", - "oeils", - "oekoumène", - "oekoumènes", - "oenanthal", - "oenanthals", - "oenanthe", - "oenanthes", - "oenanthique", - "oenanthiques", - "oenanthylique", - "oenanthyliques", - "oeneis", - "oenilisme", - "oenilismes", - "oenistéries", - "oenochoé", - "oenochoés", - "oenolature", - "oenolatures", - "oenolique", - "oenoliques", - "oenolisme", - "oenolismes", - "oenologie", - "oenologies", - "oenologique", - "oenologiquement", - "oenologiques", - "oenologue", - "oenologues", - "oenolé", - "oenolés", - "oenomancie", - "oenomancies", - "oenomanie", - "oenomanies", - "oenomètre", - "oenomètres", - "oenométrie", - "oenométries", - "oenométrique", - "oenométriques", - "oenotechnie", - "oenotechnies", - "oenothera", - "oenotheras", - "oenothèque", - "oenothèques", - "oenothère", - "oenothères", - "oenothéracée", - "oenothéracées", - "oersted", - "oersteds", - "oerstite", - "oerstites", - "oesocardiogramme", - "oesocardiogrammes", - "oesoduodénostomie", - "oesoduodénostomies", - "oesofibroscope", - "oesofibroscopes", - "oesofibroscopie", - "oesofibroscopies", - "oesogastroduodénofibroscopie", - "oesogastroduodénofibroscopies", - "oesogastroduodénoscopie", - "oesogastroduodénoscopies", - "oesogastrostomie", - "oesogastrostomies", - "oesojéjunostomie", - "oesojéjunostomies", - "oesophage", - "oesophagectomie", - "oesophagectomies", - "oesophages", - "oesophagien", - "oesophagienne", - "oesophagiennes", - "oesophagiens", - "oesophagique", - "oesophagiques", - "oesophagisme", - "oesophagismes", - "oesophagite", - "oesophagites", - "oesophago", - "oesophagofibroscope", - "oesophagofibroscopes", - "oesophagofibroscopie", - "oesophagofibroscopies", - "oesophagomalacie", - "oesophagomalacies", - "oesophagoplastie", - "oesophagoplasties", - "oesophagorragie", - "oesophagorragies", - "oesophagoscope", - "oesophagoscopes", - "oesophagoscopie", - "oesophagoscopies", - "oesophagostomie", - "oesophagostomies", - "oesophagotomie", - "oesophagotomies", - "oesophagotubage", - "oesophagotubages", - "oestradiol", - "oestradiols", - "oestradiolémie", - "oestradiolémies", - "oestral", - "oestrale", - "oestrales", - "oestrane", - "oestranediol", - "oestranediols", - "oestranes", - "oestraux", - "oestre", - "oestres", - "oestridé", - "oestridés", - "oestrien", - "oestrienne", - "oestriennes", - "oestriens", - "oestriol", - "oestriols", - "oestro", - "oestrogène", - "oestrogènes", - "oestrogénie", - "oestrogénies", - "oestrogénique", - "oestrogéniques", - "oestrogénothérapie", - "oestrogénothérapies", - "oestrone", - "oestrones", - "oestroprogestatif", - "oestroprogestatifs", - "oestroprogestative", - "oestroprogestatives", - "oestroïde", - "oestroïdes", - "oestroïdurie", - "oestroïduries", - "oestrus", - "oeuf", - "oeufrier", - "oeufriers", - "oeufs", - "oeuvra", - "oeuvrer", - "oeuvrai", - "oeuvraient", - "oeuvrais", - "oeuvrait", - "oeuvrant", - "oeuvras", - "oeuvrasse", - "oeuvrassent", - "oeuvrasses", - "oeuvrassiez", - "oeuvrassions", - "oeuvre", - "oeuvrent", - "oeuvrera", - "oeuvrerai", - "oeuvreraient", - "oeuvrerais", - "oeuvrerait", - "oeuvreras", - "oeuvrerez", - "oeuvreriez", - "oeuvrerions", - "oeuvrerons", - "oeuvreront", - "oeuvres", - "oeuvrez", - "oeuvriez", - "oeuvrions", - "oeuvrons", - "oeuvrâmes", - "oeuvrât", - "oeuvrâtes", - "oeuvrèrent", - "oeuvré", - "oeuvé", - "oeuvée", - "oeuvées", - "oeuvés", + "œcanthe", + "œcanthes", + "œcologie", + "œcologies", + "œcologique", + "œcologiques", + "œcophylle", + "œcophylles", + "œcuménicité", + "œcuménicités", + "œcuménique", + "œcuméniquement", + "œcuméniques", + "œcuménisme", + "œcuménismes", + "œcuméniste", + "œcuménistes", + "œda", + "œdas", + "œdicnème", + "œdicnèmes", + "œdipe", + "œdipianisa", + "œdipianiser", + "œdipianisai", + "œdipianisaient", + "œdipianisais", + "œdipianisait", + "œdipianisant", + "œdipianisas", + "œdipianisasse", + "œdipianisassent", + "œdipianisasses", + "œdipianisassiez", + "œdipianisassions", + "œdipianisation", + "œdipianisations", + "œdipianise", + "œdipianisent", + "œdipianisera", + "œdipianiserai", + "œdipianiseraient", + "œdipianiserais", + "œdipianiserait", + "œdipianiseras", + "œdipianiserez", + "œdipianiseriez", + "œdipianiserions", + "œdipianiserons", + "œdipianiseront", + "œdipianises", + "œdipianisez", + "œdipianisiez", + "œdipianisions", + "œdipianisons", + "œdipianisâmes", + "œdipianisât", + "œdipianisâtes", + "œdipianisèrent", + "œdipianisé", + "œdipianisée", + "œdipianisées", + "œdipianisés", + "œdipien", + "œdipienne", + "œdipiennes", + "œdipiens", + "œdipisme", + "œdipismes", + "œdipode", + "œdipodes", + "œdomètre", + "œdomètres", + "œdométrie", + "œdométries", + "œdométrique", + "œdométriques", + "œdème", + "œdèmes", + "œdémagène", + "œdémagènes", + "œdémateuse", + "œdémateux", + "œdémateuses", + "œdématia", + "œdématier", + "œdématiai", + "œdématiaient", + "œdématiais", + "œdématiait", + "œdématiant", + "œdématias", + "œdématiasse", + "œdématiassent", + "œdématiasses", + "œdématiassiez", + "œdématiassions", + "œdématie", + "œdématient", + "œdématiera", + "œdématierai", + "œdématieraient", + "œdématierais", + "œdématierait", + "œdématieras", + "œdématierez", + "œdématieriez", + "œdématierions", + "œdématierons", + "œdématieront", + "œdématies", + "œdématiez", + "œdématiiez", + "œdématiions", + "œdémations", + "œdématisa", + "œdématiser", + "œdématisai", + "œdématisaient", + "œdématisais", + "œdématisait", + "œdématisant", + "œdématisas", + "œdématisasse", + "œdématisassent", + "œdématisasses", + "œdématisassiez", + "œdématisassions", + "œdématise", + "œdématisent", + "œdématisera", + "œdématiserai", + "œdématiseraient", + "œdématiserais", + "œdématiserait", + "œdématiseras", + "œdématiserez", + "œdématiseriez", + "œdématiserions", + "œdématiserons", + "œdématiseront", + "œdématises", + "œdématisez", + "œdématisiez", + "œdématisions", + "œdématisons", + "œdématisâmes", + "œdématisât", + "œdématisâtes", + "œdématisèrent", + "œdématisé", + "œdématisée", + "œdématisées", + "œdématisés", + "œdématiâmes", + "œdématiât", + "œdématiâtes", + "œdématièrent", + "œdématié", + "œdématiée", + "œdématiées", + "œdématiés", + "œil", + "œillada", + "œillader", + "œilladai", + "œilladaient", + "œilladais", + "œilladait", + "œilladant", + "œilladas", + "œilladasse", + "œilladassent", + "œilladasses", + "œilladassiez", + "œilladassions", + "œillade", + "œilladent", + "œilladera", + "œilladerai", + "œilladeraient", + "œilladerais", + "œilladerait", + "œilladeras", + "œilladerez", + "œilladeriez", + "œilladerions", + "œilladerons", + "œilladeront", + "œillades", + "œilladez", + "œilladiez", + "œilladions", + "œilladons", + "œilladâmes", + "œilladât", + "œilladâtes", + "œilladèrent", + "œilladé", + "œilladée", + "œilladées", + "œilladés", + "œillard", + "œillards", + "œillet", + "œilleteuse", + "œilleteuses", + "œilleton", + "œilletonna", + "œilletonner", + "œilletonnage", + "œilletonnages", + "œilletonnai", + "œilletonnaient", + "œilletonnais", + "œilletonnait", + "œilletonnant", + "œilletonnas", + "œilletonnasse", + "œilletonnassent", + "œilletonnasses", + "œilletonnassiez", + "œilletonnassions", + "œilletonne", + "œilletonnent", + "œilletonnera", + "œilletonnerai", + "œilletonneraient", + "œilletonnerais", + "œilletonnerait", + "œilletonneras", + "œilletonnerez", + "œilletonneriez", + "œilletonnerions", + "œilletonnerons", + "œilletonneront", + "œilletonnes", + "œilletonnez", + "œilletonniez", + "œilletonnions", + "œilletonnons", + "œilletonnâmes", + "œilletonnât", + "œilletonnâtes", + "œilletonnèrent", + "œilletonné", + "œilletonnée", + "œilletonnées", + "œilletonnés", + "œilletons", + "œillets", + "œillette", + "œillettes", + "œillère", + "œillères", + "œillé", + "œillée", + "œillées", + "œillés", + "œils", + "œkoumène", + "œkoumènes", + "œnanthal", + "œnanthals", + "œnanthe", + "œnanthes", + "œnanthique", + "œnanthiques", + "œnanthylique", + "œnanthyliques", + "œneis", + "œnilisme", + "œnilismes", + "œnistéries", + "œnochoé", + "œnochoés", + "œnolature", + "œnolatures", + "œnolique", + "œnoliques", + "œnolisme", + "œnolismes", + "œnologie", + "œnologies", + "œnologique", + "œnologiquement", + "œnologiques", + "œnologue", + "œnologues", + "œnolé", + "œnolés", + "œnomancie", + "œnomancies", + "œnomanie", + "œnomanies", + "œnomètre", + "œnomètres", + "œnométrie", + "œnométries", + "œnométrique", + "œnométriques", + "œnotechnie", + "œnotechnies", + "œnothera", + "œnotheras", + "œnothèque", + "œnothèques", + "œnothère", + "œnothères", + "œnothéracée", + "œnothéracées", + "œrsted", + "œrsteds", + "œrstite", + "œrstites", + "œsocardiogramme", + "œsocardiogrammes", + "œsoduodénostomie", + "œsoduodénostomies", + "œsofibroscope", + "œsofibroscopes", + "œsofibroscopie", + "œsofibroscopies", + "œsogastroduodénofibroscopie", + "œsogastroduodénofibroscopies", + "œsogastroduodénoscopie", + "œsogastroduodénoscopies", + "œsogastrostomie", + "œsogastrostomies", + "œsojéjunostomie", + "œsojéjunostomies", + "œsophage", + "œsophagectomie", + "œsophagectomies", + "œsophages", + "œsophagien", + "œsophagienne", + "œsophagiennes", + "œsophagiens", + "œsophagique", + "œsophagiques", + "œsophagisme", + "œsophagismes", + "œsophagite", + "œsophagites", + "œsophago", + "œsophagofibroscope", + "œsophagofibroscopes", + "œsophagofibroscopie", + "œsophagofibroscopies", + "œsophagomalacie", + "œsophagomalacies", + "œsophagoplastie", + "œsophagoplasties", + "œsophagorragie", + "œsophagorragies", + "œsophagoscope", + "œsophagoscopes", + "œsophagoscopie", + "œsophagoscopies", + "œsophagostomie", + "œsophagostomies", + "œsophagotomie", + "œsophagotomies", + "œsophagotubage", + "œsophagotubages", + "œstradiol", + "œstradiols", + "œstradiolémie", + "œstradiolémies", + "œstral", + "œstrale", + "œstrales", + "œstrane", + "œstranediol", + "œstranediols", + "œstranes", + "œstraux", + "œstre", + "œstres", + "œstridé", + "œstridés", + "œstrien", + "œstrienne", + "œstriennes", + "œstriens", + "œstriol", + "œstriols", + "œstro", + "œstrogène", + "œstrogènes", + "œstrogénie", + "œstrogénies", + "œstrogénique", + "œstrogéniques", + "œstrogénothérapie", + "œstrogénothérapies", + "œstrone", + "œstrones", + "œstroprogestatif", + "œstroprogestatifs", + "œstroprogestative", + "œstroprogestatives", + "œstroïde", + "œstroïdes", + "œstroïdurie", + "œstroïduries", + "œstrus", + "œuf", + "œufrier", + "œufriers", + "œufs", + "œuvra", + "œuvrer", + "œuvrai", + "œuvraient", + "œuvrais", + "œuvrait", + "œuvrant", + "œuvras", + "œuvrasse", + "œuvrassent", + "œuvrasses", + "œuvrassiez", + "œuvrassions", + "œuvre", + "œuvrent", + "œuvrera", + "œuvrerai", + "œuvreraient", + "œuvrerais", + "œuvrerait", + "œuvreras", + "œuvrerez", + "œuvreriez", + "œuvrerions", + "œuvrerons", + "œuvreront", + "œuvres", + "œuvrez", + "œuvriez", + "œuvrions", + "œuvrons", + "œuvrâmes", + "œuvrât", + "œuvrâtes", + "œuvrèrent", + "œuvré", + "œuvé", + "œuvée", + "œuvées", + "œuvés", "off", "offensa", "offenser", @@ -398081,8 +398081,8 @@ "phlébocavographies", "phlébodynie", "phlébodynies", - "phléboedème", - "phléboedèmes", + "phlébœdème", + "phlébœdèmes", "phlébogramme", "phlébogrammes", "phlébographie", @@ -398197,15 +398197,15 @@ "phocéenne", "phocéennes", "phocéens", - "phoenicochroïte", - "phoenicochroïtes", - "phoenicoptère", - "phoenicoptères", - "phoenicoptéridé", - "phoenicoptéridés", - "phoenicoptériforme", - "phoenicoptériformes", - "phoenix", + "phœnicochroïte", + "phœnicochroïtes", + "phœnicoptère", + "phœnicoptères", + "phœnicoptéridé", + "phœnicoptéridés", + "phœnicoptériforme", + "phœnicoptériformes", + "phœnix", "pholade", "pholades", "pholadomyie", @@ -425076,11 +425076,11 @@ "préoccupée", "préoccupées", "préoccupés", - "préoedipien", - "préoedipienne", - "préoedipiennes", - "préoedipiens", - "préoestrus", + "préœdipien", + "préœdipienne", + "préœdipiennes", + "préœdipiens", + "préœstrus", "préolympique", "préolympiques", "préoperculaire", @@ -427750,10 +427750,10 @@ "pseudocoarctation", "pseudocoarctations", "pseudococcus", - "pseudocoelomate", - "pseudocoelomates", - "pseudocoelome", - "pseudocoelomes", + "pseudocœlomate", + "pseudocœlomates", + "pseudocœlome", + "pseudocœlomes", "pseudocomitial", "pseudocomitiale", "pseudocomitiales", @@ -432912,8 +432912,8 @@ "périodisés", "périodontite", "périodontites", - "périoesophagite", - "périoesophagites", + "périœsophagite", + "périœsophagites", "périonyxis", "périophtalmite", "périophtalmites", @@ -441941,8 +441941,8 @@ "rancissure", "rancissures", "rancit", - "rancoeur", - "rancoeurs", + "rancœur", + "rancœurs", "rancune", "rancunes", "rancuneuse", @@ -475986,45 +475986,45 @@ "remaniée", "remaniées", "remaniés", - "remanoeuvra", - "remanoeuvrer", - "remanoeuvrai", - "remanoeuvraient", - "remanoeuvrais", - "remanoeuvrait", - "remanoeuvrant", - "remanoeuvras", - "remanoeuvrasse", - "remanoeuvrassent", - "remanoeuvrasses", - "remanoeuvrassiez", - "remanoeuvrassions", - "remanoeuvre", - "remanoeuvrent", - "remanoeuvrera", - "remanoeuvrerai", - "remanoeuvreraient", - "remanoeuvrerais", - "remanoeuvrerait", - "remanoeuvreras", - "remanoeuvrerez", - "remanoeuvreriez", - "remanoeuvrerions", - "remanoeuvrerons", - "remanoeuvreront", - "remanoeuvres", - "remanoeuvrez", - "remanoeuvriez", - "remanoeuvrions", - "remanoeuvrons", - "remanoeuvrâmes", - "remanoeuvrât", - "remanoeuvrâtes", - "remanoeuvrèrent", - "remanoeuvré", - "remanoeuvrée", - "remanoeuvrées", - "remanoeuvrés", + "remanœuvra", + "remanœuvrer", + "remanœuvrai", + "remanœuvraient", + "remanœuvrais", + "remanœuvrait", + "remanœuvrant", + "remanœuvras", + "remanœuvrasse", + "remanœuvrassent", + "remanœuvrasses", + "remanœuvrassiez", + "remanœuvrassions", + "remanœuvre", + "remanœuvrent", + "remanœuvrera", + "remanœuvrerai", + "remanœuvreraient", + "remanœuvrerais", + "remanœuvrerait", + "remanœuvreras", + "remanœuvrerez", + "remanœuvreriez", + "remanœuvrerions", + "remanœuvrerons", + "remanœuvreront", + "remanœuvres", + "remanœuvrez", + "remanœuvriez", + "remanœuvrions", + "remanœuvrons", + "remanœuvrâmes", + "remanœuvrât", + "remanœuvrâtes", + "remanœuvrèrent", + "remanœuvré", + "remanœuvrée", + "remanœuvrées", + "remanœuvrés", "remanqua", "remanquer", "remanquai", @@ -498886,8 +498886,8 @@ "rhabditidé", "rhabditidés", "rhabditis", - "rhabdocoele", - "rhabdocoeles", + "rhabdocœle", + "rhabdocœles", "rhabdologie", "rhabdologies", "rhabdomancie", @@ -499189,10 +499189,10 @@ "rhinocérotidés", "rhinoderme", "rhinodermes", - "rhinoedème", - "rhinoedèmes", - "rhinoestre", - "rhinoestres", + "rhinœdème", + "rhinœdèmes", + "rhinœstre", + "rhinœstres", "rhinoglanis", "rhinogène", "rhinogènes", @@ -499615,8 +499615,8 @@ "rhynchiums", "rhynchobdelle", "rhynchobdelles", - "rhynchocoele", - "rhynchocoeles", + "rhynchocœle", + "rhynchocœles", "rhynchocyon", "rhynchocyons", "rhynchocéphale", @@ -506177,8 +506177,8 @@ "rydbergs", "rynchite", "rynchites", - "rynchocoele", - "rynchocoeles", + "rynchocœle", + "rynchocœles", "rynchote", "rynchotes", "ryssota", @@ -536072,8 +536072,8 @@ "schistoïde", "schistoïdes", "schizo", - "schizocoelie", - "schizocoelies", + "schizocœlie", + "schizocœlies", "schizocyte", "schizocytes", "schizocytose", @@ -537104,8 +537104,8 @@ "sclérodermies", "sclérodermiforme", "sclérodermiformes", - "scléroedème", - "scléroedèmes", + "sclérœdème", + "sclérœdèmes", "sclérogène", "sclérogènes", "sclérokératite", @@ -544674,10 +544674,10 @@ "sodée", "sodées", "sodés", - "soeur", - "soeurette", - "soeurettes", - "soeurs", + "sœur", + "sœurette", + "sœurettes", + "sœurs", "sofa", "sofas", "soffie", @@ -552115,8 +552115,8 @@ "stilb", "stilbite", "stilbites", - "stilboestrol", - "stilboestrols", + "stilbœstrol", + "stilbœstrols", "stilbs", "stilbène", "stilbènes", @@ -584749,10 +584749,10 @@ "transocéaniens", "transocéanique", "transocéaniques", - "transoesophagien", - "transoesophagienne", - "transoesophagiennes", - "transoesophagiens", + "transœsophagien", + "transœsophagienne", + "transœsophagiennes", + "transœsophagiens", "transombilical", "transombilicale", "transombilicales", @@ -589525,8 +589525,8 @@ "trophoblastomes", "trophodermatoneurose", "trophodermatoneuroses", - "trophoedème", - "trophoedèmes", + "trophœdème", + "trophœdèmes", "trophoneurotique", "trophoneurotiques", "trophonose", @@ -593146,8 +593146,8 @@ "typo", "typochromie", "typochromies", - "typocoelographie", - "typocoelographies", + "typocœlographie", + "typocœlographies", "typographe", "typographes", "typographia", @@ -606230,8 +606230,8 @@ "vocodeurs", "vodka", "vodkas", - "voeu", - "voeux", + "vœu", + "vœux", "voglite", "voglites", "vogoul", @@ -609553,8 +609553,8 @@ "xéno", "xénobiotique", "xénobiotiques", - "xénocoeloma", - "xénocoelomas", + "xénocœloma", + "xénocœlomas", "xénocristal", "xénocristaux", "xénoderminé", @@ -616331,50 +616331,50 @@ "écoclimatologies", "écocline", "écoclines", - "écoeura", - "écoeurer", - "écoeurai", - "écoeuraient", - "écoeurais", - "écoeurait", - "écoeurant", - "écoeurante", - "écoeurantes", - "écoeurants", - "écoeuras", - "écoeurasse", - "écoeurassent", - "écoeurasses", - "écoeurassiez", - "écoeurassions", - "écoeure", - "écoeurement", - "écoeurements", - "écoeurent", - "écoeurera", - "écoeurerai", - "écoeureraient", - "écoeurerais", - "écoeurerait", - "écoeureras", - "écoeurerez", - "écoeureriez", - "écoeurerions", - "écoeurerons", - "écoeureront", - "écoeures", - "écoeurez", - "écoeuriez", - "écoeurions", - "écoeurons", - "écoeurâmes", - "écoeurât", - "écoeurâtes", - "écoeurèrent", - "écoeuré", - "écoeurée", - "écoeurées", - "écoeurés", + "écœura", + "écœurer", + "écœurai", + "écœuraient", + "écœurais", + "écœurait", + "écœurant", + "écœurante", + "écœurantes", + "écœurants", + "écœuras", + "écœurasse", + "écœurassent", + "écœurasses", + "écœurassiez", + "écœurassions", + "écœure", + "écœurement", + "écœurements", + "écœurent", + "écœurera", + "écœurerai", + "écœureraient", + "écœurerais", + "écœurerait", + "écœureras", + "écœurerez", + "écœureriez", + "écœurerions", + "écœurerons", + "écœureront", + "écœures", + "écœurez", + "écœuriez", + "écœurions", + "écœurons", + "écœurâmes", + "écœurât", + "écœurâtes", + "écœurèrent", + "écœuré", + "écœurée", + "écœurées", + "écœurés", "écoffret", "écoffrets", "écographie", @@ -629714,8 +629714,8 @@ "érythrodiapédèses", "érythrodontie", "érythrodonties", - "érythroedème", - "érythroedèmes", + "érythrœdème", + "érythrœdèmes", "érythroenzymopathie", "érythroenzymopathies", "érythrogène", From 0a4043de458f238a91132863dd69dd0bf9dc8cbd Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Wed, 26 Nov 2025 23:03:52 +0100 Subject: [PATCH 09/15] impr: validate username on profile search page (@fehmer) (#7132) fixes #7131 --- .../controllers/profile-search-controller.ts | 79 ------------------- .../src/ts/controllers/route-controller.ts | 5 ++ frontend/src/ts/index.ts | 1 - .../src/ts/observables/navigation-event.ts | 23 ++++++ frontend/src/ts/pages/profile-search.ts | 66 +++++++++++++++- 5 files changed, 93 insertions(+), 81 deletions(-) delete mode 100644 frontend/src/ts/controllers/profile-search-controller.ts create mode 100644 frontend/src/ts/observables/navigation-event.ts diff --git a/frontend/src/ts/controllers/profile-search-controller.ts b/frontend/src/ts/controllers/profile-search-controller.ts deleted file mode 100644 index 2294d634eb98..000000000000 --- a/frontend/src/ts/controllers/profile-search-controller.ts +++ /dev/null @@ -1,79 +0,0 @@ -import { InputIndicator } from "../elements/input-indicator"; -import { sleep } from "../utils/misc"; -import Ape from "../ape"; -import { navigate } from "../controllers/route-controller"; -import * as Skeleton from "../utils/skeleton"; - -const searchIndicator = new InputIndicator( - $(".page.pageProfileSearch .search input"), - { - notFound: { - icon: "fa-user-slash", - level: -1, - }, - error: { - icon: "fa-times", - level: -1, - }, - checking: { - icon: "fa-circle-notch", - spinIcon: true, - level: 1, - }, - } -); - -function disableInputs(): void { - $(".page.pageProfileSearch .search button").addClass("disabled"); - $(".page.pageProfileSearch .search input").attr("disabled", "disabled"); -} - -function enableInputs(): void { - $(".page.pageProfileSearch .search button").removeClass("disabled"); - $(".page.pageProfileSearch .search input").removeAttr("disabled"); -} - -function areInputsDisabled(): boolean { - return ( - $(".page.pageProfileSearch .search input").attr("disabled") !== undefined - ); -} - -function focusInput(): void { - $(".page.pageProfileSearch .search input").trigger("focus"); -} - -async function lookupProfile(): Promise { - searchIndicator.hide(); - const name = $(".page.pageProfileSearch .search input").val() as string; - if (name === "") return; - - searchIndicator.show("checking"); - disableInputs(); - - await sleep(500); - - const response = await Ape.users.getProfile({ params: { uidOrName: name } }); - enableInputs(); - if (response.status === 404) { - focusInput(); - searchIndicator.show("notFound", "User not found"); - return; - } else if (response.status !== 200) { - focusInput(); - searchIndicator.show("error", `Error: ${response.body.message}`); - return; - } - searchIndicator.hide(); - await navigate(`/profile/${name}`, { - data: response.body.data, - }); -} - -$(".page.pageProfileSearch form").on("submit", (e) => { - e.preventDefault(); - if (areInputsDisabled()) return; - void lookupProfile(); -}); - -Skeleton.save("pageProfileSearch"); diff --git a/frontend/src/ts/controllers/route-controller.ts b/frontend/src/ts/controllers/route-controller.ts index 2c0eda4b504f..1aa6eab0af00 100644 --- a/frontend/src/ts/controllers/route-controller.ts +++ b/frontend/src/ts/controllers/route-controller.ts @@ -6,6 +6,7 @@ import { isFunboxActive } from "../test/funbox/list"; import * as TestState from "../test/test-state"; import * as Notifications from "../elements/notifications"; import { LoadingOptions } from "../pages/page"; +import * as NavigationEvent from "../observables/navigation-event"; //source: https://www.youtube.com/watch?v=OstALBk-jTc // https://www.youtube.com/watch?v=OstALBk-jTc @@ -249,3 +250,7 @@ document.addEventListener("DOMContentLoaded", () => { } }); }); + +NavigationEvent.subscribe((it) => { + void navigate(it.url, { data: it.data }); +}); diff --git a/frontend/src/ts/index.ts b/frontend/src/ts/index.ts index d2d9f2dc5cc0..17167bb2f56a 100644 --- a/frontend/src/ts/index.ts +++ b/frontend/src/ts/index.ts @@ -37,7 +37,6 @@ import { egVideoListener } from "./popups/video-ad-popup"; import "./states/connection"; import "./test/tts"; import "./elements/fps-counter"; -import "./controllers/profile-search-controller"; import { isDevEnvironment, addToGlobal } from "./utils/misc"; import * as VersionButton from "./elements/version-button"; import * as Focus from "./test/focus"; diff --git a/frontend/src/ts/observables/navigation-event.ts b/frontend/src/ts/observables/navigation-event.ts new file mode 100644 index 000000000000..42241636204f --- /dev/null +++ b/frontend/src/ts/observables/navigation-event.ts @@ -0,0 +1,23 @@ +type NavigationEvent = { + url: string; + data?: unknown; +}; + +type SubscribeFunction = (event: NavigationEvent) => void; + +const subscribers: SubscribeFunction[] = []; + +export function subscribe(fn: SubscribeFunction): void { + subscribers.push(fn); +} + +export function dispatch(event: NavigationEvent): void { + subscribers.forEach((fn) => { + try { + fn(event); + } catch (e) { + console.error("Navigation event subscriber threw an error"); + console.error(e); + } + }); +} diff --git a/frontend/src/ts/pages/profile-search.ts b/frontend/src/ts/pages/profile-search.ts index dcf52ea05c3a..7fea826ba13d 100644 --- a/frontend/src/ts/pages/profile-search.ts +++ b/frontend/src/ts/pages/profile-search.ts @@ -1,5 +1,24 @@ import Page from "./page"; import * as Skeleton from "../utils/skeleton"; +import Ape from "../ape"; +import { + ValidatedHtmlInputElement, + validateWithIndicator, +} from "../elements/input-validation"; +import { UserNameSchema, UserProfile } from "@monkeytype/schemas/users"; +import { remoteValidation } from "../utils/remote-validation"; +import * as NavigationEvent from "../observables/navigation-event"; + +let nameInputEl: ValidatedHtmlInputElement | null = null; +let lastProfile: UserProfile | null = null; + +function enableButton(): void { + $('.page.pageProfileSearch button[type="submit"]').prop("disabled", false); +} + +function disableButton(): void { + $('.page.pageProfileSearch button[type="submit"]').prop("disabled", true); +} export const page = new Page({ id: "profileSearch", @@ -10,9 +29,54 @@ export const page = new Page({ }, beforeShow: async (): Promise => { Skeleton.append("pageProfileSearch", "main"); - $(".page.pageProfileSearch input").val(""); + + if (nameInputEl === null) { + nameInputEl = validateWithIndicator( + document.querySelector( + ".page.pageProfileSearch input" + ) as HTMLInputElement, + { + schema: UserNameSchema, + isValid: remoteValidation( + async (name) => + Ape.users.getProfile({ params: { uidOrName: name } }), + { + check: (data) => { + lastProfile = data; + return true; + }, + on4xx: () => "Unknown user", + } + ), + callback: (result) => { + if (result.status === "success") { + enableButton(); + } else { + disableButton(); + lastProfile = null; + } + }, + } + ); + } + + nameInputEl.setValue(null); + disableButton(); }, afterShow: async (): Promise => { $(".page.pageProfileSearch input").trigger("focus"); }, }); + +$(".page.pageProfileSearch form").on("submit", (e) => { + e.preventDefault(); + if (lastProfile === null) return; + NavigationEvent.dispatch({ + url: `/profile/${lastProfile.name}`, + data: lastProfile, + }); +}); + +$(() => { + Skeleton.save("pageProfileSearch"); +}); From 14895f64a5449f714ed9d4b316f20ffefe627c68 Mon Sep 17 00:00:00 2001 From: GreenvillSSnick <135178228+GreenvillSSnick@users.noreply.github.com> Date: Wed, 26 Nov 2025 16:16:46 -0600 Subject: [PATCH 10/15] chore: add more words to hinglish language(hinglish.json) (@GreenvillSSnick) (#7138) ### Description I added some new words to /frontend/static/languages/hinglish.json Translations: barre: outside durghatana: accident oopar: above sabse: most sveekaar: accept ### Checks - [ ] Adding quotes? - [ ] Make sure to include translations for the quotes in the description (or another comment) so we can verify their content. - [ ] Adding a language? - Make sure to follow the [languages documentation](https://github.com/monkeytypegame/monkeytype/blob/master/docs/LANGUAGES.md) - [] Add language to `packages/schemas/src/languages.ts` - [ ] Add language to exactly one group in `frontend/src/ts/constants/languages.ts` - [ ] Add language json file to `frontend/static/languages` - [ ] Adding a theme? - Make sure to follow the [themes documentation](https://github.com/monkeytypegame/monkeytype/blob/master/docs/THEMES.md) - [ ] Add theme to `packages/schemas/src/themes.ts` - [ ] Add theme to `frontend/src/ts/constants/themes.ts` - [ ] Add theme css file to `frontend/static/themes` - [ ] Add some screenshot of the theme, especially with different test settings (colorful, flip colors) to your pull request - [ ] Adding a layout? - [ ] Make sure to follow the [layouts documentation](https://github.com/monkeytypegame/monkeytype/blob/master/docs/LAYOUTS.md) - [ ] Add layout to `packages/schemas/src/layouts.ts` - [ ] Add layout json file to `frontend/static/layouts` - [ ] Adding a font? - Make sure to follow the [themes documentation](https://github.com/monkeytypegame/monkeytype/blob/master/docs/FONTS.md) - [ ] Add font file to `frontend/static/webfonts` - [ ] Add font to `packages/schemas/src/fonts.ts` - [ ] Add font to `frontend/src/ts/constants/fonts.ts` - [x] Check if any open issues are related to this PR; if so, be sure to tag them below. - [x] Make sure the PR title follows the Conventional Commits standard. (https://www.conventionalcommits.org for more info) - [x] Make sure to include your GitHub username prefixed with @ inside parentheses at the end of the PR title. --- frontend/static/languages/hinglish.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/frontend/static/languages/hinglish.json b/frontend/static/languages/hinglish.json index 1856f9158153..a7d68fc7d527 100644 --- a/frontend/static/languages/hinglish.json +++ b/frontend/static/languages/hinglish.json @@ -19,6 +19,7 @@ "aur", "baad", "baar", + "barre", "baate", "bach", "bachchha", @@ -59,6 +60,7 @@ "dost", "dunga", "duniya", + "durghatana", "dusht", "dusman", "dusra", @@ -142,6 +144,7 @@ "nahi", "nazar", "neend", + "oopar", "paani", "pada", "padh", @@ -159,6 +162,7 @@ "pyaar", "roshan", "saal", + "sabse", "sach", "sahi", "se", @@ -167,6 +171,7 @@ "sona", "sun", "shuru", + "sveekaar", "tab", "tak", "taraf", From aafabeb78dcbd22688356fa77e58988ba64a7cb3 Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Wed, 26 Nov 2025 23:27:30 +0100 Subject: [PATCH 11/15] fix(friends): proper display of pending requests on small screens (@fehmer) (#7148) --- frontend/src/styles/media-queries-blue.scss | 3 ++- frontend/src/styles/media-queries-brown.scss | 5 +++++ frontend/src/styles/media-queries-yellow.scss | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/frontend/src/styles/media-queries-blue.scss b/frontend/src/styles/media-queries-blue.scss index 435c5352cdbe..529289c2eac6 100644 --- a/frontend/src/styles/media-queries-blue.scss +++ b/frontend/src/styles/media-queries-blue.scss @@ -245,7 +245,8 @@ } .pageFriends { - .content .friends table { + .content .friends table, + .content .pendingRequests table { font-size: 0.75rem; } } diff --git a/frontend/src/styles/media-queries-brown.scss b/frontend/src/styles/media-queries-brown.scss index 9fedfe9aeaca..8fdeb33500ef 100644 --- a/frontend/src/styles/media-queries-brown.scss +++ b/frontend/src/styles/media-queries-brown.scss @@ -107,6 +107,11 @@ display: none; } } + .content .pendingRequests table { + td:nth-child(2) { + display: none; + } + } } .pageAccountSettings [data-tab="blockedUsers"] { diff --git a/frontend/src/styles/media-queries-yellow.scss b/frontend/src/styles/media-queries-yellow.scss index 44d86b8d0d95..e3df58e2a8c4 100644 --- a/frontend/src/styles/media-queries-yellow.scss +++ b/frontend/src/styles/media-queries-yellow.scss @@ -91,7 +91,8 @@ } } .pageFriends { - .content .friends table { + .content .friends table, + .content .pendingRequests table { font-size: 0.9rem; .badge .text { From 227a52202495882f1715b85f588c2d517fd9aa65 Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Wed, 26 Nov 2025 23:28:39 +0100 Subject: [PATCH 12/15] refactor: use modern api for toggle fullscreen (@fehmer) (#7150) --- frontend/src/ts/utils/misc.ts | 49 +++-------------------------------- 1 file changed, 3 insertions(+), 46 deletions(-) diff --git a/frontend/src/ts/utils/misc.ts b/frontend/src/ts/utils/misc.ts index f4abae6998b5..2fbe06363193 100644 --- a/frontend/src/ts/utils/misc.ts +++ b/frontend/src/ts/utils/misc.ts @@ -112,54 +112,11 @@ export function objectToQueryString( return str.join("&"); } -declare global { - // type gets a "Duplicate identifier" error - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions - interface Document { - mozCancelFullScreen?: () => Promise; - msRequestFullscreen?: () => Promise; - msExitFullscreen?: () => Promise; - webkitExitFullscreen?: () => Promise; - mozFullScreenElement?: Element; - msFullscreenElement?: Element; - webkitFullscreenElement?: Element; - } - // eslint-disable-next-line @typescript-eslint/consistent-type-definitions - interface HTMLElement { - msRequestFullscreen?: () => Promise; - mozRequestFullScreen?: () => Promise; - webkitRequestFullscreen?: () => Promise; - } -} - export function toggleFullscreen(): void { - const elem = document.documentElement; - if ( - !document.fullscreenElement && - !document.mozFullScreenElement && - !document.webkitFullscreenElement && - !document.msFullscreenElement - ) { - if (elem.requestFullscreen !== undefined) { - void elem.requestFullscreen(); - } else if (elem.msRequestFullscreen) { - void elem.msRequestFullscreen(); - } else if (elem.mozRequestFullScreen) { - void elem.mozRequestFullScreen(); - } else if (elem.webkitRequestFullscreen) { - // @ts-expect-error some code i found online - void elem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); - } + if (!document.fullscreenElement) { + void document.documentElement.requestFullscreen(); } else { - if (document.exitFullscreen !== undefined) { - void document.exitFullscreen(); - } else if (document.msExitFullscreen) { - void document.msExitFullscreen(); - } else if (document.mozCancelFullScreen) { - void document.mozCancelFullScreen(); - } else if (document.webkitExitFullscreen) { - void document.webkitExitFullscreen(); - } + void document.exitFullscreen(); } } From 71b5d2215961888b4cc7f5a3d2f7d8c8a17eec57 Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Wed, 26 Nov 2025 23:29:57 +0100 Subject: [PATCH 13/15] refactor: Use class for validateWithIndicator (@fehmer) (#7151) In preparation for the ElementWithUtils refactoring --- frontend/src/ts/elements/input-validation.ts | 127 +++++++++--------- .../ts/elements/settings/fps-limit-section.ts | 12 +- frontend/src/ts/modals/edit-preset.ts | 13 +- frontend/src/ts/modals/google-sign-up.ts | 4 +- frontend/src/ts/modals/save-custom-text.ts | 4 +- frontend/src/ts/pages/login.ts | 22 +-- frontend/src/ts/utils/simple-modal.ts | 4 +- 7 files changed, 89 insertions(+), 97 deletions(-) diff --git a/frontend/src/ts/elements/input-validation.ts b/frontend/src/ts/elements/input-validation.ts index 5dce09c44705..277bcd8d37f5 100644 --- a/frontend/src/ts/elements/input-validation.ts +++ b/frontend/src/ts/elements/input-validation.ts @@ -142,80 +142,75 @@ export type ValidationOptions = (T extends string callback?: (result: ValidationResult) => void; }; -export type ValidatedHtmlInputElement = HTMLInputElement & { - getValidationResult: () => ValidationResult; - setValue: (val: string | null) => void; - triggerValidation: () => void; -}; -/** - * adds an 'InputIndicator` to the given `inputElement` and updates its status depending on the given validation - * @param inputElement - * @param options - */ -export function validateWithIndicator( - inputElement: HTMLInputElement, - options: ValidationOptions -): ValidatedHtmlInputElement { - //use indicator - const indicator = new InputIndicator(inputElement, { - success: { - icon: "fa-check", - level: 1, - }, - failed: { - icon: "fa-times", - level: -1, - }, - warning: { - icon: "fa-exclamation-triangle", - level: 1, - }, - checking: { - icon: "fa-circle-notch", - spinIcon: true, - level: 0, - }, - }); - - let currentStatus: ValidationResult = { +export class ValidatedHtmlInputElement { + public native: HTMLInputElement; + private indicator: InputIndicator; + private currentStatus: ValidationResult = { status: "checking", }; - const callback = (result: ValidationResult): void => { - currentStatus = result; - if (result.status === "failed" || result.status === "warning") { - indicator.show(result.status, result.errorMessage); - } else { - indicator.show(result.status); - } - options.callback?.(result); - }; - const handler = createInputEventHandler( - callback, - options, - "inputValueConvert" in options ? options.inputValueConvert : undefined - ); + constructor(inputElement: HTMLInputElement, options: ValidationOptions) { + this.native = inputElement; - inputElement.addEventListener("input", handler); + this.indicator = new InputIndicator(inputElement, { + success: { + icon: "fa-check", + level: 1, + }, + failed: { + icon: "fa-times", + level: -1, + }, + warning: { + icon: "fa-exclamation-triangle", + level: 1, + }, + checking: { + icon: "fa-circle-notch", + spinIcon: true, + level: 0, + }, + }); - const result = inputElement as ValidatedHtmlInputElement; - result.getValidationResult = () => { - return currentStatus; - }; - result.setValue = (val: string | null) => { - inputElement.value = val ?? ""; + const callback = (result: ValidationResult): void => { + this.currentStatus = result; + if (result.status === "failed" || result.status === "warning") { + this.indicator.show(result.status, result.errorMessage); + } else { + this.indicator.show(result.status); + } + options.callback?.(result); + }; + + const handler = createInputEventHandler( + callback, + options, + "inputValueConvert" in options ? options.inputValueConvert : undefined + ); + + inputElement.addEventListener("input", handler); + } + + getValidationResult(): ValidationResult { + return this.currentStatus; + } + setValue(val: string | null): this { + this.native.value = val ?? ""; if (val === null) { - indicator.hide(); - currentStatus = { status: "checking" }; + this.indicator.hide(); + this.currentStatus = { status: "checking" }; } else { - inputElement.dispatchEvent(new Event("input")); + this.native.dispatchEvent(new Event("input")); } - }; - result.triggerValidation = () => { - inputElement.dispatchEvent(new Event("input")); - }; - return result; + return this; + } + getValue(): string { + return this.native.value; + } + triggerValidation(): void { + this.native.dispatchEvent(new Event("input")); + } } export type ConfigInputOptions = { @@ -260,7 +255,7 @@ export function handleConfigInput({ if (validation !== undefined) { const schema = ConfigSchema.shape[configName] as ZodType; - validateWithIndicator(input, { + new ValidatedHtmlInputElement(input, { schema: validation.schema ? schema : undefined, //@ts-expect-error this is fine isValid: validation.isValid, diff --git a/frontend/src/ts/elements/settings/fps-limit-section.ts b/frontend/src/ts/elements/settings/fps-limit-section.ts index fb1b994121b3..1c0e52303fe0 100644 --- a/frontend/src/ts/elements/settings/fps-limit-section.ts +++ b/frontend/src/ts/elements/settings/fps-limit-section.ts @@ -1,5 +1,5 @@ import { getfpsLimit, fpsLimitSchema, setfpsLimit } from "../../anim"; -import { validateWithIndicator } from "../input-validation"; +import { ValidatedHtmlInputElement } from "../input-validation"; import * as Notifications from "../notifications"; const section = document.querySelector( @@ -10,7 +10,7 @@ const button = section.querySelector( "button[data-fpsLimit='native']" ) as HTMLButtonElement; -const input = validateWithIndicator( +const input = new ValidatedHtmlInputElement( section.querySelector('input[type="number"]') as HTMLInputElement, { schema: fpsLimitSchema, @@ -24,7 +24,7 @@ export function update(): void { input.setValue(null); button.classList.add("active"); } else { - input.value = fpsLimit.toString(); + input.setValue(fpsLimit.toString()); button.classList.remove("active"); } } @@ -38,7 +38,7 @@ function save(value: number): void { function saveFromInput(): void { if (input.getValidationResult().status !== "success") return; - const val = parseInt(input.value, 10); + const val = parseInt(input.getValue(), 10); save(val); } @@ -47,10 +47,10 @@ button.addEventListener("click", () => { update(); }); -input.addEventListener("keypress", (e) => { +input.native.addEventListener("keypress", (e) => { if (e.key === "Enter") { saveFromInput(); } }); -input.addEventListener("focusout", (e) => saveFromInput()); +input.native.addEventListener("focusout", (e) => saveFromInput()); diff --git a/frontend/src/ts/modals/edit-preset.ts b/frontend/src/ts/modals/edit-preset.ts index 5b235f12de43..3efa27fd463a 100644 --- a/frontend/src/ts/modals/edit-preset.ts +++ b/frontend/src/ts/modals/edit-preset.ts @@ -21,10 +21,7 @@ import { } from "@monkeytype/schemas/configs"; import { getDefaultConfig } from "../constants/default-config"; import { SnapshotPreset } from "../constants/default-snapshot"; -import { - ValidatedHtmlInputElement, - validateWithIndicator, -} from "../elements/input-validation"; +import { ValidatedHtmlInputElement } from "../elements/input-validation"; const state = { presetType: "full" as PresetType, @@ -50,7 +47,7 @@ export function show(action: string, id?: string, name?: string): void { $("#editPresetModal .modal .text").addClass("hidden"); addCheckBoxes(); if (!presetNameEl) { - presetNameEl = validateWithIndicator( + presetNameEl = new ValidatedHtmlInputElement( document.querySelector( "#editPresetModal .modal input" ) as HTMLInputElement, @@ -64,7 +61,7 @@ export function show(action: string, id?: string, name?: string): void { $("#editPresetModal .modal .popupTitle").html("Add new preset"); $("#editPresetModal .modal .submit").html(`add`); presetNameEl?.setValue(null); - presetNameEl?.parentElement?.classList.remove("hidden"); + presetNameEl?.native.parentElement?.classList.remove("hidden"); $("#editPresetModal .modal input").removeClass("hidden"); $( "#editPresetModal .modal label.changePresetToCurrentCheckbox" @@ -79,7 +76,7 @@ export function show(action: string, id?: string, name?: string): void { $("#editPresetModal .modal .popupTitle").html("Edit preset"); $("#editPresetModal .modal .submit").html(`save`); presetNameEl?.setValue(name); - presetNameEl?.parentElement?.classList.remove("hidden"); + presetNameEl?.native.parentElement?.classList.remove("hidden"); $("#editPresetModal .modal input").removeClass("hidden"); $( @@ -108,7 +105,7 @@ export function show(action: string, id?: string, name?: string): void { $("#editPresetModal .modal .inputs").addClass("hidden"); $("#editPresetModal .modal .presetType").addClass("hidden"); $("#editPresetModal .modal .presetNameTitle").addClass("hidden"); - presetNameEl?.parentElement?.classList.add("hidden"); + presetNameEl?.native.parentElement?.classList.add("hidden"); } updateUI(); }, diff --git a/frontend/src/ts/modals/google-sign-up.ts b/frontend/src/ts/modals/google-sign-up.ts index fc452a05eff3..5724456d321a 100644 --- a/frontend/src/ts/modals/google-sign-up.ts +++ b/frontend/src/ts/modals/google-sign-up.ts @@ -14,7 +14,7 @@ import * as Loader from "../elements/loader"; import { subscribe as subscribeToSignUpEvent } from "../observables/google-sign-up-event"; import AnimatedModal from "../utils/animated-modal"; import { resetIgnoreAuthCallback } from "../firebase"; -import { validateWithIndicator } from "../elements/input-validation"; +import { ValidatedHtmlInputElement } from "../elements/input-validation"; import { UserNameSchema } from "@monkeytype/schemas/users"; import { remoteValidation } from "../utils/remote-validation"; @@ -153,7 +153,7 @@ function disableInput(): void { nameInputEl.disabled = true; } -validateWithIndicator(nameInputEl, { +new ValidatedHtmlInputElement(nameInputEl, { schema: UserNameSchema, isValid: remoteValidation( async (name) => Ape.users.getNameAvailability({ params: { name } }), diff --git a/frontend/src/ts/modals/save-custom-text.ts b/frontend/src/ts/modals/save-custom-text.ts index 6bf9cd8d6ed3..cde6e32dce73 100644 --- a/frontend/src/ts/modals/save-custom-text.ts +++ b/frontend/src/ts/modals/save-custom-text.ts @@ -2,7 +2,7 @@ import * as CustomText from "../test/custom-text"; import * as Notifications from "../elements/notifications"; import * as CustomTextState from "../states/custom-text-name"; import AnimatedModal, { ShowOptions } from "../utils/animated-modal"; -import { validateWithIndicator } from "../elements/input-validation"; +import { ValidatedHtmlInputElement } from "../elements/input-validation"; import { z } from "zod"; type IncomingData = { @@ -17,7 +17,7 @@ const state: State = { textToSave: [], }; -const validatedInput = validateWithIndicator( +const validatedInput = new ValidatedHtmlInputElement( $("#saveCustomTextModal .textName")[0] as HTMLInputElement, { debounceDelay: 500, diff --git a/frontend/src/ts/pages/login.ts b/frontend/src/ts/pages/login.ts index 7111ec3fa6ab..8380fc158acb 100644 --- a/frontend/src/ts/pages/login.ts +++ b/frontend/src/ts/pages/login.ts @@ -7,7 +7,7 @@ import { UserEmailSchema, UserNameSchema, } from "@monkeytype/schemas/users"; -import { validateWithIndicator } from "../elements/input-validation"; +import { ValidatedHtmlInputElement } from "../elements/input-validation"; import { isDevEnvironment } from "../utils/misc"; import { z } from "zod"; import { remoteValidation } from "../utils/remote-validation"; @@ -72,7 +72,7 @@ export function getSignupData(): SignupData | false { const nameInputEl = document.querySelector( ".page.pageLogin .register.side input.usernameInput" ) as HTMLInputElement; -validateWithIndicator(nameInputEl, { +new ValidatedHtmlInputElement(nameInputEl, { schema: UserNameSchema, isValid: remoteValidation( async (name) => Ape.users.getNameAvailability({ params: { name } }), @@ -90,7 +90,7 @@ let disposableEmailModule: typeof import("disposable-email-domains-js") | null = null; let moduleLoadAttempted = false; -const emailInputEl = validateWithIndicator( +const emailInputEl = new ValidatedHtmlInputElement( document.querySelector( ".page.pageLogin .register.side input.emailInput" ) as HTMLInputElement, @@ -143,7 +143,7 @@ const emailInputEl = validateWithIndicator( } ); -emailInputEl.addEventListener("focus", async () => { +emailInputEl.native.addEventListener("focus", async () => { if (!moduleLoadAttempted) { moduleLoadAttempted = true; try { @@ -157,9 +157,9 @@ emailInputEl.addEventListener("focus", async () => { const emailVerifyInputEl = document.querySelector( ".page.pageLogin .register.side input.verifyEmailInput" ) as HTMLInputElement; -validateWithIndicator(emailVerifyInputEl, { +new ValidatedHtmlInputElement(emailVerifyInputEl, { isValid: async (emailVerify: string) => { - return emailInputEl.value === emailVerify + return emailInputEl.getValue() === emailVerify ? true : "verify email not matching email"; }, @@ -168,13 +168,13 @@ validateWithIndicator(emailVerifyInputEl, { registerForm.email = emailInputEl.getValidationResult().status === "success" && result.status === "success" - ? emailInputEl.value + ? emailInputEl.getValue() : undefined; updateSignupButton(); }, }); -const passwordInputEl = validateWithIndicator( +const passwordInputEl = new ValidatedHtmlInputElement( document.querySelector( ".page.pageLogin .register.side .passwordInput" ) as HTMLInputElement, @@ -192,9 +192,9 @@ const passwordInputEl = validateWithIndicator( const passwordVerifyInputEl = document.querySelector( ".page.pageLogin .register.side .verifyPasswordInput" ) as HTMLInputElement; -validateWithIndicator(passwordVerifyInputEl, { +new ValidatedHtmlInputElement(passwordVerifyInputEl, { isValid: async (passwordVerify: string) => { - return passwordInputEl.value === passwordVerify + return passwordInputEl.getValue() === passwordVerify ? true : "verify password not matching password"; }, @@ -203,7 +203,7 @@ validateWithIndicator(passwordVerifyInputEl, { registerForm.password = passwordInputEl.getValidationResult().status === "success" && result.status === "success" - ? passwordInputEl.value + ? passwordInputEl.getValue() : undefined; updateSignupButton(); }, diff --git a/frontend/src/ts/utils/simple-modal.ts b/frontend/src/ts/utils/simple-modal.ts index a311fee467e1..599d821b8102 100644 --- a/frontend/src/ts/utils/simple-modal.ts +++ b/frontend/src/ts/utils/simple-modal.ts @@ -6,10 +6,10 @@ import * as Notifications from "../elements/notifications"; import * as ConnectionState from "../states/connection"; import { IsValidResponse, + ValidatedHtmlInputElement, Validation, ValidationOptions, ValidationResult, - validateWithIndicator as withValidation, } from "../elements/input-validation"; type CommonInput = { @@ -351,7 +351,7 @@ export class SimpleModal { debounceDelay: input.validation.debounceDelay, }; - withValidation(element, options); + new ValidatedHtmlInputElement(element, options); } }); From c2691b334e3a74d7a15ade8136b71a35548eac9f Mon Sep 17 00:00:00 2001 From: NeraShi Date: Thu, 27 Nov 2025 01:31:24 +0300 Subject: [PATCH 14/15] impr(quotes): add Russian quotes (@NeraShi) (#7152) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ### Description Some quotes from my favourite literature. ### Translations id_1151: Almost five years! There were probably moments today when the living Daisy did not quite match the Daisy of his dreams - and it was not her fault, but the immense life force of the image he had created. This image was better than her, better than anything in the world. He shaped it with the genuine passion of an artist, constantly adding details, decorating every bright feather that came into his hand. No tangible, real charm can compare to what a person can accumulate in the depths of their imagination. id_1152: Gatsby believed in the green light, the gleam of an incredible future happiness that recedes each year. Even if it eluded him today, tomorrow we will run faster, reach further... And one fine morning... So we try to swim forward, struggling against the current, and it keeps pushing our little boats back into the past. id_1153: They say emotional wounds heal - a thoughtless analogy to bodily injuries, but in life it is not so. Such a wound may shrink, partially close, but it is always an open wound, even if no larger than a pinprick. The trace of suffered pain can perhaps be compared to the loss of a finger or sight in one eye. You come to terms with the injury, remembering it maybe only once a year - but when it suddenly comes to mind, there is no help for it. id_1154: Youth is like a plate piled high with sweets. Sentimental people claim they would like to return to the simple, pure state in which they existed before tasting the sweets. This is incorrect. They would like to experience those pleasurable sensations again. id_1155: Self-sacrifice, like a high elective office or inherited power, for some people at some times is a luxury, yet it brings not guarantee but responsibility, not calm but desperate risk. By its own inertia, it can push one to ruin — an emotional wave causes it, and the person is left alone forever on a bare rock of hopelessness. id_1156: There is so much within me that I want to express. But it is all so immense. I cannot find the words, I cannot convey what is inside. Sometimes it feels as if the whole world, all of life, everything in existence resides within me and demands: be our voice. I feel, oh, I don’t know how to explain... I feel its vastness, and when I begin to speak, it comes out as childish babble. How difficult it is to convey feeling, sensation in words, on paper or aloud, so that the reader or listener feels the same as you. It is a great task. id_1157: Facing life in all its forms, whirling in its changing vortex, Martin learned one rule: when playing an unfamiliar game, give the first move to another. This rule saved him thousands of times, honing his observation. He knew how to scrutinize the unknown and wait until a weakness or vulnerable point revealed itself. Just as in a boxing match, you test the opponent to find a weakness. And once found, - long experience taught him - use it fully. id_1158: Wherever he went, he was liked by everyone, because whether in work or in play, he remained true to himself, always ready and able to fight for his rights and demand respect. But he never put down roots. Those around him were pleased, but he himself was never fully content. There was no peace in him; he was constantly drawn and beckoned, wandering through life, not knowing what he sought or where the call came from, until he discovered books, creativity, and love. id_1159: The dream of love was more important to him than the dream of knowledge. The world seemed wondrous not because it consisted of molecules and atoms obeying some mysterious laws - it seemed wondrous because Ruth lived in it. She was a miracle, one that had never appeared to him even in dreams. id_1160: In the mouths of these people, the books he had read came alive. They spoke passionately, fervently. Thought burned them, as alcohol or anger might burn others. Philosophy was no longer dry printed lines from legendary demigods like Kant or Spencer. Philosophy had come alive, embodied in these two, filled with boiling crimson blood, transforming their faces. ### Checks - [x] Adding quotes? - [x] Make sure to include translations for the quotes in the description (or another comment) so we can verify their content. - [x] Check if any open issues are related to this PR; if so, be sure to tag them below. - [x] Make sure the PR title follows the Conventional Commits standard. (https://www.conventionalcommits.org for more info) - [x] Make sure to include your GitHub username prefixed with @ inside parentheses at the end of the PR title. --- frontend/static/quotes/russian.json | 60 +++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/frontend/static/quotes/russian.json b/frontend/static/quotes/russian.json index 383fa98a0d26..e867871ab9ed 100644 --- a/frontend/static/quotes/russian.json +++ b/frontend/static/quotes/russian.json @@ -6576,6 +6576,66 @@ "source": "А. С. Пушкин - Полтава", "text": "Тиха украинская ночь. Прозрачно небо. Звезды блещут. Своей дремоты превозмочь не хочет воздух. Чуть трепещут сребристых тополей листы. Но мрачны странные мечты в душе Мазепы: звезды ночи, как обвинительные очи, за ним насмешливо глядят. И тополи, стеснившись в ряд, качая тихо головою, как судьи, шепчут меж собою. И летней, теплой ночи тьма душна как черная тюрьма.", "length": 366 + }, + { + "id": 1151, + "source": "Ф. Скотт Фицджеральд - Великий Гэтсби", + "text": "Почти пять лет! Были, вероятно, сегодня минуты, когда живая Дэйзи в чем-то не дотянула до Дэйзи его мечтаний, - и дело тут было не в ней, а в огромной жизненной силе созданного им образа. Этот образ был лучшее ее, лучше всего на свете. Он творил его с подлинной страстью художника, все время что-то к нему прибавляя, украшая его каждым ярким перышком, попадавшимся под руку. Никакая ощутимая, реальная прелесть не может сравниться с тем, что способен накопить человек в глубинах своей фантазии.", + "length": 494 + }, + { + "id": 1152, + "source": "Ф. Скотт Фицджеральд - Великий Гэтсби", + "text": "Гэтсби верил в зеленый огонек, свет неимоверного будущего счастья, которое отодвигается с каждым годом. Пусть оно ускользнуло сегодня, не беда — завтра мы побежим еще быстрее, еще дальше станем протягивать руки… И в одно прекрасное утро… Так мы и пытаемся плыть вперед, борясь с течением, а оно все сносит и сносит наши суденышки обратно в прошлое.", + "length": 348 + }, + { + "id": 1153, + "source": "Ф. Скотт Фицджеральд - Великий Гэтсби", + "text": "Говорят, душевные раны рубцуются - бездумная аналогия с повреждениями телесными, в жизни так не бывает. Такая рана может уменьшиться, затянуться частично, но это всегда открытая рана, пусть и не больше булавочного укола. След испытанного страдания скорей можно сравнить с потерей пальца или зрения в одном глазу. С увечьем сживаешься, о нём вспоминаешь, быть может, только раз в году, - но когда вдруг вспомнишь, помочь всё равно нельзя.", + "length": 437 + }, + { + "id": 1154, + "source": "Ф. Скотт Фицджеральд - Великий Гэтсби", + "text": "Молодость - как тарелка, горой полная сластей. Люди сентиментальные уверяют, что хотели бы вернуться в то простое чистое состояние, в котором пребывали до того, как съели сласти. Это неверно. Они хотели бы снова испытать приятные вкусовые ощущения.", + "length": 248 + }, + { + "id": 1155, + "source": "Ф. Скотт Фицджеральд - Великий Гэтсби", + "text": "Самопожертвование, как высокая выборная должность, как унаследованная власть, для каких-то людей, в какие-то моменты - роскошь, но влечет оно за собой не гарантию, а ответственность, не спокойствие, а отчаянный риск. Собственной инерцией оно может толкнуть к гибели, - спадет эмоциональная волна, породившая его, и человек навсегда останется один на голой скале безнадежности.", + "length": 376 + }, + { + "id": 1156, + "source": "Джек Лондон - Мартин Иден", + "text": "Во мне столько всего, о чем я хочу сказать. Но все это так огромно. Я не нахожу слов, не могу выразить, что там внутри. Иногда мне кажется, весь мир, вся жизнь, все на свете поселилось во мне и требует: будь нашим голосом. Я чувствую, ох, не знаю, как объяснить… Я чувствую, как это огромно а начинаю говорить, выходит детский лепет. До чего трудная задача – передать чувство, ощущение такими словами, на бумаге или вслух, чтобы тот, кто читает или слушает, почувствовал или ощутил то же, что и ты. Это великая задача.", + "length": 518 + }, + { + "id": 1157, + "source": "Джек Лондон - Мартин Иден", + "text": "Сталкиваясь с жизнью, в самых разных ее обличьях, кружась в изменчивом ее водовороте, Мартин усвоил одно правило: когда играешь в незнакомую игру, первый ход предоставь другому. Правило это выручало его тысячи раз, да в придачу отточило его наблюдательность. Он умел приглядываться к тому, что незнакомо, и дождаться, когда обнаружится, в чем тут слабость, где уязвимое место. Все равно как в кулачном бою пробными ударами пытаться обнаружить слабину противника. И обнаружив ее, – этому его научил долгий опыт – использовать ее, использовать вовсю.", + "length": 548 + }, + { + "id": 1158, + "source": "Джек Лондон - Мартин Иден", + "text": "Он приходился ко двору везде, куда бы ни попал, всегда и везде оказывался общим любимцем, потому что в работе ли, в игре ли он оставался верен себе, всегда был готов и умел воевать за свои права и требовать уважения. Но нигде он не пустил корней. Им всюду были довольны те, кто рядом, но сам он вполне доволен не бывал. Не было в нём покоя, вечно что-то звало и манило его, и он скитался по жизни, сам не зная, чего ищет и откуда зов, пока не обрёл книги, творчество и любовь.", + "length": 476 + }, + { + "id": 1159, + "source": "Джек Лондон - Мартин Иден", + "text": "Мечта о любви была для него важнее мечты о знании. Мир казался удивительным вовсе не потому, что состоял из молекул и атомов, подчинявшихся действию каких-то таинственных законов, – мир казался удивительным потому, что в нем жила Руфь. Она была чудом, какое никогда раньше не являлось ему даже в мечтах.", + "length": 303 + }, + { + "id": 1160, + "source": "Джек Лондон - Мартин Иден", + "text": "В устах этих людей ожили книги, которыми он зачитывался. Они говорили страстно, увлечённо. Мысль горячила, их, как других горячат алкоголь или гнев. Философия перестала быть сухими печатными строчками из книг легендарных полубогов вроде Канта и Спенсера. Философия ожила, воплотилась вот в этих двоих, наполнилась кипучей алой кровью, преобразила их лица.", + "length": 355 } ] } From a875aa6edeccd3b2f02e0244aa1dbbebcb596343 Mon Sep 17 00:00:00 2001 From: sapbotgit <120243584+sapbotgit@users.noreply.github.com> Date: Thu, 27 Nov 2025 03:33:32 +0500 Subject: [PATCH 15/15] impr(quotes): Add quotes from eChat source code (@sapbotgit) (#7154) ### Description Different snippets of code from my old, dead project. ### Checks - [X] Adding quotes? - [ ] Make sure to include translations for the quotes in the description (or another comment) so we can verify their content. - [ ] Adding a language? - Make sure to follow the [languages documentation](https://github.com/monkeytypegame/monkeytype/blob/master/docs/LANGUAGES.md) - [ ] Add language to `packages/schemas/src/languages.ts` - [ ] Add language to exactly one group in `frontend/src/ts/constants/languages.ts` - [ ] Add language json file to `frontend/static/languages` - [ ] Adding a theme? - Make sure to follow the [themes documentation](https://github.com/monkeytypegame/monkeytype/blob/master/docs/THEMES.md) - [ ] Add theme to `packages/schemas/src/themes.ts` - [ ] Add theme to `frontend/src/ts/constants/themes.ts` - [ ] Add theme css file to `frontend/static/themes` - [ ] Add some screenshot of the theme, especially with different test settings (colorful, flip colors) to your pull request - [ ] Adding a layout? - [ ] Make sure to follow the [layouts documentation](https://github.com/monkeytypegame/monkeytype/blob/master/docs/LAYOUTS.md) - [ ] Add layout to `packages/schemas/src/layouts.ts` - [ ] Add layout json file to `frontend/static/layouts` - [ ] Adding a font? - Make sure to follow the [themes documentation](https://github.com/monkeytypegame/monkeytype/blob/master/docs/FONTS.md) - [ ] Add font file to `frontend/static/webfonts` - [ ] Add font to `packages/schemas/src/fonts.ts` - [ ] Add font to `frontend/src/ts/constants/fonts.ts` - [ ] Check if any open issues are related to this PR; if so, be sure to tag them below. - [ ] Make sure the PR title follows the Conventional Commits standard. (https://www.conventionalcommits.org for more info) - [ ] Make sure to include your GitHub username prefixed with @ inside parentheses at the end of the PR title. --- frontend/static/quotes/code_bash.json | 6 ++++++ frontend/static/quotes/code_css.json | 6 ++++++ frontend/static/quotes/code_python.json | 12 ++++++++++++ 3 files changed, 24 insertions(+) diff --git a/frontend/static/quotes/code_bash.json b/frontend/static/quotes/code_bash.json index 5a0fefe1cb8b..3e0e21bf6b15 100644 --- a/frontend/static/quotes/code_bash.json +++ b/frontend/static/quotes/code_bash.json @@ -66,6 +66,12 @@ "source": "Monitoring disk usage in Bash", "length": 218, "id": 10 + }, + { + "text": "echo INSTALLING PACKAGES\nsudo apt install python3 --assume-yes\nsudo apt install python3-pip --assume-yes\nsudo apt install python3-flask --assume-yes\nsudo apt install python3-transliterate --assume-yes\nsudo apt install python3-fuzzywuzzy --assume-yes\nsudo apt install vsftpd --assume-yes\nsudo apt install nginx --assume-yes\npip install bext --break-system-packages", + "source": "eChat - Install script line 1-9", + "length": 363, + "id": 11 } ] } diff --git a/frontend/static/quotes/code_css.json b/frontend/static/quotes/code_css.json index 43858902bbf6..b7ed838428cc 100644 --- a/frontend/static/quotes/code_css.json +++ b/frontend/static/quotes/code_css.json @@ -126,6 +126,12 @@ "source": "W3Schools CSS Linear Gradient with Multiple Color Stops", "id": 20, "length": 362 + }, + { + "text": "/* General body styles */\nbody {\n\tfont-family: Arial, sans-serif;\n\tmargin: 0;\n\tpadding: 0;\n\tbackground-color: #f4f4f4;\n\tcolor: #333;\n}", + "source": "eChat - CSS source code line 1-8", + "id": 21, + "length": 134 } ] } diff --git a/frontend/static/quotes/code_python.json b/frontend/static/quotes/code_python.json index a458bc9d3a33..82f7b33f3221 100644 --- a/frontend/static/quotes/code_python.json +++ b/frontend/static/quotes/code_python.json @@ -450,6 +450,18 @@ "source": "https://www.geeksforgeeks.org/python-program-for-dijkstras-shortest-path-algorithm-greedy-algo-7/", "id": 75, "length": 851 + }, + { + "text": "def redirect(link:str, text=\"\"):\n\treturn render_template(\"redirect.html\", link=link, text=text)", + "source": "eChat source code line 35-36", + "id": 76, + "length": 95 + }, + { + "text": "def isEnglish(s):\n\ttry:\n\t\ts.encode(encoding='utf-8').decode('ascii')\n\texcept UnicodeDecodeError:\n\t\treturn False\n\telse:\n\t\treturn True", + "source": "eChat source code line 96-102", + "id": 77, + "length": 132 } ] }