From d2c93792ffa7e4003c3e5b9678968e4fddc59e98 Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Tue, 6 Jan 2026 11:14:46 +0100 Subject: [PATCH 01/15] test: fix dom-utils mock (@fehmer) (#7319) - parital mock dom-utils module, prevents errors like [no "onWindowLoad" export is defined](https://github.com/monkeytypegame/monkeytype/actions/runs/20730640347/job/59517489709#step:11:616) - return empty `ElementsWithUtils` on `qsa` to prevent errors like `.hide is not a function` --- frontend/__tests__/setup-tests.ts | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/frontend/__tests__/setup-tests.ts b/frontend/__tests__/setup-tests.ts index 88e3e4ec4075..21a133a1ff32 100644 --- a/frontend/__tests__/setup-tests.ts +++ b/frontend/__tests__/setup-tests.ts @@ -1,6 +1,6 @@ import { vi } from "vitest"; import $ from "jquery"; -import { ElementWithUtils } from "../src/ts/utils/dom"; +import { ElementsWithUtils, ElementWithUtils } from "../src/ts/utils/dom"; //@ts-expect-error add to global global["$"] = $; @@ -20,7 +20,7 @@ vi.mock("../src/ts/firebase", () => ({ isAuthenticated: () => false, })); -vi.mock("../src/ts/utils/dom", () => { +vi.mock("../src/ts/utils/dom", async (importOriginal) => { const createMockElement = (): ElementWithUtils => { return { disable: vi.fn().mockReturnThis(), @@ -45,9 +45,9 @@ vi.mock("../src/ts/utils/dom", () => { setStyle: vi.fn().mockReturnThis(), getStyle: vi.fn().mockReturnValue({}), isFocused: vi.fn().mockReturnValue(false), - qs: vi.fn().mockReturnValue(null), + qs: vi.fn().mockImplementation(() => createMockElement()), qsr: vi.fn().mockImplementation(() => createMockElement()), - qsa: vi.fn().mockReturnValue([]), + qsa: vi.fn().mockImplementation(() => new ElementsWithUtils()), empty: vi.fn().mockReturnThis(), appendHtml: vi.fn().mockReturnThis(), append: vi.fn().mockReturnThis(), @@ -71,10 +71,14 @@ vi.mock("../src/ts/utils/dom", () => { }; }; + const actual = await importOriginal(); + return { + //@ts-expect-error - mocking private method + ...actual, qsr: vi.fn().mockImplementation(() => createMockElement()), qs: vi.fn().mockImplementation(() => createMockElement()), - qsa: vi.fn().mockReturnValue([]), + qsa: vi.fn().mockImplementation(() => new ElementsWithUtils()), }; }); From ace96b3a6145a00f07b3a09bb7da5bb0a8651055 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 6 Jan 2026 16:30:37 +0200 Subject: [PATCH 02/15] impr(burst-history): Use end time when calculating burst if test ended (@Leonabcd123) (#7302) ### Description Use the time when test ended to calculate burst instead of current time, so that burst history matches more closely actual wpm . Example bug fixed: When typing a single letter, wpm will be infinity but burst history will be ~90. --------- Co-authored-by: Jack --- frontend/src/ts/test/test-logic.ts | 2 +- frontend/src/ts/test/test-stats.ts | 4 ++-- frontend/src/ts/test/test-ui.ts | 7 +++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index 28206df798bf..96ee87c03e9c 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -904,7 +904,7 @@ export async function finish(difficultyFailed = false): Promise { //need one more calculation for the last word if test auto ended if (TestInput.burstHistory.length !== TestInput.input.getHistory()?.length) { - const burst = TestStats.calculateBurst(); + const burst = TestStats.calculateBurst(now); TestInput.pushBurstToHistory(burst); } diff --git a/frontend/src/ts/test/test-stats.ts b/frontend/src/ts/test/test-stats.ts index c86721225144..2644e4ee6a88 100644 --- a/frontend/src/ts/test/test-stats.ts +++ b/frontend/src/ts/test/test-stats.ts @@ -217,9 +217,9 @@ export function setLastSecondNotRound(): void { lastSecondNotRound = true; } -export function calculateBurst(): number { +export function calculateBurst(endTime: number = performance.now()): number { const containsKorean = TestInput.input.getKoreanStatus(); - const timeToWrite = (performance.now() - TestInput.currentBurstStart) / 1000; + const timeToWrite = (endTime - TestInput.currentBurstStart) / 1000; let wordLength: number; wordLength = !containsKorean ? TestInput.input.current.length diff --git a/frontend/src/ts/test/test-ui.ts b/frontend/src/ts/test/test-ui.ts index 6dfa81b14e32..d10e6e6651a8 100644 --- a/frontend/src/ts/test/test-ui.ts +++ b/frontend/src/ts/test/test-ui.ts @@ -1436,8 +1436,7 @@ export async function applyBurstHeatmap(): Promise { let burstlist = [...TestInput.burstHistory]; - burstlist = burstlist.filter((x) => x !== Infinity); - burstlist = burstlist.filter((x) => x < 500); + burstlist = burstlist.map((x) => (x >= 1000 ? Infinity : x)); const typingSpeedUnit = getTypingSpeedUnit(Config.typingSpeedUnit); burstlist.forEach((burst, index) => { @@ -1508,7 +1507,7 @@ export async function applyBurstHeatmap(): Promise { } $("#resultWordsHistory .heatmapLegend .box" + index).html( - `
${string}
`, + `
${Misc.escapeHTML(string)}
`, ); }); @@ -1977,7 +1976,7 @@ $(".pageTest #resultWordsHistory").on("mouseenter", ".words .word", (e) => { .replace(/>/g, ">")}
- ${Format.typingSpeed(burst, { showDecimalPlaces: false })} + ${isNaN(burst) || burst >= 1000 ? "Infinite" : Format.typingSpeed(burst, { showDecimalPlaces: false })} ${Config.typingSpeedUnit}
`, From f8ec9da43528127df68c9c710ae53b4366642f2e Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 6 Jan 2026 16:42:40 +0200 Subject: [PATCH 03/15] fix(custom-mode): chart problems in custom mode (@Leonabcd123) (#7293) ### Description Round when user is in custom mode with limit mode being time. Bug fixed: - Switch to custom mode - Set limit to some time - Do tests until you get a finishing time of x.99 - Notice the last value in the chart is less than the value that came before it, and is the value that came before it -0.01 --- frontend/src/ts/test/test-logic.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/src/ts/test/test-logic.ts b/frontend/src/ts/test/test-logic.ts index 96ee87c03e9c..90138cefa18f 100644 --- a/frontend/src/ts/test/test-logic.ts +++ b/frontend/src/ts/test/test-logic.ts @@ -915,7 +915,13 @@ export async function finish(difficultyFailed = false): Promise { // stats const stats = TestStats.calculateFinalStats(); - if (stats.time % 1 !== 0 && Config.mode !== "time") { + if ( + stats.time % 1 !== 0 && + !( + Config.mode === "time" || + (Config.mode === "custom" && CustomText.getLimitMode() === "time") + ) + ) { TestStats.setLastSecondNotRound(); } From 31aa70a5093ce0815458bad2de0acef6dcf2f830 Mon Sep 17 00:00:00 2001 From: "Y. Meyer-Norwood" <106889957+norwd@users.noreply.github.com> Date: Wed, 7 Jan 2026 03:44:37 +1300 Subject: [PATCH 04/15] impr(quotes): add Esperanto (X-Sistemo) quotes (@norwd) (#7294) This copies the original quotes, which still need to be converted to x-sistemo notation. ### Description ### Checks - [ ] Adding/modifying Typescript code? - [ ] I have used `qs`, `qsa` or `qsr` instead of JQuery selectors. - [x] Adding quotes? - [x] 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 screenshots 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. --- .../static/quotes/esperanto_x_sistemo.json | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 frontend/static/quotes/esperanto_x_sistemo.json diff --git a/frontend/static/quotes/esperanto_x_sistemo.json b/frontend/static/quotes/esperanto_x_sistemo.json new file mode 100644 index 000000000000..f4d4caa5d0ef --- /dev/null +++ b/frontend/static/quotes/esperanto_x_sistemo.json @@ -0,0 +1,95 @@ +{ + "language": "esperanto_x_sistemo", + "groups": [ + [0, 100], + [101, 300], + [301, 600], + [601, 9999] + ], + "quotes": [ + { + "text": "La nun proponatan brosxuron la leganto kredeble prenos en la manojn kun malkonfido, kun antauxe preta penso, ke al li estos proponata ia neefektivigebla utopio.", + "source": "La unua libro, L.Zamenof", + "length": 160, + "id": 1 + }, + { + "text": "Mi devas tial antaux cxio peti la leganton, ke li formetu tiun cxi antauxjugxon kaj ke li pripensu serioze kaj kritike la proponatan aferon.", + "source": "La unua libro, L.Zamenof", + "length": 140, + "id": 2 + }, + { + "text": "La demando pri lingvo internacia okupadis min jam longe; sed sentante min nek pli talenta, nek pli energia, ol la auxtoroj de cxiuj senfrukte pereintaj provoj, mi longan tempon limigadis min nur per revado kaj nevola meditado super tiu cxi afero. Sed kelke da felicxaj ideoj, kiuj aperis kiel frukto de tiu cxi nevola meditado, kuragxigis min por plua laborado kaj igis min ekprovi, cxu ne prosperos al mi sisteme venki cxiujn barojn por la kreo kaj enkonduko en uzadon de racia lingvo internacia.", + "source": "La unua libro, L.Zamenof", + "length": 497, + "id": 3 + }, + { + "text": "La Unua Libro estas samtempe enkonduko al la origino kaj idealoj de la lingvo kaj priskribo de gxia simpla gramatiko (kun ekzemploj el prozo kaj poezio kaj aldonita vortaro de oftaj vortoj).", + "source": "Vikipedio - La unua libro", + "length": 190, + "id": 4 + }, + { + "text": "Tajpado (ankaux masxinskribado) estas skribi tekston klavante, per masxino. Pli gxusta maniero tajpi konsistas en tio ke oni ne rigardu al la klavaro, sed nur al papero (okaze de masxino) aux al la ekrano (okaze de komputilo). Estas metodoj por lerni tiun sistemon, cxu per rekta instruado de instruisto, cxu per librometodo, cxu per interreta kurso aux komputila programo.", + "source": "Vikipedio - Tajpado", + "length": 373, + "id": 5 + }, + { + "text": "Esperanta Vikipedio estas projekto de kunlabora enciklopedio, universala kaj plurlingva, kreita interrete laux la vikio-principo. Gxi celas liveri en Esperanto liberan, objektivan kaj kontroleblan enhavon, kiun cxiuj povas redakti.", + "source": "Vikipedio - Ĉefpaĝo", + "length": 231, + "id": 6 + }, + { + "text": "Ke la lingvo estu eksterordinare facila, tiel ke oni povu ellerni gxin ludante.", + "source": "La unua libro, L.Zamenof", + "length": 79, + "id": 7 + }, + { + "text": "Juna Rikardo preskaux ploris cxe tiu terura konstato. Li rondrigardis. En la dormejo, li estis sola. Videble, ne nur lia mono malaperis, sed ankaux Jancxjo.", + "source": "Dankon, amiko!, Claude Piron", + "length": 156, + "id": 8 + }, + { + "text": "Normale mi devus forkuri kun via mono kaj veturbileto sen diri al vi ion ajn. Sed miaj amikaj sentoj tion malhelpas, kaj mi volas skribi adiauxon al vi. Mi sentas devon instrui vin pri la vivo. Se je la agxo de 21 jaroj vi ankoraux ne komprenis la riskojn, al kiuj vi vin elmetas, iu devas vin lernigi. Ni hazarde renkontigxis nur antaux tri tagoj. Vi sciis nenion pri mi. Tamen vian tutan vivon vi rakontis kaj... montris al mi vian tutan monon.", + "source": "Dankon, amiko!, Claude Piron", + "length": 446, + "id": 9 + }, + { + "text": "Kaj nun li sentas sin ema zorgi pri Linda. Cxu tiu belega knabino ne trovigxas en dangxero? Li amas sxin, li ecx amegas sxin, pli kaj pli, kaj la ideo, ke dangxeraj homoj povus fari ion al sxi, apenaux estas travivebla.", + "source": "Gerda malaperis, Claude Piron", + "length": 219, + "id": 10 + }, + { + "text": "Kion esperantistoj faru post la milito? Tiun demandon klopodas prilumi Istvan Szabolcs en dua vidpunkta artikolo pri la temo.", + "source": "Tragedio por Ukrainio kaj katastrofo por Rusio, 2022, Libera folio", + "length": 125, + "id": 11 + }, + { + "text": "En la vilagxo de Nomen Tuum, antikva cervfontano estas supozata enhavi kuracpovojn. En certaj okazoj personoj estis risanigitaj, sed pliofte ili akiris certan belecon.", + "source": "Inkubo (1966), Leslie Stevens", + "length": 167, + "id": 12 + }, + { + "text": "Kiam mi eniris la cxefstraton de la malgranda vilagxo, gxi estis tute senhoma, krom ke unu maljunulo per la helpo de marsxbastono malrapide iris en la direkto al la haveno kaj mi sciis, ke la vilagxanoj trovigxos tie, kien li iras.", + "source": "La ŝtormo, John S. Dinwoodie", + "length": 231, + "id": 13 + }, + { + "text": "La muroj de la haveno mem kaj la deklivo super gxi estis kovritaj de grupoj de la vilagxanoj.", + "source": "La ŝtormo, John S. Dinwoodie", + "length": 93, + "id": 14 + } + ] +} From 1b193532c9e36ecfd6d0345278e6123eb209c3da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hector=20Queir=C3=B3z?= Date: Tue, 6 Jan 2026 11:45:16 -0300 Subject: [PATCH 05/15] impr(quote): Added an English and Portuguese quote (@h-queiroz) (#7297) ### Description Added a quote in English and it's translation in Portuguese as well. The quote is "Let them see my weakness, and let them see me overcome it." both in english and in portuguese. ### Checks - [ ] Adding/modifying Typescript code? - [ ] I have used `qs`, `qsa` or `qsr` instead of JQuery selectors. - [x] Adding quotes? - [x] 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 screenshots 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. - [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. Closes # --- frontend/static/quotes/english.json | 6 ++++++ frontend/static/quotes/portuguese.json | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/frontend/static/quotes/english.json b/frontend/static/quotes/english.json index d5c3455c6eb6..311f6d9f4a0c 100644 --- a/frontend/static/quotes/english.json +++ b/frontend/static/quotes/english.json @@ -39141,6 +39141,12 @@ "source": "XCOM: Enemy Unknown", "id": 7736, "length": 308 + }, + { + "text": "Let them see my weakness, and let them see me overcome it.", + "source": "Mistborn: The Final Empire", + "id": 7737, + "length": 58 } ] } diff --git a/frontend/static/quotes/portuguese.json b/frontend/static/quotes/portuguese.json index 36238acf30d1..db7a1d727183 100644 --- a/frontend/static/quotes/portuguese.json +++ b/frontend/static/quotes/portuguese.json @@ -654,6 +654,12 @@ "source": "Luís Soares, Machado de Assis", "length": 215, "id": 109 + }, + { + "text": "Deixe-os ver minha fraqueza, e deixe que me vejam superando-a.", + "source": "Mistborn: O Império Final, Brandon Sanderson", + "length": 62, + "id": 110 } ] } From fe2f151072c9ad52a648a78c86ba4cc6090b6846 Mon Sep 17 00:00:00 2001 From: Mike Bart <43823770+mikebartGN@users.noreply.github.com> Date: Tue, 6 Jan 2026 09:52:58 -0500 Subject: [PATCH 06/15] feat(layout): add night_stic layout (@mikebartGN) (#7301) ### Description ### Checks - [ ] Adding/modifying Typescript code? - [ ] I have used `qs`, `qsa` or `qsr` instead of JQuery selectors. - [ ] 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 screenshots 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. Closes # --------- Co-authored-by: Miodec <13181393+Miodec@users.noreply.github.com> Co-authored-by: Miodec --- frontend/static/layouts/night_stic.json | 62 +++++++++++++++++++++++++ packages/schemas/src/layouts.ts | 1 + 2 files changed, 63 insertions(+) create mode 100644 frontend/static/layouts/night_stic.json diff --git a/frontend/static/layouts/night_stic.json b/frontend/static/layouts/night_stic.json new file mode 100644 index 000000000000..6b3f3db22de1 --- /dev/null +++ b/frontend/static/layouts/night_stic.json @@ -0,0 +1,62 @@ +{ + "keymapShowTopRow": false, + "type": "ansi", + "keys": { + "row1": [ + ["`", "~"], + ["1", "!"], + ["2", "@"], + ["3", "#"], + ["4", "$"], + ["5", "%"], + ["6", "^"], + ["7", "&"], + ["8", "*"], + ["9", "("], + ["0", ")"], + ["-", "_"], + ["=", "+"] + ], + "row2": [ + ["b", "B"], + ["f", "F"], + ["l", "L"], + ["d", "D"], + ["v", "V"], + ["y", "Y"], + ["p", "P"], + ["o", "O"], + ["u", "U"], + ["/", "?"], + ["[", "{"], + ["]", "}"], + ["\\", "|"] + ], + "row3": [ + ["n", "N"], + ["s", "S"], + ["h", "H"], + ["t", "T"], + ["m", "M"], + ["g", "G"], + ["c", "C"], + ["a", "A"], + ["e", "E"], + ["i", "I"], + ["-", "_"] + ], + "row4": [ + ["q", "Q"], + ["x", "X"], + ["j", "J"], + ["k", "K"], + ["z", "Z"], + ["'", "\""], + ["w", "W"], + [",", "<"], + [";", ":"], + [".", ">"] + ], + "row5": [[" "]] + } +} diff --git a/packages/schemas/src/layouts.ts b/packages/schemas/src/layouts.ts index f55d5f6abc1e..9cc82b0e400f 100644 --- a/packages/schemas/src/layouts.ts +++ b/packages/schemas/src/layouts.ts @@ -203,6 +203,7 @@ export const LayoutNameSchema = z.enum( "inqwerted", "rain", "night", + "night_stic", "whix2", "haruka", "kuntum", From 8c9ca7de1ce3faebb6931ca5e7177e2178e08990 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 6 Jan 2026 17:00:04 +0200 Subject: [PATCH 07/15] refactor: remove jQuery from email-handler (@Leonabcd123) (#7304) Co-authored-by: Jack --- frontend/src/email-handler.html | 100 ++++++++++++------------ frontend/src/ts/pages/profile-search.ts | 2 +- frontend/src/ts/utils/dom.ts | 4 +- 3 files changed, 52 insertions(+), 54 deletions(-) diff --git a/frontend/src/email-handler.html b/frontend/src/email-handler.html index 160ad19080de..f0753f098988 100644 --- a/frontend/src/email-handler.html +++ b/frontend/src/email-handler.html @@ -167,7 +167,6 @@ diff --git a/frontend/src/ts/pages/profile-search.ts b/frontend/src/ts/pages/profile-search.ts index e5ca472ef48c..e35d6b4c4041 100644 --- a/frontend/src/ts/pages/profile-search.ts +++ b/frontend/src/ts/pages/profile-search.ts @@ -57,7 +57,7 @@ export const page = new Page({ disableButton(); }, afterShow: async (): Promise => { - qs(".page.pageProfileSearch input")?.dispatch("focus"); + qs(".page.pageProfileSearch input")?.focus(); }, }); diff --git a/frontend/src/ts/utils/dom.ts b/frontend/src/ts/utils/dom.ts index 4e1088691bc4..d0525086bb93 100644 --- a/frontend/src/ts/utils/dom.ts +++ b/frontend/src/ts/utils/dom.ts @@ -212,11 +212,13 @@ export class ElementWithUtils { /** * Check if element is visible */ - isVisible(): boolean { return this.native.offsetWidth > 0 || this.native.offsetHeight > 0; } + /** + * Make element visible by scrolling the element's ancestor containers + */ scrollIntoView(options: ScrollIntoViewOptions): this { this.native.scrollIntoView(options); From 7e0d99244f6a3176b87a8b8dfa01b1ffe41b8f5a Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Tue, 6 Jan 2026 17:13:02 +0200 Subject: [PATCH 08/15] refactor: Remove jQuery from event-handlers (@Leonabcd123) (#7311) Progress towards #7186 --- frontend/src/ts/event-handlers/about.ts | 17 +-- frontend/src/ts/event-handlers/account.ts | 24 ++-- frontend/src/ts/event-handlers/footer.ts | 121 ++++++++---------- frontend/src/ts/event-handlers/keymap.ts | 3 +- .../src/ts/event-handlers/leaderboards.ts | 13 +- frontend/src/ts/event-handlers/login.ts | 5 +- frontend/src/ts/event-handlers/settings.ts | 101 +++++++-------- frontend/src/ts/event-handlers/test.ts | 59 +++++---- 8 files changed, 167 insertions(+), 176 deletions(-) diff --git a/frontend/src/ts/event-handlers/about.ts b/frontend/src/ts/event-handlers/about.ts index d1c66c86a3ec..0cde61d83e88 100644 --- a/frontend/src/ts/event-handlers/about.ts +++ b/frontend/src/ts/event-handlers/about.ts @@ -1,14 +1,11 @@ import * as SupportPopup from "../modals/support"; import * as ContactModal from "../modals/contact"; +import { qs } from "../utils/dom"; -document - .querySelector("#pageAbout #supportMeAboutButton") - ?.addEventListener("click", () => { - SupportPopup.show(); - }); +qs("#pageAbout #supportMeAboutButton")?.on("click", () => { + SupportPopup.show(); +}); -document - .querySelector("#pageAbout #contactPopupButton2") - ?.addEventListener("click", () => { - ContactModal.show(); - }); +qs("#pageAbout #contactPopupButton2")?.on("click", () => { + ContactModal.show(); +}); diff --git a/frontend/src/ts/event-handlers/account.ts b/frontend/src/ts/event-handlers/account.ts index d852e07144f6..c2f8f97e6a6f 100644 --- a/frontend/src/ts/event-handlers/account.ts +++ b/frontend/src/ts/event-handlers/account.ts @@ -7,18 +7,19 @@ import * as EditResultTagsModal from "../modals/edit-result-tags"; import * as AddFilterPresetModal from "../modals/new-filter-preset"; import { parseWithSchema as parseJsonWithSchema } from "@monkeytype/util/json"; import { z } from "zod"; +import { qs } from "../utils/dom"; -const accountPage = document.querySelector("#pageAccount") as HTMLElement; +const accountPage = qs("#pageAccount"); -$(accountPage).on("click", ".pbsTime .showAllButton", () => { +accountPage?.onChild("click", ".pbsTime .showAllButton", () => { PbTablesModal.show("time"); }); -$(accountPage).on("click", ".pbsWords .showAllButton", () => { +accountPage?.onChild("click", ".pbsWords .showAllButton", () => { PbTablesModal.show("words"); }); -$(accountPage).on("click", ".editProfileButton", () => { +accountPage?.onChild("click", ".editProfileButton", () => { if (!isAuthenticated()) { Notifications.add("You must be logged in to edit your profile", 0); return; @@ -40,9 +41,10 @@ $(accountPage).on("click", ".editProfileButton", () => { const TagsArraySchema = z.array(z.string()); -$(accountPage).on("click", ".group.history .resultEditTagsButton", (e) => { - const resultid = $(e.target).attr("data-result-id"); - const tags = $(e.target).attr("data-tags"); +accountPage?.onChild("click", ".group.history .resultEditTagsButton", (e) => { + const targetButton = e.childTarget as HTMLElement; + const resultid = targetButton?.getAttribute("data-result-id"); + const tags = targetButton?.getAttribute("data-tags"); EditResultTagsModal.show( resultid ?? "", @@ -51,8 +53,6 @@ $(accountPage).on("click", ".group.history .resultEditTagsButton", (e) => { ); }); -$(accountPage) - .find("button.createFilterPresetBtn") - .on("click", () => { - AddFilterPresetModal.show(); - }); +accountPage?.qs("button.createFilterPresetBtn")?.on("click", () => { + AddFilterPresetModal.show(); +}); diff --git a/frontend/src/ts/event-handlers/footer.ts b/frontend/src/ts/event-handlers/footer.ts index 949cca104459..25e8e02856e9 100644 --- a/frontend/src/ts/event-handlers/footer.ts +++ b/frontend/src/ts/event-handlers/footer.ts @@ -9,77 +9,66 @@ import * as VersionHistoryModal from "../modals/version-history"; import { envConfig } from "virtual:env-config"; import { COMPATIBILITY_CHECK } from "@monkeytype/contracts"; import { lastSeenServerCompatibility } from "../ape/adapters/ts-rest-adapter"; +import { qs } from "../utils/dom"; -document - .querySelector("footer #commandLineMobileButton") - ?.addEventListener("click", async () => { - Commandline.show({ - singleListOverride: false, - }); +qs("footer #commandLineMobileButton")?.on("click", async () => { + Commandline.show({ + singleListOverride: false, }); +}); -document - .querySelector("footer #newVersionIndicator") - ?.addEventListener("click", (e) => { - e.stopPropagation(); - document.querySelector("#newVersionIndicator")?.classList.add("hidden"); - }); +qs("footer #newVersionIndicator")?.on("click", (e) => { + e.stopPropagation(); + qs("#newVersionIndicator")?.hide(); +}); -document - .querySelector("footer .currentVersion") - ?.addEventListener("click", (e) => { - const event = e as MouseEvent; - if (event.shiftKey) { - alert( - JSON.stringify( - { - clientVersion: envConfig.clientVersion, - clientCompatibility: COMPATIBILITY_CHECK, - lastSeenServerCompatibility, - }, - null, - 2, - ), - ); - } else { - VersionHistoryModal.show(); - } - }); +qs("footer .currentVersion")?.on("click", (e) => { + const event = e as MouseEvent; + if (event.shiftKey) { + alert( + JSON.stringify( + { + clientVersion: envConfig.clientVersion, + clientCompatibility: COMPATIBILITY_CHECK, + lastSeenServerCompatibility, + }, + null, + 2, + ), + ); + } else { + VersionHistoryModal.show(); + } +}); -document - .querySelector("footer .right .current-theme") - ?.addEventListener("click", async (event) => { - const e = event as MouseEvent; - if (e.shiftKey) { - if (Config.customTheme) { - setConfig("customTheme", false); - return; - } - if ( - isAuthenticated() && - (DB.getSnapshot()?.customThemes?.length ?? 0) < 1 - ) { - Notifications.add("No custom themes!", 0); - setConfig("customTheme", false); - return; - } - setConfig("customTheme", true); - } else { - const subgroup = Config.customTheme ? "customTheme" : "themes"; - Commandline.show({ - subgroupOverride: subgroup, - }); +qs("footer .right .current-theme")?.on("click", async (event) => { + const e = event as MouseEvent; + if (e.shiftKey) { + if (Config.customTheme) { + setConfig("customTheme", false); + return; } - }); + if ( + isAuthenticated() && + (DB.getSnapshot()?.customThemes?.length ?? 0) < 1 + ) { + Notifications.add("No custom themes!", 0); + setConfig("customTheme", false); + return; + } + setConfig("customTheme", true); + } else { + const subgroup = Config.customTheme ? "customTheme" : "themes"; + Commandline.show({ + subgroupOverride: subgroup, + }); + } +}); -document - .querySelector("footer #supportMeButton") - ?.addEventListener("click", () => { - SupportPopup.show(); - }); +qs("footer #supportMeButton")?.on("click", () => { + SupportPopup.show(); +}); -document - .querySelector("footer #contactPopupButton") - ?.addEventListener("click", () => { - ContactModal.show(); - }); +qs("footer #contactPopupButton")?.on("click", () => { + ContactModal.show(); +}); diff --git a/frontend/src/ts/event-handlers/keymap.ts b/frontend/src/ts/event-handlers/keymap.ts index 90eb7e8f46ff..da67f60e37e7 100644 --- a/frontend/src/ts/event-handlers/keymap.ts +++ b/frontend/src/ts/event-handlers/keymap.ts @@ -1,6 +1,7 @@ import * as Commandline from "../commandline/commandline"; +import { qs } from "../utils/dom"; -$("#keymap").on("click", ".r5 .layoutIndicator", async () => { +qs("#keymap")?.onChild("click", ".r5 .layoutIndicator", async () => { Commandline.show({ subgroupOverride: "keymapLayout", }); diff --git a/frontend/src/ts/event-handlers/leaderboards.ts b/frontend/src/ts/event-handlers/leaderboards.ts index 56875b74df9e..61769069e879 100644 --- a/frontend/src/ts/event-handlers/leaderboards.ts +++ b/frontend/src/ts/event-handlers/leaderboards.ts @@ -1,11 +1,8 @@ import { showPopup } from "../modals/simple-modals"; +import { qs } from "../utils/dom"; -const lb = document.getElementById("pageLeaderboards"); +const lb = qs("#pageLeaderboards"); -for (const button of lb?.querySelectorAll( - ".jumpButtons button[data-action='goToPage']", -) ?? []) { - button?.addEventListener("click", () => { - showPopup("lbGoToPage"); - }); -} +lb?.qsa(".jumpButtons button[data-action='goToPage']").on("click", () => { + showPopup("lbGoToPage"); +}); diff --git a/frontend/src/ts/event-handlers/login.ts b/frontend/src/ts/event-handlers/login.ts index 092691a618ba..9931a92b41a0 100644 --- a/frontend/src/ts/event-handlers/login.ts +++ b/frontend/src/ts/event-handlers/login.ts @@ -1,7 +1,8 @@ import * as ForgotPasswordModal from "../modals/forgot-password"; +import { qs } from "../utils/dom"; -const loginPage = document.querySelector("#pageLogin") as HTMLElement; +const loginPage = qs("#pageLogin"); -$(loginPage).on("click", "#forgotPasswordButton", () => { +loginPage?.onChild("click", "#forgotPasswordButton", () => { ForgotPasswordModal.show(); }); diff --git a/frontend/src/ts/event-handlers/settings.ts b/frontend/src/ts/event-handlers/settings.ts index 13137de1b6a5..a8c5610107ae 100644 --- a/frontend/src/ts/event-handlers/settings.ts +++ b/frontend/src/ts/event-handlers/settings.ts @@ -4,67 +4,64 @@ import * as EditPresetPopup from "../modals/edit-preset"; import * as EditTagPopup from "../modals/edit-tag"; import * as Notifications from "../elements/notifications"; +import { qs } from "../utils/dom"; -const settingsPage = document.querySelector("#pageSettings"); +const settingsPage = qs("#pageSettings"); -settingsPage - ?.querySelector("#shareCustomThemeButton") - ?.addEventListener("click", () => { - ShareCustomThemeModal.show(); - }); +settingsPage?.qs("#shareCustomThemeButton")?.on("click", () => { + ShareCustomThemeModal.show(); +}); settingsPage - ?.querySelector(".section.updateCookiePreferences .buttons button") - ?.addEventListener("click", () => { + ?.qs(".section.updateCookiePreferences .buttons button") + ?.on("click", () => { CookiesModal.show(true); }); -settingsPage - ?.querySelector(".section.presets") - ?.addEventListener("click", (e) => { - const target = e.target as HTMLElement; - if (target.classList.contains("addPresetButton")) { - EditPresetPopup.show("add"); - } else if (target.classList.contains("editButton")) { - const presetid = target.parentElement?.getAttribute("data-id"); - const name = target.parentElement?.getAttribute("data-display"); - if ( - presetid === undefined || - name === undefined || - presetid === "" || - name === "" || - presetid === null || - name === null - ) { - Notifications.add( - "Failed to edit preset: Could not find preset id or name", - -1, - ); - return; - } - EditPresetPopup.show("edit", presetid, name); - } else if (target.classList.contains("removeButton")) { - const presetid = target.parentElement?.getAttribute("data-id"); - const name = target.parentElement?.getAttribute("data-display"); - if ( - presetid === undefined || - name === undefined || - presetid === "" || - name === "" || - presetid === null || - name === null - ) { - Notifications.add( - "Failed to remove preset: Could not find preset id or name", - -1, - ); - return; - } - EditPresetPopup.show("remove", presetid, name); +settingsPage?.qs(".section.presets")?.on("click", (e) => { + const target = e.target as HTMLElement; + if (target.classList.contains("addPresetButton")) { + EditPresetPopup.show("add"); + } else if (target.classList.contains("editButton")) { + const presetid = target.parentElement?.getAttribute("data-id"); + const name = target.parentElement?.getAttribute("data-display"); + if ( + presetid === undefined || + name === undefined || + presetid === "" || + name === "" || + presetid === null || + name === null + ) { + Notifications.add( + "Failed to edit preset: Could not find preset id or name", + -1, + ); + return; } - }); + EditPresetPopup.show("edit", presetid, name); + } else if (target.classList.contains("removeButton")) { + const presetid = target.parentElement?.getAttribute("data-id"); + const name = target.parentElement?.getAttribute("data-display"); + if ( + presetid === undefined || + name === undefined || + presetid === "" || + name === "" || + presetid === null || + name === null + ) { + Notifications.add( + "Failed to remove preset: Could not find preset id or name", + -1, + ); + return; + } + EditPresetPopup.show("remove", presetid, name); + } +}); -settingsPage?.querySelector(".section.tags")?.addEventListener("click", (e) => { +settingsPage?.qs(".section.tags")?.on("click", (e) => { const target = e.target as HTMLElement; if (target.classList.contains("addTagButton")) { EditTagPopup.show("add"); diff --git a/frontend/src/ts/event-handlers/test.ts b/frontend/src/ts/event-handlers/test.ts index 072c212cd3dd..f2ee6cf01fd3 100644 --- a/frontend/src/ts/event-handlers/test.ts +++ b/frontend/src/ts/event-handlers/test.ts @@ -17,55 +17,63 @@ import { getMode2 } from "../utils/misc"; import * as ShareTestSettingsPopup from "../modals/share-test-settings"; import { ConfigKey } from "@monkeytype/schemas/configs"; import { ListsObjectKeys } from "../commandline/lists"; +import { qs } from "../utils/dom"; -$(".pageTest").on("click", "#testModesNotice .textButton", async (event) => { - const attr = $(event.currentTarget).attr("commands"); +const testPage = qs(".pageTest"); + +testPage?.onChild("click", "#testModesNotice .textButton", async (event) => { + const target = event.childTarget as HTMLElement; + const attr = target?.getAttribute("commands"); if (attr === undefined) return; Commandline.show({ subgroupOverride: attr as ConfigKey | ListsObjectKeys }); }); -$(".pageTest").on("click", "#testModesNotice .textButton", async (event) => { - const attr = $(event.currentTarget).attr("commandId"); - if (attr === undefined) return; +testPage?.onChild("click", "#testModesNotice .textButton", async (event) => { + const target = event.childTarget as HTMLElement; + const attr = target?.getAttribute("commandId"); + if (attr === null) return; Commandline.show({ commandOverride: attr }); }); -$(".pageTest").on("click", "#testConfig .wordCount .textButton", (e) => { - const wrd = $(e.currentTarget).attr("wordCount"); +testPage?.onChild("click", "#testConfig .wordCount .textButton", (event) => { + const target = event.childTarget as HTMLElement; + const wrd = target?.getAttribute("wordCount"); if (wrd === "custom") { CustomWordAmount.show(); } }); -$(".pageTest").on("click", "#testConfig .time .textButton", (e) => { - const time = $(e.currentTarget).attr("timeconfig"); +testPage?.onChild("click", "#testConfig .time .textButton", (event) => { + const target = event.childTarget as HTMLElement; + const time = target?.getAttribute("timeconfig"); if (time === "custom") { CustomTestDurationModal.show(); } }); -$(".pageTest").on("click", "#testConfig .shareButton", (e) => { +testPage?.onChild("click", "#testConfig .shareButton", () => { ShareTestSettingsPopup.show(); }); -$(".pageTest").on("click", ".tags .editTagsButton", () => { +testPage?.onChild("click", ".tags .editTagsButton", () => { if ((DB.getSnapshot()?.tags?.length ?? 0) > 0) { - const resultid = $(".pageTest .tags .editTagsButton").attr( - "data-result-id", - ) as string; - const activeTagIds = $(".pageTest .tags .editTagsButton").attr( - "data-active-tag-ids", - ) as string; + const resultid = + qs(".pageTest .tags .editTagsButton")?.getAttribute("data-result-id") ?? + ""; + const activeTagIds = + qs(".pageTest .tags .editTagsButton")?.getAttribute( + "data-active-tag-ids", + ) ?? ""; const tags = activeTagIds === "" ? [] : activeTagIds.split(","); EditResultTagsModal.show(resultid, tags, "resultPage"); } }); -$(".pageTest").on("click", "#mobileTestConfigButton", () => { +testPage?.onChild("click", "#mobileTestConfigButton", () => { MobileTestConfigModal.show(); }); -$(".pageTest #rateQuoteButton").on("click", async () => { +qs(".pageTest #rateQuoteButton")?.on("click", async () => { if (TestWords.currentQuote === null) { Notifications.add("Failed to show quote rating popup: no quote", -1); return; @@ -73,7 +81,7 @@ $(".pageTest #rateQuoteButton").on("click", async () => { QuoteRateModal.show(TestWords.currentQuote); }); -$(".pageTest #reportQuoteButton").on("click", async () => { +qs(".pageTest #reportQuoteButton")?.on("click", async () => { if (TestWords.currentQuote === null) { Notifications.add("Failed to show quote report popup: no quote", -1); return; @@ -81,18 +89,19 @@ $(".pageTest #reportQuoteButton").on("click", async () => { void QuoteReportModal.show(TestWords.currentQuote?.id); }); -$(".pageTest").on("click", "#testConfig .quoteLength .textButton", (e) => { - const len = parseInt($(e.currentTarget).attr("quoteLength") ?? "0"); +testPage?.onChild("click", "#testConfig .quoteLength .textButton", (event) => { + const target = event.childTarget as HTMLElement; + const len = parseInt(target?.getAttribute("quoteLength") ?? "0"); if (len === -2) { void QuoteSearchModal.show(); } }); -$(".pageTest").on("click", "#testConfig .customText .textButton", () => { +testPage?.onChild("click", "#testConfig .customText .textButton", () => { CustomTextModal.show(); }); -$(".pageTest").on("click", "#practiseWordsButton", () => { +testPage?.onChild("click", "#practiseWordsButton", () => { if (Config.mode === "zen") { Notifications.add("Practice words is unsupported in zen mode", 0); return; @@ -100,7 +109,7 @@ $(".pageTest").on("click", "#practiseWordsButton", () => { PractiseWordsModal.show(); }); -$(".pageTest #dailyLeaderboardRank").on("click", async () => { +qs(".pageTest #dailyLeaderboardRank")?.on("click", async () => { void navigate( `/leaderboards?type=daily&language=${Config.language}&mode2=${getMode2( Config, From bd2df3971fa858c922d2624f24cdf061f4a1d3d7 Mon Sep 17 00:00:00 2001 From: Vignesh <75526550+ving-sh@users.noreply.github.com> Date: Tue, 6 Jan 2026 20:50:15 +0530 Subject: [PATCH 09/15] feat(layout): add tamil99 layout (@ving-sh) (#7313) ### Description ### Checks - [ ] Adding/modifying Typescript code? - [ ] I have used `qs`, `qsa` or `qsr` instead of JQuery selectors. - [ ] 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 screenshots of the theme, especially with different test settings (colorful, flip colors) to your pull request - [x] Adding a layout? - [x] Make sure to follow the [layouts documentation](https://github.com/monkeytypegame/monkeytype/blob/master/docs/LAYOUTS.md) - [x] Add layout to `packages/schemas/src/layouts.ts` - [x] 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] Make sure the PR title follows the Conventional Commits standard. (https://www.conventionalcommits.org for more info) - [x] Check if any open issues are related to this PR; if so, be sure to tag them below. - [x] Make sure to include your GitHub username prefixed with @ inside parentheses at the end of the PR title. Closes # [Discussion #6483](https://github.com/monkeytypegame/monkeytype/discussions/6483) Layout Documentation https://learn.microsoft.com/en-us/globalization/keyboards/kbdtam99 http://kbdlayout.info/KBDTAM99?arrangement=ANSI104 --------- Co-authored-by: Jack --- frontend/static/layouts/tamil99.json | 62 ++++++++++++++++++++++++++++ packages/schemas/src/layouts.ts | 1 + 2 files changed, 63 insertions(+) create mode 100644 frontend/static/layouts/tamil99.json diff --git a/frontend/static/layouts/tamil99.json b/frontend/static/layouts/tamil99.json new file mode 100644 index 000000000000..7331df0ed416 --- /dev/null +++ b/frontend/static/layouts/tamil99.json @@ -0,0 +1,62 @@ +{ + "keymapShowTopRow": false, + "type": "ansi", + "keys": { + "row1": [ + ["`", "~"], + ["1", "!"], + ["2", "@"], + ["3", "#"], + ["4", "$"], + ["5", "%"], + ["6", "^"], + ["7", "&"], + ["8", "*"], + ["9", "("], + ["0", ")"], + ["-", "_"], + ["=", "+"] + ], + "row2": [ + ["ஆ", "ஸ"], + ["ஈ", "ஷ"], + ["ஊ", "ஜ"], + ["ஐ", "ஹ"], + ["ஏ"], + ["ள"], + ["ற", "ஶ"], + ["ன", ":"], + ["ட", "["], + ["ண", "]"], + ["ச", "{"], + ["ஞ", "}"], + ["\\", "|"] + ], + "row3": [ + ["அ", "௹"], + ["இ", "௺"], + ["உ", "௸"], + ["்", "ஃ"], + ["எ", "எ"], + ["க", "க"], + ["ப", "ப"], + ["ம", "\""], + ["த", "௱"], + ["ந", ";"], + ["ய", "'"] + ], + "row4": [ + ["ஔ", "௳"], + ["ஓ", "௴"], + ["ஒ", "௵"], + ["வ", "௶"], + ["ங", "௷"], + ["ல", "ௐ"], + ["ர", "/"], + [",", "<"], + [".", ">"], + ["ழ", "?"] + ], + "row5": [[" "]] + } +} diff --git a/packages/schemas/src/layouts.ts b/packages/schemas/src/layouts.ts index 9cc82b0e400f..94de81ef32df 100644 --- a/packages/schemas/src/layouts.ts +++ b/packages/schemas/src/layouts.ts @@ -231,6 +231,7 @@ export const LayoutNameSchema = z.enum( "persian_farsi_colemak", "persian_standard_colemak", "ergo_split46", + "tamil99", ], { errorMap: customEnumErrorHandler("Must be a supported layout"), From a4b6671046824c91047fe9a1a933d541f0d1b181 Mon Sep 17 00:00:00 2001 From: thanos <236362159+thanoskn@users.noreply.github.com> Date: Tue, 6 Jan 2026 17:20:57 +0200 Subject: [PATCH 10/15] refactor(states): Replace jQuery with dom utils in states (@thanoskn) (#7314) ### Description Replaced jQuery with dom utils ### Checks - [x] Adding/modifying Typescript code? - [x] I have used `qs`, `qsa` or `qsr` instead of JQuery selectors. - [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. ### Related issue #7186 , #7319 --- frontend/src/ts/states/connection.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/src/ts/states/connection.ts b/frontend/src/ts/states/connection.ts index b9f0327299bc..efaeebd8f6a4 100644 --- a/frontend/src/ts/states/connection.ts +++ b/frontend/src/ts/states/connection.ts @@ -2,6 +2,7 @@ import { debounce } from "throttle-debounce"; import * as Notifications from "../elements/notifications"; import * as ConnectionEvent from "../observables/connection-event"; import * as TestState from "../test/test-state"; +import { qs, onWindowLoad } from "../utils/dom"; let state = navigator.onLine; @@ -33,9 +34,9 @@ const throttledHandleState = debounce(5000, () => { Notifications.add("You're back online", 1, { customTitle: "Connection", }); - $( + qs( `#bannerCenter .psa.notice[id="${noInternetBannerId}"] .closeButton`, - ).trigger("click"); + )?.dispatch("click"); } bannerAlreadyClosed = false; } else if (!TestState.isActive) { @@ -48,7 +49,7 @@ ConnectionEvent.subscribe((newState) => { throttledHandleState(); }); -window.addEventListener("load", () => { +onWindowLoad(() => { state = navigator.onLine; if (!state) { showOfflineBanner(); From 0c168af84157ee7fea66fb331c44ffad6325d243 Mon Sep 17 00:00:00 2001 From: Seif Soliman Date: Tue, 6 Jan 2026 17:24:40 +0200 Subject: [PATCH 11/15] fix(custom): ignore prototype properties in British English replacement rules (@byseif21) (#7317) ### Description * custom mode (with british english enabled) could break with some words that matched an inherited JS object property, causing crashes * made the replacement logic now ignores prototype property names on the rules object, added a small test for it. Closes #7316 --- frontend/__tests__/test/british-english.spec.ts | 5 +++++ frontend/src/ts/test/british-english.ts | 3 +++ 2 files changed, 8 insertions(+) diff --git a/frontend/__tests__/test/british-english.spec.ts b/frontend/__tests__/test/british-english.spec.ts index b0650bc89bc0..12a7e53f4915 100644 --- a/frontend/__tests__/test/british-english.spec.ts +++ b/frontend/__tests__/test/british-english.spec.ts @@ -63,5 +63,10 @@ describe("british-english", () => { await expect(replace("'hello'", "")).resolves.toEqual("'hello'"); await expect(replace("test", "")).resolves.toEqual("test"); }); + + it("ignores prototype-related property names (e.g. constructor, __proto__)", async () => { + await expect(replace("constructor", "")).resolves.toEqual("constructor"); + await expect(replace("__proto__", "")).resolves.toEqual("__proto__"); + }); }); }); diff --git a/frontend/src/ts/test/british-english.ts b/frontend/src/ts/test/british-english.ts index b97f3fed7e9e..d90449ce4ce5 100644 --- a/frontend/src/ts/test/british-english.ts +++ b/frontend/src/ts/test/british-english.ts @@ -700,6 +700,9 @@ export async function replace( ).join("-"); } else { const cleanedWord = word.replace(/^[\W]+|[\W]+$/g, "").toLowerCase(); + if (!Object.prototype.hasOwnProperty.call(replacementRules, cleanedWord)) { + return word; + } const rule = replacementRules[cleanedWord]; if (rule === undefined) return word; From 4da82d0f2b7bccedfcbc45ff3d74ee6bd000edb9 Mon Sep 17 00:00:00 2001 From: Justiniscoding Date: Tue, 6 Jan 2026 10:42:02 -0500 Subject: [PATCH 12/15] feat: create new sPoNgEcAsE and modify raNDOmcASe to be random (@Justiniscoding) (#7295) ### Description The old rAnDoMcAsE mode was not actually random and more accurately reflected [sponge case](https://en.wikipedia.org/wiki/Alternating_caps). I modified the old rAnDoMcAsE mode and turned it into raNDOmcASe, where it calls `Math.random()` for every letter and bases the capitalization of of it. The old code from rAnDoMcAsE was moved to a separate sPoNgEcAsE funbox mode. ### Changes - `rAnDoMcAsE` becomes `raNDOmcASe` and has a 50% chance to capitalize every letter. - `sPoNgEcAsE` is added as a funbox mode and contains the old functionality of `rAnDoMcAsE` - "i KINda LikE HoW inEFFICIeNt QwErtY Is." challenge is updated to use the updated `raNDOmcASe` mode as well as a new title that is in proper random case. ### Checks - [x] Adding/modifying Typescript code? - [ ] I have used `qs`, `qsa` or `qsr` instead of JQuery selectors. - [ ] 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 screenshots 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. - [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. --------- Co-authored-by: Miodec --- .../src/ts/test/funbox/funbox-functions.ts | 32 +++++++++++++------ frontend/static/challenges/_list.json | 8 ++--- packages/funbox/src/list.ts | 10 +++++- packages/schemas/src/configs.ts | 1 + 4 files changed, 37 insertions(+), 14 deletions(-) diff --git a/frontend/src/ts/test/funbox/funbox-functions.ts b/frontend/src/ts/test/funbox/funbox-functions.ts index 4810b36fbc74..200720604cc0 100644 --- a/frontend/src/ts/test/funbox/funbox-functions.ts +++ b/frontend/src/ts/test/funbox/funbox-functions.ts @@ -318,18 +318,32 @@ const list: Partial> = { }, rAnDoMcAsE: { alterText(word: string): string { - let randomcaseword = word[0] as string; - for (let i = 1; i < word.length; i++) { - if ( - randomcaseword[i - 1] === - (randomcaseword[i - 1] as string).toUpperCase() - ) { - randomcaseword += (word[i] as string).toLowerCase(); + let randomCaseWord = ""; + + for (let letter of word) { + if (Math.random() < 0.5) { + randomCaseWord += letter.toUpperCase(); } else { - randomcaseword += (word[i] as string).toUpperCase(); + randomCaseWord += letter.toLowerCase(); } } - return randomcaseword; + + return randomCaseWord; + }, + }, + sPoNgEcAsE: { + alterText(word: string): string { + let spongeCaseWord = ""; + + for (let i = 0; i < word.length; i++) { + if (i % 2 === 0) { + spongeCaseWord += word[i]?.toLowerCase(); + } else { + spongeCaseWord += word[i]?.toUpperCase(); + } + } + + return spongeCaseWord; }, }, rot13: { diff --git a/frontend/static/challenges/_list.json b/frontend/static/challenges/_list.json index 73564f3036f9..69d487158ea0 100644 --- a/frontend/static/challenges/_list.json +++ b/frontend/static/challenges/_list.json @@ -613,11 +613,11 @@ } }, { - "name": "iKiNdAlIkEhOwInEfFiCiEnTqWeRtYiS", - "display": "I kInDa LiKe HoW iNeFfIcIeNt QwErTy Is", + "name": "iKINdaLikEHoWinEFFICIeNtQwErtYIs.", + "display": "i KINda LikE HoW inEFFICIeNt QwErtY Is.", "autoRole": true, "type": "funbox", - "parameters": [["rAnDoMcAsE"], "time", 3600], + "parameters": [["sPoNgEcAsE"], "time", 3600], "requirements": { "wpm": { "min": 100 @@ -626,7 +626,7 @@ "min": 60 }, "funbox": { - "exact": ["rAnDoMcAsE"] + "exact": ["sPoNgEcAsE"] } } }, diff --git a/packages/funbox/src/list.ts b/packages/funbox/src/list.ts index bae05e7f6f77..f43ab93e8c80 100644 --- a/packages/funbox/src/list.ts +++ b/packages/funbox/src/list.ts @@ -114,13 +114,21 @@ const list: Record = { name: "arrows", }, rAnDoMcAsE: { - description: "I kInDa LiKe HoW iNeFfIcIeNt QwErTy Is.", + description: "raNdomIze ThE CApitaLizatIon Of EveRY LeTtEr.", canGetPb: false, difficultyLevel: 2, properties: ["changesCapitalisation"], frontendFunctions: ["alterText"], name: "rAnDoMcAsE", }, + sPoNgEcAsE: { + description: "I kInDa LiKe HoW iNeFfIcIeNt QwErTy Is.", + canGetPb: false, + difficultyLevel: 2, + properties: ["changesCapitalisation"], + frontendFunctions: ["alterText"], + name: "sPoNgEcAsE", + }, capitals: { description: "Capitalize Every Word.", canGetPb: false, diff --git a/packages/schemas/src/configs.ts b/packages/schemas/src/configs.ts index 21e374ebbe72..d6e8e1d510cf 100644 --- a/packages/schemas/src/configs.ts +++ b/packages/schemas/src/configs.ts @@ -280,6 +280,7 @@ export const FunboxNameSchema = z.enum([ "choo_choo", "arrows", "rAnDoMcAsE", + "sPoNgEcAsE", "capitals", "layout_mirror", "layoutfluid", From 1294499d0f89b7016cb8aef55f0aa7f99fb7ee51 Mon Sep 17 00:00:00 2001 From: Miodec Date: Tue, 6 Jan 2026 16:56:51 +0100 Subject: [PATCH 13/15] fix: themes ui list shows clipped when selected or hovered closes #7318 --- frontend/src/styles/settings.scss | 1 - frontend/src/ts/pages/settings.ts | 14 +++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/frontend/src/styles/settings.scss b/frontend/src/styles/settings.scss index 2dcc02cabd25..f37ed4b68c31 100644 --- a/frontend/src/styles/settings.scss +++ b/frontend/src/styles/settings.scss @@ -50,7 +50,6 @@ .settingsGroup { display: grid; gap: 2rem; - overflow: hidden; &.quickNav { justify-content: center; .links { diff --git a/frontend/src/ts/pages/settings.ts b/frontend/src/ts/pages/settings.ts index a9523702074b..125c18d18b73 100644 --- a/frontend/src/ts/pages/settings.ts +++ b/frontend/src/ts/pages/settings.ts @@ -753,26 +753,30 @@ function toggleSettingsGroup(groupName: string): void { const groupEl = qs(`.pageSettings .settingsGroup.${groupName}`); if (!groupEl?.hasClass("slideup")) { - groupEl?.animate({ + groupEl?.setStyle({ overflow: "hidden" })?.animate({ height: 0, duration: 250, onComplete: () => { - groupEl?.hide(); + groupEl + ?.hide() + .setStyle({ height: "", overflow: "" }) + .addClass("slideup"); }, }); - groupEl?.addClass("slideup"); $(`.pageSettings .sectionGroupTitle[group=${groupName}]`).addClass( "rotateIcon", ); } else { groupEl?.show(); - groupEl?.setStyle({ height: "" }); + groupEl?.setStyle({ height: "", overflow: "hidden" }); const height = groupEl.getOffsetHeight(); groupEl?.animate({ height: [0, height], duration: 250, + onComplete: () => { + groupEl?.setStyle({ height: "", overflow: "" }).removeClass("slideup"); + }, }); - groupEl?.removeClass("slideup"); $(`.pageSettings .sectionGroupTitle[group=${groupName}]`).removeClass( "rotateIcon", ); From 8d42ae057eb21bea8952ea41d557ecb32a565e9d Mon Sep 17 00:00:00 2001 From: Christian Fehmer Date: Tue, 6 Jan 2026 16:58:29 +0100 Subject: [PATCH 14/15] docs: remove jquery (@fehmer) (#7320) ### Description ### Checks - [ ] Adding/modifying Typescript code? - [ ] I have used `qs`, `qsa` or `qsr` instead of JQuery selectors. - [ ] 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 screenshots 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. Closes #7186 --- README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/README.md b/README.md index dff3d5bdbc96..f6dc3e426c80 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,6 @@ [![Firebase](https://img.shields.io/badge/firebase-ffca28?style=for-the-badge&logo=firebase&logoColor=black)](https://firebase.google.com/) [![Fontawesome](https://img.shields.io/badge/fontawesome-538DD7?style=for-the-badge&logo=fontawesome&logoColor=white)](https://fontawesome.com/) [![HTML5](https://img.shields.io/badge/html5-%23E34F26.svg?style=for-the-badge&logo=html5&logoColor=white)](https://developer.mozilla.org/en-US/docs/Web/HTML) -[![JQuery](https://img.shields.io/badge/jQuery-0769AD?style=for-the-badge&logo=jquery&logoColor=white)](https://jquery.com/) [![MongoDB](https://img.shields.io/badge/-MongoDB-13aa52?style=for-the-badge&logo=mongodb&logoColor=white)](https://www.mongodb.com/) [![OXLint](https://img.shields.io/badge/%E2%9A%93%20oxlint-2b3c5a?style=for-the-badge&logoColor=white)](https://oxc.rs/docs/guide/usage/linter.html) [![PNPM](https://img.shields.io/badge/pnpm-F69220?style=for-the-badge&logo=pnpm&logoColor=white)](https://pnpm.io/) From b9ee8b7d235dd6a28931be17899119075cc664ec Mon Sep 17 00:00:00 2001 From: Miodec Date: Tue, 6 Jan 2026 17:03:53 +0100 Subject: [PATCH 15/15] chore: bump oxc --- backend/package.json | 4 +- frontend/package.json | 4 +- frontend/src/email-handler.html | 192 +++++++++++--------- package.json | 6 +- packages/contracts/package.json | 4 +- packages/funbox/package.json | 4 +- packages/release/package.json | 4 +- packages/schemas/package.json | 4 +- packages/tsup-config/package.json | 4 +- packages/util/package.json | 4 +- pnpm-lock.yaml | 292 +++++++++++++++--------------- 11 files changed, 275 insertions(+), 247 deletions(-) diff --git a/backend/package.json b/backend/package.json index f78b40335a3b..d772d85b7920 100644 --- a/backend/package.json +++ b/backend/package.json @@ -80,8 +80,8 @@ "@vitest/coverage-v8": "4.0.15", "concurrently": "8.2.2", "openapi3-ts": "2.0.2", - "oxlint": "1.36.0", - "oxlint-tsgolint": "0.10.0", + "oxlint": "1.38.0", + "oxlint-tsgolint": "0.10.1", "readline-sync": "1.4.10", "supertest": "7.1.4", "testcontainers": "11.10.0", diff --git a/frontend/package.json b/frontend/package.json index b35a0c0be0ec..09d7b37315ab 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -83,8 +83,8 @@ "madge": "8.0.0", "magic-string": "0.30.17", "normalize.css": "8.0.1", - "oxlint": "1.36.0", - "oxlint-tsgolint": "0.10.0", + "oxlint": "1.38.0", + "oxlint-tsgolint": "0.10.1", "postcss": "8.4.31", "sass": "1.70.0", "subset-font": "2.3.0", diff --git a/frontend/src/email-handler.html b/frontend/src/email-handler.html index f0753f098988..9e24eb6b60cb 100644 --- a/frontend/src/email-handler.html +++ b/frontend/src/email-handler.html @@ -199,7 +199,9 @@ .then((resp) => { // Email address has been verified. - qs("main .preloader .icon")?.setHtml(``); + qs("main .preloader .icon")?.setHtml( + ``, + ); qs("main .preloader .text")?.setText( `Your email address has been verified`, ); @@ -207,7 +209,9 @@ }) .catch((error) => { console.error(error); - qs("main .preloader .icon")?.setHtml(``); + qs("main .preloader .icon")?.setHtml( + ``, + ); qs("main .preloader .text")?.setText( `Fatal error: ${error.message}. If this issue persists, please report it.`, ); @@ -234,8 +238,12 @@ .then((email) => { var accountEmail = email; - var newPassword = qs("main .resetPassword .pwd")?.getValue(); - var newPasswordConfirm = qs("main .resetPassword .pwd-confirm")?.getValue(); + var newPassword = + qs < HTMLInputElement > "main .resetPassword .pwd"?.getValue(); + var newPasswordConfirm = + qs < + HTMLInputElement > + "main .resetPassword .pwd-confirm"?.getValue(); if (newPassword !== newPasswordConfirm) { alert("Passwords do not match"); @@ -258,8 +266,12 @@ qs("main .preloader .icon")?.setHtml( ``, ); - qs("main .preloader .text")?.setText(`Your password has been changed`); - qs("main .preloader .subText")?.setText(`You can now close this tab`); + qs("main .preloader .text")?.setText( + `Your password has been changed`, + ); + qs("main .preloader .subText")?.setText( + `You can now close this tab`, + ); signInWithEmailAndPassword(Auth, accountEmail, newPassword); }) @@ -277,7 +289,9 @@ }) .catch((error) => { console.error(error); - qs("main .preloader .icon")?.setHtml(``); + qs("main .preloader .icon")?.setHtml( + ``, + ); qs("main .preloader .text")?.setText( `Fatal error: ${error.message}. If this issue persists, please report it.`, ); @@ -303,8 +317,12 @@ return applyActionCode(Auth, actionCode); }) .then(() => { - qs("main .preloader .icon")?.setHtml(``); - qs("main .preloader .text")?.setText(`Your account email was reverted.`); + qs("main .preloader .icon")?.setHtml( + ``, + ); + qs("main .preloader .text")?.setText( + `Your account email was reverted.`, + ); qs("main .preloader .subText")?.setText(``); qs("main .preloader")?.appendHtml(` @@ -325,7 +343,9 @@ }) .catch((error) => { console.error(error); - qs("main .preloader .icon")?.setHtml(``); + qs("main .preloader .icon")?.setHtml( + ``, + ); qs("main .preloader .text")?.setText(error.message); }); } @@ -333,13 +353,17 @@ function sendPasswordReset(email) { sendPasswordResetEmail(Auth, email) .then(() => { - qs("main .preloader .icon")?.setHtml(``); + qs("main .preloader .icon")?.setHtml( + ``, + ); qs("main .preloader .text")?.setText(`Password reset email sent`); qs("main .preloader .subText")?.setText(`Please check your inbox`); }) .catch((error) => { console.error(error); - qs("main .preloader .icon")?.setHtml(``); + qs("main .preloader .icon")?.setHtml( + ``, + ); qs("main .preloader .text")?.setText(error.message); }); } @@ -354,82 +378,86 @@ } onDOMReady(() => { - try { - // Get the action to complete. - var mode = getParameterByName("mode"); - // Get the one-time code from the query parameter. - var actionCode = getParameterByName("oobCode"); - // (Optional) Get the continue URL from the query parameter if available. - var continueUrl = getParameterByName("continueUrl"); - // (Optional) Get the language code if available. - var lang = getParameterByName("lang") || "en"; - - // Configure the Firebase SDK. - // // This is the minimum configuration required for the API to be used. - // var config = { - // 'apiKey': "YOU_API_KEY" // Copy this key from the web initialization - // // snippet found in the Firebase console. - // }; - // var app = firebase.initializeApp(config); - // var auth = firebase.auth(); - - if (!mode) { - qs("main .preloader .icon")?.setHtml( - ``, - ); - qs("main .preloader .text")?.setText(`Mode parameter not found`); - return; - } + try { + // Get the action to complete. + var mode = getParameterByName("mode"); + // Get the one-time code from the query parameter. + var actionCode = getParameterByName("oobCode"); + // (Optional) Get the continue URL from the query parameter if available. + var continueUrl = getParameterByName("continueUrl"); + // (Optional) Get the language code if available. + var lang = getParameterByName("lang") || "en"; + + // Configure the Firebase SDK. + // // This is the minimum configuration required for the API to be used. + // var config = { + // 'apiKey': "YOU_API_KEY" // Copy this key from the web initialization + // // snippet found in the Firebase console. + // }; + // var app = firebase.initializeApp(config); + // var auth = firebase.auth(); + + if (!mode) { + qs("main .preloader .icon")?.setHtml( + ``, + ); + qs("main .preloader .text")?.setText(`Mode parameter not found`); + return; + } + + if (!actionCode) { + qs("main .preloader .icon")?.setHtml( + ``, + ); + qs("main .preloader .text")?.setText( + `Action code parameter not found`, + ); + return; + } - if (!actionCode) { + // Handle the user management action. + switch (mode) { + case "resetPassword": + // Display reset password handler and UI. + qs("#logo .text span")?.setText("Reset Password"); + document.title = "Reset Password | Monkeytype"; + showResetPassword(); + break; + case "recoverEmail": + // Display email recovery handler and UI. + handleRecoverEmail(actionCode); + break; + case "verifyEmail": + qs("#logo .text span")?.setText("Verify Email"); + document.title = "Verify Email | Monkeytype"; + // Display email verification handler and UI. + handleVerifyEmail(actionCode, continueUrl); + break; + default: qs("main .preloader .icon")?.setHtml( ``, ); - qs("main .preloader .text")?.setText(`Action code parameter not found`); - return; - } - - // Handle the user management action. - switch (mode) { - case "resetPassword": - // Display reset password handler and UI. - qs("#logo .text span")?.setText("Reset Password"); - document.title = "Reset Password | Monkeytype"; - showResetPassword(); - break; - case "recoverEmail": - // Display email recovery handler and UI. - handleRecoverEmail(actionCode); - break; - case "verifyEmail": - qs("#logo .text span")?.setText("Verify Email"); - document.title = "Verify Email | Monkeytype"; - // Display email verification handler and UI. - handleVerifyEmail(actionCode, continueUrl); - break; - default: - qs("main .preloader .icon")?.setHtml( - ``, - ); - qs("main .preloader .text")?.setText(`Invalid mode`); - console.error("no mode found"); - // Error: invalid mode. - } + qs("main .preloader .text")?.setText(`Invalid mode`); + console.error("no mode found"); + // Error: invalid mode. + } - qs("main .resetPassword .button")?.on("click", () => { - handleResetPassword(actionCode, continueUrl); - }); + qs("main .resetPassword .button")?.on("click", () => { + handleResetPassword(actionCode, continueUrl); + }); - qs("main .resetPassword input")?.on("keypress", (e) => { - if (e.key === "Enter") handleResetPassword(actionCode, continueUrl); - }); - } catch (e) { - qs("main .preloader .icon")?.setHtml(``); - qs("main .preloader .text")?.setText( - `Fatal error: ${e.message}. If this issue persists, please report it.`, - ); - } - }); + qs("main .resetPassword input")?.on("keypress", (e) => { + if (e.key === "Enter") handleResetPassword(actionCode, continueUrl); + }); + } catch (e) { + qs("main .preloader .icon")?.setHtml( + ``, + ); + qs("main .preloader .text")?.setText( + `Fatal error: ${e.message}. If this issue persists, please report it.`, + ); + } + }); qs("header")?.on("click", () => { window.location = "/"; diff --git a/package.json b/package.json index c085818889f9..438ab7cbb222 100644 --- a/package.json +++ b/package.json @@ -65,9 +65,9 @@ "knip": "2.19.2", "lint-staged": "13.2.3", "only-allow": "1.2.1", - "oxfmt": "0.21.0", - "oxlint": "1.36.0", - "oxlint-tsgolint": "0.10.0", + "oxfmt": "0.23.0", + "oxlint": "1.38.0", + "oxlint-tsgolint": "0.10.1", "prettier": "3.7.1", "turbo": "2.5.6", "vitest": "4.0.15" diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 48cb8ce560ce..fb16dc57a539 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -29,8 +29,8 @@ "@monkeytype/tsup-config": "workspace:*", "@monkeytype/typescript-config": "workspace:*", "madge": "8.0.0", - "oxlint": "1.36.0", - "oxlint-tsgolint": "0.10.0", + "oxlint": "1.38.0", + "oxlint-tsgolint": "0.10.1", "tsup": "8.4.0", "typescript": "5.9.3", "vitest": "4.0.15" diff --git a/packages/funbox/package.json b/packages/funbox/package.json index 98917faefdc8..37ad69f22a19 100644 --- a/packages/funbox/package.json +++ b/packages/funbox/package.json @@ -25,8 +25,8 @@ "@monkeytype/tsup-config": "workspace:*", "@monkeytype/typescript-config": "workspace:*", "madge": "8.0.0", - "oxlint": "1.36.0", - "oxlint-tsgolint": "0.10.0", + "oxlint": "1.38.0", + "oxlint-tsgolint": "0.10.1", "tsup": "8.4.0", "typescript": "5.9.3", "vitest": "4.0.15" diff --git a/packages/release/package.json b/packages/release/package.json index 0224deaf7785..2f5015f6274b 100644 --- a/packages/release/package.json +++ b/packages/release/package.json @@ -20,7 +20,7 @@ }, "devDependencies": { "nodemon": "3.1.4", - "oxlint": "1.36.0", - "oxlint-tsgolint": "0.10.0" + "oxlint": "1.38.0", + "oxlint-tsgolint": "0.10.1" } } diff --git a/packages/schemas/package.json b/packages/schemas/package.json index c64be9fb3bd6..fffb14bcbcad 100644 --- a/packages/schemas/package.json +++ b/packages/schemas/package.json @@ -26,8 +26,8 @@ "@monkeytype/tsup-config": "workspace:*", "@monkeytype/typescript-config": "workspace:*", "madge": "8.0.0", - "oxlint": "1.36.0", - "oxlint-tsgolint": "0.10.0", + "oxlint": "1.38.0", + "oxlint-tsgolint": "0.10.1", "tsup": "8.4.0", "typescript": "5.9.3", "vitest": "4.0.15" diff --git a/packages/tsup-config/package.json b/packages/tsup-config/package.json index 82e5419a9175..56576aaa91f3 100644 --- a/packages/tsup-config/package.json +++ b/packages/tsup-config/package.json @@ -17,8 +17,8 @@ }, "devDependencies": { "@monkeytype/typescript-config": "workspace:*", - "oxlint": "1.36.0", - "oxlint-tsgolint": "0.10.0", + "oxlint": "1.38.0", + "oxlint-tsgolint": "0.10.1", "typescript": "5.9.3" }, "peerDependencies": { diff --git a/packages/util/package.json b/packages/util/package.json index dc46543b054e..c48994ae890a 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -20,8 +20,8 @@ "@monkeytype/tsup-config": "workspace:*", "@monkeytype/typescript-config": "workspace:*", "madge": "8.0.0", - "oxlint": "1.36.0", - "oxlint-tsgolint": "0.10.0", + "oxlint": "1.38.0", + "oxlint-tsgolint": "0.10.1", "tsup": "8.4.0", "typescript": "5.9.3", "vitest": "4.0.15", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 50c69e54238a..83e4030ce3af 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -36,14 +36,14 @@ importers: specifier: 1.2.1 version: 1.2.1 oxfmt: - specifier: 0.21.0 - version: 0.21.0 + specifier: 0.23.0 + version: 0.23.0 oxlint: - specifier: 1.36.0 - version: 1.36.0(oxlint-tsgolint@0.10.0) + specifier: 1.38.0 + version: 1.38.0(oxlint-tsgolint@0.10.1) oxlint-tsgolint: - specifier: 0.10.0 - version: 0.10.0 + specifier: 0.10.1 + version: 0.10.1 prettier: specifier: 3.7.1 version: 3.7.1 @@ -232,11 +232,11 @@ importers: specifier: 2.0.2 version: 2.0.2 oxlint: - specifier: 1.36.0 - version: 1.36.0(oxlint-tsgolint@0.10.0) + specifier: 1.38.0 + version: 1.38.0(oxlint-tsgolint@0.10.1) oxlint-tsgolint: - specifier: 0.10.0 - version: 0.10.0 + specifier: 0.10.1 + version: 0.10.1 readline-sync: specifier: 1.4.10 version: 1.4.10 @@ -437,11 +437,11 @@ importers: specifier: 8.0.1 version: 8.0.1 oxlint: - specifier: 1.36.0 - version: 1.36.0(oxlint-tsgolint@0.10.0) + specifier: 1.38.0 + version: 1.38.0(oxlint-tsgolint@0.10.1) oxlint-tsgolint: - specifier: 0.10.0 - version: 0.10.0 + specifier: 0.10.1 + version: 0.10.1 postcss: specifier: 8.4.31 version: 8.4.31 @@ -507,11 +507,11 @@ importers: specifier: 8.0.0 version: 8.0.0(typescript@5.9.3) oxlint: - specifier: 1.36.0 - version: 1.36.0(oxlint-tsgolint@0.10.0) + specifier: 1.38.0 + version: 1.38.0(oxlint-tsgolint@0.10.1) oxlint-tsgolint: - specifier: 0.10.0 - version: 0.10.0 + specifier: 0.10.1 + version: 0.10.1 tsup: specifier: 8.4.0 version: 8.4.0(postcss@8.5.6)(tsx@4.16.2)(typescript@5.9.3)(yaml@2.8.1) @@ -541,11 +541,11 @@ importers: specifier: 8.0.0 version: 8.0.0(typescript@5.9.3) oxlint: - specifier: 1.36.0 - version: 1.36.0(oxlint-tsgolint@0.10.0) + specifier: 1.38.0 + version: 1.38.0(oxlint-tsgolint@0.10.1) oxlint-tsgolint: - specifier: 0.10.0 - version: 0.10.0 + specifier: 0.10.1 + version: 0.10.1 tsup: specifier: 8.4.0 version: 8.4.0(postcss@8.5.6)(tsx@4.16.2)(typescript@5.9.3)(yaml@2.8.1) @@ -574,11 +574,11 @@ importers: specifier: 3.1.4 version: 3.1.4 oxlint: - specifier: 1.36.0 - version: 1.36.0(oxlint-tsgolint@0.10.0) + specifier: 1.38.0 + version: 1.38.0(oxlint-tsgolint@0.10.1) oxlint-tsgolint: - specifier: 0.10.0 - version: 0.10.0 + specifier: 0.10.1 + version: 0.10.1 packages/schemas: dependencies: @@ -596,11 +596,11 @@ importers: specifier: 8.0.0 version: 8.0.0(typescript@5.9.3) oxlint: - specifier: 1.36.0 - version: 1.36.0(oxlint-tsgolint@0.10.0) + specifier: 1.38.0 + version: 1.38.0(oxlint-tsgolint@0.10.1) oxlint-tsgolint: - specifier: 0.10.0 - version: 0.10.0 + specifier: 0.10.1 + version: 0.10.1 tsup: specifier: 8.4.0 version: 8.4.0(postcss@8.5.6)(tsx@4.16.2)(typescript@5.9.3)(yaml@2.8.1) @@ -621,11 +621,11 @@ importers: specifier: workspace:* version: link:../typescript-config oxlint: - specifier: 1.36.0 - version: 1.36.0(oxlint-tsgolint@0.10.0) + specifier: 1.38.0 + version: 1.38.0(oxlint-tsgolint@0.10.1) oxlint-tsgolint: - specifier: 0.10.0 - version: 0.10.0 + specifier: 0.10.1 + version: 0.10.1 typescript: specifier: 5.9.3 version: 5.9.3 @@ -644,11 +644,11 @@ importers: specifier: 8.0.0 version: 8.0.0(typescript@5.9.3) oxlint: - specifier: 1.36.0 - version: 1.36.0(oxlint-tsgolint@0.10.0) + specifier: 1.38.0 + version: 1.38.0(oxlint-tsgolint@0.10.1) oxlint-tsgolint: - specifier: 0.10.0 - version: 0.10.0 + specifier: 0.10.1 + version: 0.10.1 tsup: specifier: 8.4.0 version: 8.4.0(postcss@8.5.6)(tsx@4.16.2)(typescript@5.9.3)(yaml@2.8.1) @@ -2557,113 +2557,113 @@ packages: resolution: {integrity: sha512-aKcOkyrorBGlajjRdVoJWHTxfxO1vCNHLJVlSDaRHDIdjU+pX8IYQPvPDkYiujKLbRnWU+1TBwEt0QRgSm4SGA==} engines: {node: '>=14'} - '@oxfmt/darwin-arm64@0.21.0': - resolution: {integrity: sha512-defgGcchFCq2F7f5Nr3E4VXYW1sUhBGmIejgcPZ1gSsc8FAeT+vP5cSeGnDv+kcX+OKFDt89C67c31qZ6yZBsQ==} + '@oxfmt/darwin-arm64@0.23.0': + resolution: {integrity: sha512-shGng2EjBspvuqtFtcjcKf0WoZ9QCdL8iLYgdOoKSiSQ9pPyLJ4jQf62yhm4b2PpZNVcV/20gV6d8SyKzg6SZQ==} cpu: [arm64] os: [darwin] - '@oxfmt/darwin-x64@0.21.0': - resolution: {integrity: sha512-rYJinOZRabPF2V3kn0TWX4vcYHV2F+DkGewNP8HZ/OXQ3CEJKP+E7KCnEz/x614g3/S5J7cahr9l5Mr3AEZigA==} + '@oxfmt/darwin-x64@0.23.0': + resolution: {integrity: sha512-DxQ7Hm7B+6JiIkiRU3CSJmM15nTJDDezyaAv+x9NN8BfU0C49O8JuZIFu1Lr9AKEPV+ECIYM2X4HU0xm6IdiMQ==} cpu: [x64] os: [darwin] - '@oxfmt/linux-arm64-gnu@0.21.0': - resolution: {integrity: sha512-ILTv8stX3r2gK+pgSc2alJrbpI4i8zlLXzuuhUsjeEN/Ti//Z38MDi6kTov3pzcaBEnQ/xEMgQyczokp7jpyyQ==} + '@oxfmt/linux-arm64-gnu@0.23.0': + resolution: {integrity: sha512-7qTXPpENi45sEKsaYFit4VRywPVkX+ZJc5JVA17KW1coJ/SLUuRAdLjRipU+QTZsr1TF93HCmGFSlUjB7lmEVQ==} cpu: [arm64] os: [linux] - '@oxfmt/linux-arm64-musl@0.21.0': - resolution: {integrity: sha512-kFZ0vPJzsGjkrwq2MPEpp8TjV7/Znv9kCEwLF+HcFwvfcSt75dWloGmTRRrViH0ACaCM7YBSDUOV8E4nyLvxPA==} + '@oxfmt/linux-arm64-musl@0.23.0': + resolution: {integrity: sha512-qkFXbf+K01B++j69o9mLvvyfhmmL4+qX7hGPA2PRDkE5xxuUTWdqboQQc1FgGI0teUlIYYyxjamq9UztL2A7NA==} cpu: [arm64] os: [linux] - '@oxfmt/linux-x64-gnu@0.21.0': - resolution: {integrity: sha512-VH8ZcS2TkTBE0v9cLxjNGX++vB9Xvx/7VTFrbwHYzY/fYypYTwQ+n1KplUQoU+LrMC0nKqwPWYzvA5/cAfo5zg==} + '@oxfmt/linux-x64-gnu@0.23.0': + resolution: {integrity: sha512-J7Q13Ujyn8IgjHD96urA377GOy8HerxC13OrEyYaM8iwH3gc/EoboK9AKu0bxp9qai4btPFDhnkRnpCwJE9pAw==} cpu: [x64] os: [linux] - '@oxfmt/linux-x64-musl@0.21.0': - resolution: {integrity: sha512-qleaVEFHw/kmbvNj3hjobX1kwbP2/d7SVJzQjyEFULou1v3EZj7jWbblIu7GmDCSspdiEk1j/pZDYH801Dn8QA==} + '@oxfmt/linux-x64-musl@0.23.0': + resolution: {integrity: sha512-3gb25Zk2/y4An8fi399KdpLkDYFTJEB5Nq/sSHmeXG0pZlR/jnKoXEFHsjU+9nqF2wsuZ+tmkoi/swcaGG8+Qg==} cpu: [x64] os: [linux] - '@oxfmt/win32-arm64@0.21.0': - resolution: {integrity: sha512-JLZUo5qEyJfxhoj6KEU/CqI8FQlzIP8rBq7qGTq0kCJ2yZJC9tysBqJYZXvX88ShiNe89/T/H3khodaKGBBNgg==} + '@oxfmt/win32-arm64@0.23.0': + resolution: {integrity: sha512-JKfRP2ENWwRZ73rMZFyChvRi/+oDEW+3obp1XIwecot8gvDHgGZ4nX3hTp4VPiBFL89JORMpWSKzJvjRDucJIw==} cpu: [arm64] os: [win32] - '@oxfmt/win32-x64@0.21.0': - resolution: {integrity: sha512-DYNpbuPzUhTuWUIqDhwSaV1mK+VcknD4ANaEON+/ygaNGriSZ4pRUt1BTRcXfcOF9GZ4BO9udjv31S0bAEsFeQ==} + '@oxfmt/win32-x64@0.23.0': + resolution: {integrity: sha512-vgqtYK1X1n/KexCNQKWXao3hyOnmWuCzk2sQyCSpkLhjSNIDPm7dmnEkvOXhf1t0O5RjCwHpk2VB6Fuaq3GULg==} cpu: [x64] os: [win32] - '@oxlint-tsgolint/darwin-arm64@0.10.0': - resolution: {integrity: sha512-mhBF/pjey0UdLL1ocU46Fqta+uJuRfqrLfDpcViRg17BtDiUNd8JY9iN2FOoS2HGSCAgCUjZ0AZkwkHwFs/VTw==} + '@oxlint-tsgolint/darwin-arm64@0.10.1': + resolution: {integrity: sha512-KGC4++BeEqrIcmDHiJt/e6/860PWJmUJjjp0mE+smpBmRXMjmOFFjrPmN+ZyCyVgf1WdmhPkQXsRSPeTR+2omw==} cpu: [arm64] os: [darwin] - '@oxlint-tsgolint/darwin-x64@0.10.0': - resolution: {integrity: sha512-roLi34mw/i1z+NS7luboix55SXyhVv38dNUTcRDkk+0lNPzI9ngrM+1y1N2oBSUmz5o9OZGnfJJ7BSGCw/fFEQ==} + '@oxlint-tsgolint/darwin-x64@0.10.1': + resolution: {integrity: sha512-tvmrDgj3Q0tdc+zMWfCVLVq8EQDEUqasm1zaWgSMYIszpID6qdgqbT+OpWWXV9fLZgtvrkoXGwxkHAUJzdVZXQ==} cpu: [x64] os: [darwin] - '@oxlint-tsgolint/linux-arm64@0.10.0': - resolution: {integrity: sha512-HL9NThPH1V2F6l9XhwNmhQZUknN4m4yQYEvQFFGfZTYN6cvEEBIiqfF4KvBUg8c0xadMbQlW+Ug7/ybA9Nn+CA==} + '@oxlint-tsgolint/linux-arm64@0.10.1': + resolution: {integrity: sha512-7kD28z6/ykGx8WetKTPRZt30pd+ziassxg/8cM24lhjUI+hNXyRHVtHes73dh9D6glJKno+1ut+3amUdZBZcpQ==} cpu: [arm64] os: [linux] - '@oxlint-tsgolint/linux-x64@0.10.0': - resolution: {integrity: sha512-Tw8QNq8ab+4+qE5krvJyMA66v6XE3GoiISRD5WmJ7YOxUnu//jSw/bBm7OYf/TNEZyeV0BTR7zXzhT5R+VFWlQ==} + '@oxlint-tsgolint/linux-x64@0.10.1': + resolution: {integrity: sha512-NmJmiqdzYUTHIxteSTyX6IFFgnIsOAjRWXfrS6Jbo5xlB3g39WHniSF3asB/khLJNtwSg4InUS34NprYM7zrEw==} cpu: [x64] os: [linux] - '@oxlint-tsgolint/win32-arm64@0.10.0': - resolution: {integrity: sha512-LTogmTRwpwQqVaH1Ama8Wd5/VVZWBSF8v5qTbeT628+1F5Kt1V5eHBvyFh4oN18UCZlgqrh7DqkDhsieXUaC8Q==} + '@oxlint-tsgolint/win32-arm64@0.10.1': + resolution: {integrity: sha512-3KrT80vl3nXUkjuJI/z8dF6xWsKx0t9Tz4ZQHgQw3fYw+CoihBRWGklrdlmCz+EGfMyVaQLqBV9PZckhSqLe2A==} cpu: [arm64] os: [win32] - '@oxlint-tsgolint/win32-x64@0.10.0': - resolution: {integrity: sha512-ygqxx8EmNWy9/wCQS5uXq9k/o2EyYNwNxY1ZHNzlmZC/kV06Aemx5OBDafefawBNqH7xTZPfccUrjdiy+QlTrw==} + '@oxlint-tsgolint/win32-x64@0.10.1': + resolution: {integrity: sha512-hW1fSJZVxG51sLdGq1sQjOzb1tsQ23z/BquJfUwL7CqBobxr7TJvGmoINL+9KryOJt0jCoaiMfWe4yoYw5XfIA==} cpu: [x64] os: [win32] - '@oxlint/darwin-arm64@1.36.0': - resolution: {integrity: sha512-MJkj82GH+nhvWKJhSIM6KlZ8tyGKdogSQXtNdpIyP02r/tTayFJQaAEWayG2Jhsn93kske+nimg5MYFhwO/rlg==} + '@oxlint/darwin-arm64@1.38.0': + resolution: {integrity: sha512-9rN3047QTyA4i73FKikDUBdczRcLtOsIwZ5TsEx5Q7jr5nBjolhYQOFQf9QdhBLdInxw1iX4+lgdMCf1g74zjg==} cpu: [arm64] os: [darwin] - '@oxlint/darwin-x64@1.36.0': - resolution: {integrity: sha512-VvEhfkqj/99dCTqOcfkyFXOSbx4lIy5u2m2GHbK4WCMDySokOcMTNRHGw8fH/WgQ5cDrDMSTYIGQTmnBGi9tiQ==} + '@oxlint/darwin-x64@1.38.0': + resolution: {integrity: sha512-Y1UHW4KOlg5NvyrSn/bVBQP8/LRuid7Pnu+BWGbAVVsFcK0b565YgMSO3Eu9nU3w8ke91dr7NFpUmS+bVkdkbw==} cpu: [x64] os: [darwin] - '@oxlint/linux-arm64-gnu@1.36.0': - resolution: {integrity: sha512-EMx92X5q+hHc3olTuj/kgkx9+yP0p/AVs4yvHbUfzZhBekXNpUWxWvg4hIKmQWn+Ee2j4o80/0ACGO0hDYJ9mg==} + '@oxlint/linux-arm64-gnu@1.38.0': + resolution: {integrity: sha512-ZiVxPZizlXSnAMdkEFWX/mAj7U3bNiku8p6I9UgLrXzgGSSAhFobx8CaFGwVoKyWOd+gQgZ/ogCrunvx2k0CFg==} cpu: [arm64] os: [linux] - '@oxlint/linux-arm64-musl@1.36.0': - resolution: {integrity: sha512-7YCxtrPIctVYLqWrWkk8pahdCxch6PtsaucfMLC7TOlDt4nODhnQd4yzEscKqJ8Gjrw1bF4g+Ngob1gB+Qr9Fw==} + '@oxlint/linux-arm64-musl@1.38.0': + resolution: {integrity: sha512-ELtlCIGZ72A65ATZZHFxHMFrkRtY+DYDCKiNKg6v7u5PdeOFey+OlqRXgXtXlxWjCL+g7nivwI2FPVsWqf05Qw==} cpu: [arm64] os: [linux] - '@oxlint/linux-x64-gnu@1.36.0': - resolution: {integrity: sha512-lnaJVlx5r3NWmoOMesfQXJSf78jHTn8Z+sdAf795Kgteo72+qGC1Uax2SToCJVN2J8PNG3oRV5bLriiCNR2i6Q==} + '@oxlint/linux-x64-gnu@1.38.0': + resolution: {integrity: sha512-E1OcDh30qyng1m0EIlsOuapYkqk5QB6o6IMBjvDKqIoo6IrjlVAasoJfS/CmSH998gXRL3BcAJa6Qg9IxPFZnQ==} cpu: [x64] os: [linux] - '@oxlint/linux-x64-musl@1.36.0': - resolution: {integrity: sha512-AhuEU2Qdl66lSfTGu/Htirq8r/8q2YnZoG3yEXLMQWnPMn7efy8spD/N1NA7kH0Hll+cdfwgQkQqC2G4MS2lPQ==} + '@oxlint/linux-x64-musl@1.38.0': + resolution: {integrity: sha512-4AfpbM/4sQnr6S1dMijEPfsq4stQbN5vJ2jsahSy/QTcvIVbFkgY+RIhrA5UWlC6eb0rD5CdaPQoKGMJGeXpYw==} cpu: [x64] os: [linux] - '@oxlint/win32-arm64@1.36.0': - resolution: {integrity: sha512-GlWCBjUJY2QgvBFuNRkiRJu7K/djLmM0UQKfZV8IN+UXbP/JbjZHWKRdd4LXlQmzoz7M5Hd6p+ElCej8/90FCg==} + '@oxlint/win32-arm64@1.38.0': + resolution: {integrity: sha512-OvUVYdI68OwXh3d1RjH9N/okCxb6PrOGtEtzXyqGA7Gk+IxyZcX0/QCTBwV8FNbSSzDePSSEHOKpoIB+VXdtvg==} cpu: [arm64] os: [win32] - '@oxlint/win32-x64@1.36.0': - resolution: {integrity: sha512-J+Vc00Utcf8p77lZPruQgb0QnQXuKnFogN88kCnOqs2a83I+vTBB8ILr0+L9sTwVRvIDMSC0pLdeQH4svWGFZg==} + '@oxlint/win32-x64@1.38.0': + resolution: {integrity: sha512-7IuZMYiZiOcgg5zHvpJY6jRlEwh8EB/uq7GsoQJO9hANq96TIjyntGByhIjFSsL4asyZmhTEki+MO/u5Fb/WQA==} cpu: [x64] os: [win32] @@ -3800,8 +3800,8 @@ packages: base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} - baseline-browser-mapping@2.9.10: - resolution: {integrity: sha512-2VIKvDx8Z1a9rTB2eCkdPE5nSe28XnA+qivGnWHoB40hMMt/h1hSz0960Zqsn6ZyxWXUie0EBdElKv8may20AA==} + baseline-browser-mapping@2.9.11: + resolution: {integrity: sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==} hasBin: true basic-auth-connect@1.0.0: @@ -3999,8 +3999,8 @@ packages: caniuse-lite@1.0.30001715: resolution: {integrity: sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw==} - caniuse-lite@1.0.30001761: - resolution: {integrity: sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==} + caniuse-lite@1.0.30001762: + resolution: {integrity: sha512-PxZwGNvH7Ak8WX5iXzoK1KPZttBXNPuaOvI2ZYU7NrlM+d9Ov+TUvlLOBNGzVXAntMSMMlJPd+jY6ovrVjSmUw==} canvas-confetti@1.5.1: resolution: {integrity: sha512-Ncz+oZJP6OvY7ti4E1slxVlyAV/3g7H7oQtcCDXgwGgARxPnwYY9PW5Oe+I8uvspYNtuHviAdgA0LfcKFWJfpg==} @@ -7242,17 +7242,17 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} - oxfmt@0.21.0: - resolution: {integrity: sha512-EXK5pd1kGbI8hp9Ld69oy/ObAoe+gfH3dYHBviKqwSAHNkAHiqxWF1hnrWj5oun1GnQ8bVpqBMMVXJESMx6/+g==} + oxfmt@0.23.0: + resolution: {integrity: sha512-dh4rlNBua93aVf2ZaDecbQxVLMnUUTvDi1K1fdvBdontQeEf6K22Z1KQg5QKl2D9aNFeFph+wOVwcjjYUIO6Mw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true - oxlint-tsgolint@0.10.0: - resolution: {integrity: sha512-LDDSIu5J/4D4gFUuQQIEQpAC6maNEbMg4nC8JL/+Pe0cUDR86dtVZ09E2x5MwCh8f9yfktoaxt5x6UIVyzrajg==} + oxlint-tsgolint@0.10.1: + resolution: {integrity: sha512-EEHNdo5cW2w1xwYdBQ7d3IXDqWAtMkfVFrh+9gQ4kYbYJwygY4QXSh1eH80/xVipZdVKujAwBgg/nNNHk56kxQ==} hasBin: true - oxlint@1.36.0: - resolution: {integrity: sha512-IicUdXfXgI8OKrDPnoSjvBfeEF8PkKtm+CoLlg4LYe4ypc8U+T4r7730XYshdBGZdelg+JRw8GtCb2w/KaaZvw==} + oxlint@1.38.0: + resolution: {integrity: sha512-XT7tBinQS+hVLxtfJOnokJ9qVBiQvZqng40tDgR6qEJMRMnpVq/JwYfbYyGntSq8MO+Y+N9M1NG4bAMFUtCJiw==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true peerDependencies: @@ -11726,70 +11726,70 @@ snapshots: '@opentelemetry/semantic-conventions@1.34.0': {} - '@oxfmt/darwin-arm64@0.21.0': + '@oxfmt/darwin-arm64@0.23.0': optional: true - '@oxfmt/darwin-x64@0.21.0': + '@oxfmt/darwin-x64@0.23.0': optional: true - '@oxfmt/linux-arm64-gnu@0.21.0': + '@oxfmt/linux-arm64-gnu@0.23.0': optional: true - '@oxfmt/linux-arm64-musl@0.21.0': + '@oxfmt/linux-arm64-musl@0.23.0': optional: true - '@oxfmt/linux-x64-gnu@0.21.0': + '@oxfmt/linux-x64-gnu@0.23.0': optional: true - '@oxfmt/linux-x64-musl@0.21.0': + '@oxfmt/linux-x64-musl@0.23.0': optional: true - '@oxfmt/win32-arm64@0.21.0': + '@oxfmt/win32-arm64@0.23.0': optional: true - '@oxfmt/win32-x64@0.21.0': + '@oxfmt/win32-x64@0.23.0': optional: true - '@oxlint-tsgolint/darwin-arm64@0.10.0': + '@oxlint-tsgolint/darwin-arm64@0.10.1': optional: true - '@oxlint-tsgolint/darwin-x64@0.10.0': + '@oxlint-tsgolint/darwin-x64@0.10.1': optional: true - '@oxlint-tsgolint/linux-arm64@0.10.0': + '@oxlint-tsgolint/linux-arm64@0.10.1': optional: true - '@oxlint-tsgolint/linux-x64@0.10.0': + '@oxlint-tsgolint/linux-x64@0.10.1': optional: true - '@oxlint-tsgolint/win32-arm64@0.10.0': + '@oxlint-tsgolint/win32-arm64@0.10.1': optional: true - '@oxlint-tsgolint/win32-x64@0.10.0': + '@oxlint-tsgolint/win32-x64@0.10.1': optional: true - '@oxlint/darwin-arm64@1.36.0': + '@oxlint/darwin-arm64@1.38.0': optional: true - '@oxlint/darwin-x64@1.36.0': + '@oxlint/darwin-x64@1.38.0': optional: true - '@oxlint/linux-arm64-gnu@1.36.0': + '@oxlint/linux-arm64-gnu@1.38.0': optional: true - '@oxlint/linux-arm64-musl@1.36.0': + '@oxlint/linux-arm64-musl@1.38.0': optional: true - '@oxlint/linux-x64-gnu@1.36.0': + '@oxlint/linux-x64-gnu@1.38.0': optional: true - '@oxlint/linux-x64-musl@1.36.0': + '@oxlint/linux-x64-musl@1.38.0': optional: true - '@oxlint/win32-arm64@1.36.0': + '@oxlint/win32-arm64@1.38.0': optional: true - '@oxlint/win32-x64@1.36.0': + '@oxlint/win32-x64@1.38.0': optional: true '@paralleldrive/cuid2@2.2.2': @@ -12997,7 +12997,7 @@ snapshots: base64-js@1.5.1: {} - baseline-browser-mapping@2.9.10: {} + baseline-browser-mapping@2.9.11: {} basic-auth-connect@1.0.0: {} @@ -13134,8 +13134,8 @@ snapshots: browserslist@4.28.0: dependencies: - baseline-browser-mapping: 2.9.10 - caniuse-lite: 1.0.30001761 + baseline-browser-mapping: 2.9.11 + caniuse-lite: 1.0.30001762 electron-to-chromium: 1.5.267 node-releases: 2.0.27 update-browserslist-db: 1.2.3(browserslist@4.28.0) @@ -13263,7 +13263,7 @@ snapshots: caniuse-lite@1.0.30001715: {} - caniuse-lite@1.0.30001761: {} + caniuse-lite@1.0.30001762: {} canvas-confetti@1.5.1: {} @@ -17187,39 +17187,39 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - oxfmt@0.21.0: + oxfmt@0.23.0: dependencies: tinypool: 2.0.0 optionalDependencies: - '@oxfmt/darwin-arm64': 0.21.0 - '@oxfmt/darwin-x64': 0.21.0 - '@oxfmt/linux-arm64-gnu': 0.21.0 - '@oxfmt/linux-arm64-musl': 0.21.0 - '@oxfmt/linux-x64-gnu': 0.21.0 - '@oxfmt/linux-x64-musl': 0.21.0 - '@oxfmt/win32-arm64': 0.21.0 - '@oxfmt/win32-x64': 0.21.0 - - oxlint-tsgolint@0.10.0: + '@oxfmt/darwin-arm64': 0.23.0 + '@oxfmt/darwin-x64': 0.23.0 + '@oxfmt/linux-arm64-gnu': 0.23.0 + '@oxfmt/linux-arm64-musl': 0.23.0 + '@oxfmt/linux-x64-gnu': 0.23.0 + '@oxfmt/linux-x64-musl': 0.23.0 + '@oxfmt/win32-arm64': 0.23.0 + '@oxfmt/win32-x64': 0.23.0 + + oxlint-tsgolint@0.10.1: optionalDependencies: - '@oxlint-tsgolint/darwin-arm64': 0.10.0 - '@oxlint-tsgolint/darwin-x64': 0.10.0 - '@oxlint-tsgolint/linux-arm64': 0.10.0 - '@oxlint-tsgolint/linux-x64': 0.10.0 - '@oxlint-tsgolint/win32-arm64': 0.10.0 - '@oxlint-tsgolint/win32-x64': 0.10.0 - - oxlint@1.36.0(oxlint-tsgolint@0.10.0): + '@oxlint-tsgolint/darwin-arm64': 0.10.1 + '@oxlint-tsgolint/darwin-x64': 0.10.1 + '@oxlint-tsgolint/linux-arm64': 0.10.1 + '@oxlint-tsgolint/linux-x64': 0.10.1 + '@oxlint-tsgolint/win32-arm64': 0.10.1 + '@oxlint-tsgolint/win32-x64': 0.10.1 + + oxlint@1.38.0(oxlint-tsgolint@0.10.1): optionalDependencies: - '@oxlint/darwin-arm64': 1.36.0 - '@oxlint/darwin-x64': 1.36.0 - '@oxlint/linux-arm64-gnu': 1.36.0 - '@oxlint/linux-arm64-musl': 1.36.0 - '@oxlint/linux-x64-gnu': 1.36.0 - '@oxlint/linux-x64-musl': 1.36.0 - '@oxlint/win32-arm64': 1.36.0 - '@oxlint/win32-x64': 1.36.0 - oxlint-tsgolint: 0.10.0 + '@oxlint/darwin-arm64': 1.38.0 + '@oxlint/darwin-x64': 1.38.0 + '@oxlint/linux-arm64-gnu': 1.38.0 + '@oxlint/linux-arm64-musl': 1.38.0 + '@oxlint/linux-x64-gnu': 1.38.0 + '@oxlint/linux-x64-musl': 1.38.0 + '@oxlint/win32-arm64': 1.38.0 + '@oxlint/win32-x64': 1.38.0 + oxlint-tsgolint: 0.10.1 p-defer@3.0.0: {}