diff options
author | Christian Fehmer <[email protected]> | 2024-12-22 21:39:30 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2024-12-22 21:39:30 +0100 |
commit | ca166a436af8da5a5577b90b95b7cb3b9645b128 (patch) | |
tree | 087ef36d420308a43a80856e12c77c7193fa7ad5 | |
parent | e26eb65fdd0522c32b5fdc841cf9939de05026fe (diff) | |
parent | 353fc14b4ee19ac9c129ff0886f7d21bcafaf9b9 (diff) | |
download | monkeytype-ca166a436af8da5a5577b90b95b7cb3b9645b128.tar.gz monkeytype-ca166a436af8da5a5577b90b95b7cb3b9645b128.zip |
Merge branch 'master' into feature/fix-crt-indicate-typosfeature/fix-crt-indicate-typos
-rw-r--r-- | frontend/src/ts/controllers/account-controller.ts | 6 | ||||
-rw-r--r-- | frontend/src/ts/controllers/input-controller.ts | 6 | ||||
-rw-r--r-- | frontend/src/ts/db.ts | 3 | ||||
-rw-r--r-- | frontend/src/ts/ready.ts | 13 | ||||
-rw-r--r-- | frontend/src/ts/test/test-stats.ts | 2 | ||||
-rw-r--r-- | frontend/src/ts/test/test-timer.ts | 11 | ||||
-rw-r--r-- | frontend/src/ts/utils/misc.ts | 21 | ||||
-rw-r--r-- | frontend/src/ts/utils/url-handler.ts | 6 | ||||
-rw-r--r-- | frontend/static/languages/_groups.json | 1 | ||||
-rw-r--r-- | frontend/static/languages/_list.json | 1 | ||||
-rw-r--r-- | frontend/static/languages/code_typst.json | 50 | ||||
-rw-r--r-- | frontend/static/languages/polish_2k.json | 1 | ||||
-rw-r--r-- | frontend/static/quotes/dutch.json | 24 | ||||
-rw-r--r-- | frontend/static/quotes/english.json | 2 | ||||
-rw-r--r-- | packages/contracts/src/users.ts | 2 | ||||
-rw-r--r-- | packages/funbox/__test__/utils.spec.ts | 20 | ||||
-rw-r--r-- | packages/util/__test__/json.spec.ts | 42 | ||||
-rw-r--r-- | packages/util/package.json | 3 | ||||
-rw-r--r-- | packages/util/src/json.ts | 27 | ||||
-rw-r--r-- | pnpm-lock.yaml | 3 |
20 files changed, 202 insertions, 42 deletions
diff --git a/frontend/src/ts/controllers/account-controller.ts b/frontend/src/ts/controllers/account-controller.ts index 70191802c..c60b5d21e 100644 --- a/frontend/src/ts/controllers/account-controller.ts +++ b/frontend/src/ts/controllers/account-controller.ts @@ -48,6 +48,7 @@ import { navigate } from "./route-controller"; import { FirebaseError } from "firebase/app"; import * as PSA from "../elements/psa"; import defaultResultFilters from "../constants/default-result-filters"; +import { getActiveFunboxes } from "../test/funbox/list"; export const gmailProvider = new GoogleAuthProvider(); export const githubProvider = new GithubAuthProvider(); @@ -171,6 +172,11 @@ async function getDataAndInit(): Promise<boolean> { ); await UpdateConfig.apply(snapshot.config); UpdateConfig.saveFullConfigToLocalStorage(true); + + //funboxes might be different and they wont activate on the account page + for (const fb of getActiveFunboxes()) { + fb.functions?.applyGlobalCSS?.(); + } } AccountButton.loading(false); TagController.loadActiveFromLocalStorage(); diff --git a/frontend/src/ts/controllers/input-controller.ts b/frontend/src/ts/controllers/input-controller.ts index dcb263ca9..50a7c8bc4 100644 --- a/frontend/src/ts/controllers/input-controller.ts +++ b/frontend/src/ts/controllers/input-controller.ts @@ -425,12 +425,14 @@ function isCharCorrect(char: string, charIndex: number): boolean { char === "‘" || char === "'" || char === "ʼ" || - char === "׳") && + char === "׳" || + char === "ʻ") && (originalChar === "’" || originalChar === "‘" || originalChar === "'" || originalChar === "ʼ" || - originalChar === "׳") + originalChar === "׳" || + originalChar === "ʻ") ) { return true; } diff --git a/frontend/src/ts/db.ts b/frontend/src/ts/db.ts index ff437e07f..8accd57c2 100644 --- a/frontend/src/ts/db.ts +++ b/frontend/src/ts/db.ts @@ -372,6 +372,9 @@ export async function getUserResults(offset?: number): Promise<boolean> { return false; } + //another check in case user logs out while waiting for response + if (!isAuthenticated()) return false; + const results: SnapshotResult<Mode>[] = response.body.data.map((result) => { if (result.bailedOut === undefined) result.bailedOut = false; if (result.blindMode === undefined) result.blindMode = false; diff --git a/frontend/src/ts/ready.ts b/frontend/src/ts/ready.ts index e1b923688..695c82478 100644 --- a/frontend/src/ts/ready.ts +++ b/frontend/src/ts/ready.ts @@ -8,8 +8,10 @@ import * as AccountButton from "./elements/account-button"; import Konami from "konami"; import * as ServerConfiguration from "./ape/server-configuration"; import { getActiveFunboxes } from "./test/funbox/list"; +import { loadPromise } from "./config"; -$((): void => { +$(async (): Promise<void> => { + await loadPromise; Misc.loadCSS("/css/slimselect.min.css", true); Misc.loadCSS("/css/balloon.min.css", true); @@ -19,11 +21,10 @@ $((): void => { //to make sure the initial theme application doesnt animate the background color $("body").css("transition", "background .25s, transform .05s"); MerchBanner.showIfNotClosedBefore(); - setTimeout(() => { - for (const fb of getActiveFunboxes()) { - fb.functions?.applyGlobalCSS?.(); - } - }, 500); //this approach will probably bite me in the ass at some point + + for (const fb of getActiveFunboxes()) { + fb.functions?.applyGlobalCSS?.(); + } $("#app") .css("opacity", "0") diff --git a/frontend/src/ts/test/test-stats.ts b/frontend/src/ts/test/test-stats.ts index b69cc6b97..96360a570 100644 --- a/frontend/src/ts/test/test-stats.ts +++ b/frontend/src/ts/test/test-stats.ts @@ -52,6 +52,8 @@ export function getStats(): unknown { lastResult, start, end, + start3, + end3, afkHistory: TestInput.afkHistory, errorHistory: TestInput.errorHistory, wpmHistory: TestInput.wpmHistory, diff --git a/frontend/src/ts/test/test-timer.ts b/frontend/src/ts/test/test-timer.ts index 1cbf5e19f..e8ba4416d 100644 --- a/frontend/src/ts/test/test-timer.ts +++ b/frontend/src/ts/test/test-timer.ts @@ -129,7 +129,7 @@ function layoutfluid(): void { function checkIfFailed( wpmAndRaw: { wpm: number; raw: number }, acc: number -): void { +): boolean { if (timerDebug) console.time("fail conditions"); TestInput.pushKeypressesToHistory(); TestInput.pushErrorToHistory(); @@ -143,16 +143,17 @@ function checkIfFailed( SlowTimer.clear(); slowTimerCount = 0; TimerEvent.dispatch("fail", "min speed"); - return; + return true; } if (Config.minAcc === "custom" && acc < Config.minAccCustom) { if (timer !== null) clearTimeout(timer); SlowTimer.clear(); slowTimerCount = 0; TimerEvent.dispatch("fail", "min accuracy"); - return; + return true; } if (timerDebug) console.timeEnd("fail conditions"); + return false; } function checkIfTimeIsUp(): void { @@ -200,8 +201,8 @@ async function timerStep(): Promise<void> { const acc = calculateAcc(); monkey(wpmAndRaw); layoutfluid(); - checkIfFailed(wpmAndRaw, acc); - checkIfTimeIsUp(); + const failed = checkIfFailed(wpmAndRaw, acc); + if (!failed) checkIfTimeIsUp(); if (timerDebug) console.timeEnd("timer step -----------------------------"); } diff --git a/frontend/src/ts/utils/misc.ts b/frontend/src/ts/utils/misc.ts index 82651157c..3ff17bf4d 100644 --- a/frontend/src/ts/utils/misc.ts +++ b/frontend/src/ts/utils/misc.ts @@ -7,7 +7,6 @@ import { Mode2, PersonalBests, } from "@monkeytype/contracts/schemas/shared"; -import { ZodError, ZodSchema } from "zod"; import { CustomTextDataWithTextLen, Result, @@ -655,26 +654,6 @@ export function isObject(obj: unknown): obj is Record<string, unknown> { return typeof obj === "object" && !Array.isArray(obj) && obj !== null; } -/** - * Parse a JSON string into an object and validate it against a schema - * @param input JSON string - * @param schema Zod schema to validate the JSON against - * @returns The parsed JSON object - */ -export function parseJsonWithSchema<T>(input: string, schema: ZodSchema<T>): T { - try { - const jsonParsed = JSON.parse(input) as unknown; - const zodParsed = schema.parse(jsonParsed); - return zodParsed; - } catch (error) { - if (error instanceof ZodError) { - throw new Error(error.errors.map((err) => err.message).join("\n")); - } else { - throw error; - } - } -} - export function deepClone<T>(obj: T[]): T[]; export function deepClone<T extends object>(obj: T): T; export function deepClone<T>(obj: T): T; diff --git a/frontend/src/ts/utils/url-handler.ts b/frontend/src/ts/utils/url-handler.ts index 7ba713e49..036e8d470 100644 --- a/frontend/src/ts/utils/url-handler.ts +++ b/frontend/src/ts/utils/url-handler.ts @@ -22,6 +22,7 @@ import { Difficulty, } from "@monkeytype/contracts/schemas/configs"; import { z } from "zod"; +import { parseWithSchema as parseJsonWithSchema } from "@monkeytype/util/json"; export async function linkDiscord(hashOverride: string): Promise<void> { if (!hashOverride) return; @@ -78,10 +79,7 @@ export function loadCustomThemeFromUrl(getOverride?: string): void { let decoded: z.infer<typeof customThemeUrlDataSchema>; try { - decoded = Misc.parseJsonWithSchema( - atob(getValue), - customThemeUrlDataSchema - ); + decoded = parseJsonWithSchema(atob(getValue), customThemeUrlDataSchema); } catch (e) { console.log("Custom theme URL decoding failed", e); Notifications.add( diff --git a/frontend/static/languages/_groups.json b/frontend/static/languages/_groups.json index 6335a4790..512b259e1 100644 --- a/frontend/static/languages/_groups.json +++ b/frontend/static/languages/_groups.json @@ -606,6 +606,7 @@ "code_lua", "code_luau", "code_latex", + "code_typst", "code_matlab", "code_sql", "code_perl", diff --git a/frontend/static/languages/_list.json b/frontend/static/languages/_list.json index c6b02836b..460cfbd13 100644 --- a/frontend/static/languages/_list.json +++ b/frontend/static/languages/_list.json @@ -339,6 +339,7 @@ ,"code_lua" ,"code_luau" ,"code_latex" + ,"code_typst" ,"code_matlab" ,"code_sql" ,"code_perl" diff --git a/frontend/static/languages/code_typst.json b/frontend/static/languages/code_typst.json new file mode 100644 index 000000000..bd9f85323 --- /dev/null +++ b/frontend/static/languages/code_typst.json @@ -0,0 +1,50 @@ +{ + "name": "code_typst", + "noLazyMode": true, + "ligatures": false, + "words": [ + "#use", + "#set par(justify: true)", + "#show", + "#set", + "#let", + "#par", + "#figure", + "#underline", + "#smallcaps", + "#grid", + "#box", + "#place", + "#import", + "#link", + "#lorem(50)", + "let", + "#{", + "}", + "#(", + ")", + "#[", + "]", + "$", + "@", + "*", + "-", + "_", + "\\", + "/", + "//", + "floor(x)", + "cal(A)", + "NN", + "RR", + ">", + "<", + ">=", + "gt.eq.not", + "sum_(k=1)^oo", + "pi", + "&=", + "vec", + "mat" + ] +} diff --git a/frontend/static/languages/polish_2k.json b/frontend/static/languages/polish_2k.json index e004e46d8..3eba85e53 100644 --- a/frontend/static/languages/polish_2k.json +++ b/frontend/static/languages/polish_2k.json @@ -2039,7 +2039,6 @@ "Bóg", "wybrać", "zjawisko", - "abugida", "według", "kara", "czas", diff --git a/frontend/static/quotes/dutch.json b/frontend/static/quotes/dutch.json index bc716cd88..fad54d712 100644 --- a/frontend/static/quotes/dutch.json +++ b/frontend/static/quotes/dutch.json @@ -396,6 +396,30 @@ "source": "Etty Hillesum", "length": 95, "id": 65 + }, + { + "text": "Geef al uw geld aan de arme mensen... als zij hetzelfde doen heb je het morgen misschien al terug.", + "source": "Herman Brusselmans", + "length": 98, + "id": 66 + }, + { + "text": "Schrap het woord 'ik' uit het taalgebruik en de hele mensheid staat met de mond vol tanden en het paniekzweet op het voorhoofd.", + "source": "Herman Brusselmans", + "length": 127, + "id": 67 + }, + { + "text": "Een James Bond-boek is stom maar opwindend, terwijl een meesterwerk van de Vlaamse literatuur even stom maar daarbij ook nog vervelend is.", + "source": "Louis Paul Boon", + "length": 138, + "id": 68 + }, + { + "text": "Ik ben absoluut tegen de puurheid van de taal. Als het iets wezenlijks meebrengt, moet je anglicismen, germanismen en gallicismen meteen cultiveren. Ik geloof niet in het uitgedunde, dat men voorhoudt als het enige Nederlands, ik irriteer me aan de Nederlandse overheersing.", + "source": "Hugo Claus", + "length": 274, + "id": 69 } ] } diff --git a/frontend/static/quotes/english.json b/frontend/static/quotes/english.json index 202b69bd2..28a20306c 100644 --- a/frontend/static/quotes/english.json +++ b/frontend/static/quotes/english.json @@ -1094,7 +1094,7 @@ "length": 204 }, { - "text": "There are mysteries to the universe we were never meant to solve, but who we are and why we are here, are not among them, those answers we carry inside.", + "text": "There are mysteries to the universe we were never meant to solve. But who we are and why we are here, are not among them. Those answers we carry inside.", "source": "Transformers: Age of Extinction", "id": 192, "length": 152 diff --git a/packages/contracts/src/users.ts b/packages/contracts/src/users.ts index 4a835284e..498f8af62 100644 --- a/packages/contracts/src/users.ts +++ b/packages/contracts/src/users.ts @@ -45,7 +45,7 @@ export const UserNameSchema = doesNotContainProfanity( .max(16) .regex( /^[\da-zA-Z_-]+$/, - "Can only contain lower/uppercase letters, underscare and minus." + "Can only contain lower/uppercase letters, underscore and minus." ) ); diff --git a/packages/funbox/__test__/utils.spec.ts b/packages/funbox/__test__/utils.spec.ts new file mode 100644 index 000000000..15e88156f --- /dev/null +++ b/packages/funbox/__test__/utils.spec.ts @@ -0,0 +1,20 @@ +import * as Util from "../src/util"; + +describe("util", () => { + describe("stringToFunboxNames", () => { + it("should get single funbox", () => { + expect(Util.stringToFunboxNames("58008")).toEqual(["58008"]); + }); + it("should fail for unknown funbox name", () => { + expect(() => Util.stringToFunboxNames("unknown")).toThrowError( + new Error("Invalid funbox name: unknown") + ); + }); + it("should split multiple funboxes by hash", () => { + expect(Util.stringToFunboxNames("58008#choo_choo")).toEqual([ + "58008", + "choo_choo", + ]); + }); + }); +}); diff --git a/packages/util/__test__/json.spec.ts b/packages/util/__test__/json.spec.ts new file mode 100644 index 000000000..008437a8f --- /dev/null +++ b/packages/util/__test__/json.spec.ts @@ -0,0 +1,42 @@ +import { parseWithSchema } from "../src/json"; +import { z } from "zod"; + +describe("json", () => { + describe("parseWithSchema", () => { + const schema = z.object({ + test: z.boolean().optional(), + name: z.string(), + nested: z.object({ foo: z.string() }).strict().optional(), + }); + it("should parse", () => { + const json = `{ + "test":true, + "name":"bob", + "unknown":"unknown", + "nested":{ + "foo":"bar" + } + }`; + + expect(parseWithSchema(json, schema)).toStrictEqual({ + test: true, + name: "bob", + nested: { foo: "bar" }, + }); + }); + it("should fail with invalid schema", () => { + const json = `{ + "test":"yes", + "nested":{ + "foo":1 + } + }`; + + expect(() => parseWithSchema(json, schema)).toThrowError( + new Error( + `"test" Expected boolean, received string\n"name" Required\n"nested.foo" Expected string, received number` + ) + ); + }); + }); +}); diff --git a/packages/util/package.json b/packages/util/package.json index d16623d1f..b03c5f73b 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -18,7 +18,8 @@ "madge": "8.0.0", "rimraf": "6.0.1", "typescript": "5.5.4", - "vitest": "2.0.5" + "vitest": "2.0.5", + "zod": "3.23.8" }, "exports": { ".": { diff --git a/packages/util/src/json.ts b/packages/util/src/json.ts new file mode 100644 index 000000000..d8061eead --- /dev/null +++ b/packages/util/src/json.ts @@ -0,0 +1,27 @@ +import { ZodError, ZodIssue, ZodSchema } from "zod"; + +/** + * Parse a JSON string into an object and validate it against a schema + * @param json JSON string + * @param schema Zod schema to validate the JSON against + * @returns The parsed JSON object + */ +export function parseWithSchema<T>(json: string, schema: ZodSchema<T>): T { + try { + const jsonParsed = JSON.parse(json) as unknown; + const zodParsed = schema.parse(jsonParsed); + return zodParsed; + } catch (error) { + if (error instanceof ZodError) { + throw new Error(error.issues.map(prettyErrorMessage).join("\n")); + } else { + throw error; + } + } +} + +function prettyErrorMessage(issue: ZodIssue | undefined): string { + if (issue === undefined) return ""; + const path = issue.path.length > 0 ? `"${issue.path.join(".")}" ` : ""; + return `${path}${issue.message}`; +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 852d0600c..31ab5890d 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -614,6 +614,9 @@ importers: vitest: specifier: 2.0.5 + zod: + specifier: 3.23.8 + version: 3.23.8 packages: |