From 3b01090e5a3e0a354501f45609da63fbbdd4f7c6 Mon Sep 17 00:00:00 2001 From: Miodec Date: Thu, 27 Nov 2025 19:26:10 +0100 Subject: [PATCH 1/3] chore: remove oxc prettier plugin too many issues --- .github/workflows/pretty-check.yml | 2 +- .prettierrc | 3 +- package.json | 1 - pnpm-lock.yaml | 219 ----------------------------- 4 files changed, 2 insertions(+), 223 deletions(-) diff --git a/.github/workflows/pretty-check.yml b/.github/workflows/pretty-check.yml index 8864497a2997..46fb3fd1d6c4 100644 --- a/.github/workflows/pretty-check.yml +++ b/.github/workflows/pretty-check.yml @@ -36,7 +36,7 @@ jobs: version: ${{ env.PNPM_VERSION }} - name: Install Prettier deps only - run: pnpm install -D -w prettier @prettier/plugin-oxc + run: pnpm install -D -w prettier - name: Get changed files diff --git a/.prettierrc b/.prettierrc index 8ffdcc646e9c..267b0d4c3660 100644 --- a/.prettierrc +++ b/.prettierrc @@ -3,6 +3,5 @@ "useTabs": false, "htmlWhitespaceSensitivity": "ignore", "trailingComma": "all", - "endOfLine": "lf", - "plugins": ["@prettier/plugin-oxc"] + "endOfLine": "lf" } diff --git a/package.json b/package.json index 84be39ce3526..2b409c2d8dd5 100644 --- a/package.json +++ b/package.json @@ -67,7 +67,6 @@ "@commitlint/cli": "17.7.1", "@commitlint/config-conventional": "19.2.2", "@monkeytype/release": "workspace:*", - "@prettier/plugin-oxc": "0.1.1", "@vitest/coverage-v8": "4.0.8", "conventional-changelog": "6.0.0", "eslint": "8.57.1", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 972ce9ab0e56..31219991556c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,9 +17,6 @@ importers: '@monkeytype/release': specifier: workspace:* version: link:packages/release - '@prettier/plugin-oxc': - specifier: 0.1.1 - version: 0.1.1 '@vitest/coverage-v8': specifier: 4.0.8 version: 4.0.8(vitest@4.0.8(@types/node@20.5.1)(happy-dom@20.0.10)(sass@1.70.0)(terser@5.44.1)(tsx@4.16.2)(yaml@2.8.1)) @@ -1391,15 +1388,6 @@ packages: resolution: {integrity: sha512-D/9dozteKcutI5OdxJd8rU+fL6XgaaRg60sPPJWkT33OCiRfkCu5wO5B/yXTaaL2e6EB0lcCBGe5E0XscZCvvQ==} engines: {node: '>=18'} - '@emnapi/core@1.7.1': - resolution: {integrity: sha512-o1uhUASyo921r2XtHYOHy7gdkGLge8ghBEQHMWmyJFoXlpU58kIrhhN3w26lpQb6dspetweapMn2CSNwQ8I4wg==} - - '@emnapi/runtime@1.7.1': - resolution: {integrity: sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==} - - '@emnapi/wasi-threads@1.1.0': - resolution: {integrity: sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ==} - '@emotion/is-prop-valid@1.2.2': resolution: {integrity: sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==} @@ -2415,9 +2403,6 @@ packages: cpu: [x64] os: [win32] - '@napi-rs/wasm-runtime@1.0.7': - resolution: {integrity: sha512-SeDnOO0Tk7Okiq6DbXmmBODgOAb9dp9gjlphokTUxmt8U3liIP1ZsozBahH69j/RJv+Rfs6IwUKHTgQYJ/HBAw==} - '@noble/hashes@1.8.0': resolution: {integrity: sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==} engines: {node: ^14.21.3 || >=16} @@ -2587,98 +2572,6 @@ packages: resolution: {integrity: sha512-aKcOkyrorBGlajjRdVoJWHTxfxO1vCNHLJVlSDaRHDIdjU+pX8IYQPvPDkYiujKLbRnWU+1TBwEt0QRgSm4SGA==} engines: {node: '>=14'} - '@oxc-parser/binding-android-arm64@0.99.0': - resolution: {integrity: sha512-V4jhmKXgQQdRnm73F+r3ZY4pUEsijQeSraFeaCGng7abSNJGs76X6l82wHnmjLGFAeY00LWtjcELs7ZmbJ9+lA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [android] - - '@oxc-parser/binding-darwin-arm64@0.99.0': - resolution: {integrity: sha512-Rp41nf9zD5FyLZciS9l1GfK8PhYqrD5kEGxyTOA2esTLeAy37rZxetG2E3xteEolAkeb2WDkVrlxPtibeAncMg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [darwin] - - '@oxc-parser/binding-darwin-x64@0.99.0': - resolution: {integrity: sha512-WVonp40fPPxo5Gs0POTI57iEFv485TvNKOHMwZRhigwZRhZY2accEAkYIhei9eswF4HN5B44Wybkz7Gd1Qr/5Q==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [darwin] - - '@oxc-parser/binding-freebsd-x64@0.99.0': - resolution: {integrity: sha512-H30bjOOttPmG54gAqu6+HzbLEzuNOYO2jZYrIq4At+NtLJwvNhXz28Hf5iEAFZIH/4hMpLkM4VN7uc+5UlNW3Q==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [freebsd] - - '@oxc-parser/binding-linux-arm-gnueabihf@0.99.0': - resolution: {integrity: sha512-0Z/Th0SYqzSRDPs6tk5lQdW0i73UCupnim3dgq2oW0//UdLonV/5wIZCArfKGC7w9y4h8TxgXpgtIyD1kKzzlQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - - '@oxc-parser/binding-linux-arm-musleabihf@0.99.0': - resolution: {integrity: sha512-xo0wqNd5bpbzQVNpAIFbHk1xa+SaS/FGBABCd942SRTnrpxl6GeDj/s1BFaGcTl8MlwlKVMwOcyKrw/2Kdfquw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm] - os: [linux] - - '@oxc-parser/binding-linux-arm64-gnu@0.99.0': - resolution: {integrity: sha512-u26I6LKoLTPTd4Fcpr0aoAtjnGf5/ulMllo+QUiBhupgbVCAlaj4RyXH/mvcjcsl2bVBv9E/gYJZz2JjxQWXBA==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - - '@oxc-parser/binding-linux-arm64-musl@0.99.0': - resolution: {integrity: sha512-qhftDo2D37SqCEl3ZTa367NqWSZNb1Ddp34CTmShLKFrnKdNiUn55RdokLnHtf1AL5ssaQlYDwBECX7XiBWOhw==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [linux] - - '@oxc-parser/binding-linux-riscv64-gnu@0.99.0': - resolution: {integrity: sha512-zxn/xkf519f12FKkpL5XwJipsylfSSnm36h6c1zBDTz4fbIDMGyIhHfWfwM7uUmHo9Aqw1pLxFpY39Etv398+Q==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [riscv64] - os: [linux] - - '@oxc-parser/binding-linux-s390x-gnu@0.99.0': - resolution: {integrity: sha512-Y1eSDKDS5E4IVC7Oxw+NbYAKRmJPMJTIjW+9xOWwteDHkFqpocKe0USxog+Q1uhzalD9M0p9eXWEWdGQCMDBMQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [s390x] - os: [linux] - - '@oxc-parser/binding-linux-x64-gnu@0.99.0': - resolution: {integrity: sha512-YVJMfk5cFWB8i2/nIrbk6n15bFkMHqWnMIWkVx7r2KwpTxHyFMfu2IpeVKo1ITDSmt5nBrGdLHD36QRlu2nDLg==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - - '@oxc-parser/binding-linux-x64-musl@0.99.0': - resolution: {integrity: sha512-2+SDPrie5f90A1b9EirtVggOgsqtsYU5raZwkDYKyS1uvJzjqHCDhG/f4TwQxHmIc5YkczdQfwvN91lwmjsKYQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [linux] - - '@oxc-parser/binding-wasm32-wasi@0.99.0': - resolution: {integrity: sha512-DKA4j0QerUWSMADziLM5sAyM7V53Fj95CV9SjP77bPfEfT7MnvFKnneaRMqPK1cpzjAGiQF52OBUIKyk0dwOQA==} - engines: {node: '>=14.0.0'} - cpu: [wasm32] - - '@oxc-parser/binding-win32-arm64-msvc@0.99.0': - resolution: {integrity: sha512-EaB3AvsxqdNUhh9FOoAxRZ2L4PCRwDlDb//QXItwyOJrX7XS+uGK9B1KEUV4FZ/7rDhHsWieLt5e07wl2Ti5AQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [arm64] - os: [win32] - - '@oxc-parser/binding-win32-x64-msvc@0.99.0': - resolution: {integrity: sha512-sJN1Q8h7ggFOyDn0zsHaXbP/MklAVUvhrbq0LA46Qum686P3SZQHjbATqJn9yaVEvaSKXCshgl0vQ1gWkGgpcQ==} - engines: {node: ^20.19.0 || >=22.12.0} - cpu: [x64] - os: [win32] - - '@oxc-project/types@0.99.0': - resolution: {integrity: sha512-LLDEhXB7g1m5J+woRSgfKsFPS3LhR9xRhTeIoEBm5WrkwMxn6eZ0Ld0c0K5eHB57ChZX6I3uSmmLjZ8pcjlRcw==} - '@oxlint/darwin-arm64@1.29.0': resolution: {integrity: sha512-XYsieDAI0kXJyvayHnmOW1qVydqklRRVT4O5eZmO/rdNCku5CoXsZvBvkPc3U8/9V1mRuen1sxbM9T5JsZqhdA==} cpu: [arm64] @@ -2741,10 +2634,6 @@ packages: '@polka/url@1.0.0-next.29': resolution: {integrity: sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==} - '@prettier/plugin-oxc@0.1.1': - resolution: {integrity: sha512-gXqHoTpdHOE0WcbE25gDrBVJ09uGb+u29q73HoyA/o05SxCBT0XtTxocOzVTMo+vCBsXt74yf3XNSzeczbfiVQ==} - engines: {node: '>=14'} - '@protobufjs/aspromise@1.1.2': resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} @@ -3231,9 +3120,6 @@ packages: '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - '@tybys/wasm-util@0.10.1': - resolution: {integrity: sha512-9tTaPJLSiejZKx+Bmog4uSubteqTvFrVrURwkmHixBo0G4seD0zUxp98E1DzUBJxLQ3NPwXrGKDiVjwx/DpPsg==} - '@types/bcrypt@5.0.2': resolution: {integrity: sha512-6atioO8Y75fNcbmj0G7UjI9lXN2pQ/IGJ2FWT4a/btd0Lk9lQalHLKhkgKVZ3r+spnmWUKfbMi1GEe9wyHQfNQ==} @@ -7606,10 +7492,6 @@ packages: resolution: {integrity: sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==} engines: {node: '>= 0.4'} - oxc-parser@0.99.0: - resolution: {integrity: sha512-MpS1lbd2vR0NZn1v0drpgu7RUFu3x9Rd0kxExObZc2+F+DIrV0BOMval/RO3BYGwssIOerII6iS8EbbpCCZQpQ==} - engines: {node: ^20.19.0 || >=22.12.0} - oxlint@1.29.0: resolution: {integrity: sha512-YqUVUhTYDqazV2qu3QSQn/H4Z1OP+fTnedgZWDk1/lDZxGfR0b1MqRVaEm3rRjBMLHP0zXlriIWUx+DD6UMaPA==} engines: {node: ^20.19.0 || >=22.12.0} @@ -10947,22 +10829,6 @@ snapshots: gonzales-pe: 4.3.0 node-source-walk: 7.0.0 - '@emnapi/core@1.7.1': - dependencies: - '@emnapi/wasi-threads': 1.1.0 - tslib: 2.8.1 - optional: true - - '@emnapi/runtime@1.7.1': - dependencies: - tslib: 2.8.1 - optional: true - - '@emnapi/wasi-threads@1.1.0': - dependencies: - tslib: 2.8.1 - optional: true - '@emotion/is-prop-valid@1.2.2': dependencies: '@emotion/memoize': 0.8.1 @@ -12014,13 +11880,6 @@ snapshots: '@msgpackr-extract/msgpackr-extract-win32-x64@3.0.3': optional: true - '@napi-rs/wasm-runtime@1.0.7': - dependencies: - '@emnapi/core': 1.7.1 - '@emnapi/runtime': 1.7.1 - '@tybys/wasm-util': 0.10.1 - optional: true - '@noble/hashes@1.8.0': {} '@nodelib/fs.scandir@2.1.5': @@ -12208,55 +12067,6 @@ snapshots: '@opentelemetry/semantic-conventions@1.34.0': {} - '@oxc-parser/binding-android-arm64@0.99.0': - optional: true - - '@oxc-parser/binding-darwin-arm64@0.99.0': - optional: true - - '@oxc-parser/binding-darwin-x64@0.99.0': - optional: true - - '@oxc-parser/binding-freebsd-x64@0.99.0': - optional: true - - '@oxc-parser/binding-linux-arm-gnueabihf@0.99.0': - optional: true - - '@oxc-parser/binding-linux-arm-musleabihf@0.99.0': - optional: true - - '@oxc-parser/binding-linux-arm64-gnu@0.99.0': - optional: true - - '@oxc-parser/binding-linux-arm64-musl@0.99.0': - optional: true - - '@oxc-parser/binding-linux-riscv64-gnu@0.99.0': - optional: true - - '@oxc-parser/binding-linux-s390x-gnu@0.99.0': - optional: true - - '@oxc-parser/binding-linux-x64-gnu@0.99.0': - optional: true - - '@oxc-parser/binding-linux-x64-musl@0.99.0': - optional: true - - '@oxc-parser/binding-wasm32-wasi@0.99.0': - dependencies: - '@napi-rs/wasm-runtime': 1.0.7 - optional: true - - '@oxc-parser/binding-win32-arm64-msvc@0.99.0': - optional: true - - '@oxc-parser/binding-win32-x64-msvc@0.99.0': - optional: true - - '@oxc-project/types@0.99.0': {} - '@oxlint/darwin-arm64@1.29.0': optional: true @@ -12302,10 +12112,6 @@ snapshots: '@polka/url@1.0.0-next.29': {} - '@prettier/plugin-oxc@0.1.1': - dependencies: - oxc-parser: 0.99.0 - '@protobufjs/aspromise@1.1.2': {} '@protobufjs/base64@1.1.2': {} @@ -12764,11 +12570,6 @@ snapshots: '@tsconfig/node16@1.0.4': {} - '@tybys/wasm-util@0.10.1': - dependencies: - tslib: 2.8.1 - optional: true - '@types/bcrypt@5.0.2': dependencies: '@types/node': 24.9.1 @@ -18161,26 +17962,6 @@ snapshots: object-keys: 1.1.1 safe-push-apply: 1.0.0 - oxc-parser@0.99.0: - dependencies: - '@oxc-project/types': 0.99.0 - optionalDependencies: - '@oxc-parser/binding-android-arm64': 0.99.0 - '@oxc-parser/binding-darwin-arm64': 0.99.0 - '@oxc-parser/binding-darwin-x64': 0.99.0 - '@oxc-parser/binding-freebsd-x64': 0.99.0 - '@oxc-parser/binding-linux-arm-gnueabihf': 0.99.0 - '@oxc-parser/binding-linux-arm-musleabihf': 0.99.0 - '@oxc-parser/binding-linux-arm64-gnu': 0.99.0 - '@oxc-parser/binding-linux-arm64-musl': 0.99.0 - '@oxc-parser/binding-linux-riscv64-gnu': 0.99.0 - '@oxc-parser/binding-linux-s390x-gnu': 0.99.0 - '@oxc-parser/binding-linux-x64-gnu': 0.99.0 - '@oxc-parser/binding-linux-x64-musl': 0.99.0 - '@oxc-parser/binding-wasm32-wasi': 0.99.0 - '@oxc-parser/binding-win32-arm64-msvc': 0.99.0 - '@oxc-parser/binding-win32-x64-msvc': 0.99.0 - oxlint@1.29.0: optionalDependencies: '@oxlint/darwin-arm64': 1.29.0 From f6df272466fa6d023f0c5608c319644a0d1a4c51 Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Thu, 27 Nov 2025 21:30:34 +0200 Subject: [PATCH 2/3] impr(input-history): Change style for incomplete last word in input history (@Leonabcd123) (#7117) ### Description Added a new style named "incomplete" that mirrors the error style, but uses yellow for the color. Words are marked in this style when they don't match the correct word exactly, but share the same prefix. Implements #6690 --------- Co-authored-by: Jack --- frontend/src/ts/test/test-ui.ts | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/frontend/src/ts/test/test-ui.ts b/frontend/src/ts/test/test-ui.ts index 769d8e523e3d..972ece968389 100644 --- a/frontend/src/ts/test/test-ui.ts +++ b/frontend/src/ts/test/test-ui.ts @@ -1286,7 +1286,8 @@ function buildWordLettersHTML( async function loadWordsHistory(): Promise { $("#resultWordsHistory .words").empty(); let wordsHTML = ""; - for (let i = 0; i < TestInput.input.getHistory().length + 2; i++) { + const inputHistoryLength = TestInput.input.getHistory().length; + for (let i = 0; i < inputHistoryLength + 2; i++) { const input = TestInput.input.getHistory(i); const corrected = TestInput.corrected.getHistory(i); const word = TestWords.words.get(i); @@ -1303,8 +1304,19 @@ async function loadWordsHistory(): Promise { throw new Error("empty input word"); } - const errorClass = - Config.mode === "zen" ? "" : input !== word ? "error" : ""; + const isIncorrectWord = input !== word; + const isLastWord = i === inputHistoryLength - 1; + const isTimedTest = + Config.mode === "time" || + (Config.mode === "custom" && CustomText.getLimitMode() === "time") || + (Config.mode === "custom" && CustomText.getLimitValue() === 0); + const isPartiallyCorrect = word.substring(0, input.length) === input; + + const shouldShowError = + Config.mode !== "zen" && + !(isLastWord && isTimedTest && isPartiallyCorrect); + + const errorClass = isIncorrectWord && shouldShowError ? "error" : ""; if (corrected !== undefined && corrected !== "") { const correctedChar = !containsKorean From 2886c72833f2cbc8d305ddfcd881d7bb3960ddaa Mon Sep 17 00:00:00 2001 From: Leonabcd123 <156839416+Leonabcd123@users.noreply.github.com> Date: Thu, 27 Nov 2025 21:36:38 +0200 Subject: [PATCH 3/3] impr(words-filter): add 'exact match only' checkbox (@Leonabcd123) (#7126) ### Description Added a checkbox in the words filter modal that allows the user to make all characters not in the include list be excluded. Implements #5970 --------- Co-authored-by: Miodec --- frontend/src/html/popups.html | 4 + frontend/src/styles/inputs.scss | 4 + frontend/src/ts/modals/word-filter.ts | 103 +++++++++++++++----------- 3 files changed, 67 insertions(+), 44 deletions(-) diff --git a/frontend/src/html/popups.html b/frontend/src/html/popups.html index 2b51f5751973..bbe596c993b9 100644 --- a/frontend/src/html/popups.html +++ b/frontend/src/html/popups.html @@ -742,6 +742,10 @@ autocomplete="off" title="include" /> +
exclude
diff --git a/frontend/src/styles/inputs.scss b/frontend/src/styles/inputs.scss index ca0768d7920c..2e3533bde952 100644 --- a/frontend/src/styles/inputs.scss +++ b/frontend/src/styles/inputs.scss @@ -102,6 +102,10 @@ label.checkboxWithSub { } } +#wordFilterModal #exactMatchOnly { + width: 1.25em; +} + input[type="checkbox"] { appearance: none; height: 1.25em; diff --git a/frontend/src/ts/modals/word-filter.ts b/frontend/src/ts/modals/word-filter.ts index fa3de51867a8..ad0913a9dd64 100644 --- a/frontend/src/ts/modals/word-filter.ts +++ b/frontend/src/ts/modals/word-filter.ts @@ -16,8 +16,17 @@ import { LayoutObject } from "@monkeytype/schemas/layouts"; type FilterPreset = { display: string; getIncludeString: (layout: LayoutObject) => string[][]; - getExcludeString: (layout: LayoutObject) => string[][]; -}; +} & ( + | { + exactMatch: true; + } + | { + exactMatch?: false; + getExcludeString?: (layout: LayoutObject) => string[][]; + } +); + +const exactMatchCheckbox = $("#wordFilterModal #exactMatchOnly"); const presets: Record = { homeKeys: { @@ -27,13 +36,7 @@ const presets: Record = { const homeKeysRight = layout.keys.row3.slice(6, 10); return [...homeKeysLeft, ...homeKeysRight]; }, - getExcludeString: (layout) => { - const topRow = layout.keys.row2; - const bottomRow = layout.keys.row4; - const homeRowRight = layout.keys.row3.slice(10); - const homeRowMiddle = layout.keys.row3.slice(4, 6); - return [...topRow, ...homeRowMiddle, ...homeRowRight, ...bottomRow]; - }, + exactMatch: true, }, leftHand: { display: "left hand", @@ -43,12 +46,7 @@ const presets: Record = { const bottomRowInclude = layout.keys.row4.slice(0, 5); return [...topRowInclude, ...homeRowInclude, ...bottomRowInclude]; }, - getExcludeString: (layout) => { - const topRowExclude = layout.keys.row2.slice(5); - const homeRowExclude = layout.keys.row3.slice(5); - const bottomRowExclude = layout.keys.row4.slice(5); - return [...topRowExclude, ...homeRowExclude, ...bottomRowExclude]; - }, + exactMatch: true, }, rightHand: { display: "right hand", @@ -58,45 +56,28 @@ const presets: Record = { const bottomRowInclude = layout.keys.row4.slice(4); return [...topRowInclude, ...homeRowInclude, ...bottomRowInclude]; }, - getExcludeString: (layout) => { - const topRowExclude = layout.keys.row2.slice(0, 5); - const homeRowExclude = layout.keys.row3.slice(0, 5); - const bottomRowExclude = layout.keys.row4.slice(0, 4); - return [...topRowExclude, ...homeRowExclude, ...bottomRowExclude]; - }, + exactMatch: true, }, homeRow: { display: "home row", getIncludeString: (layout) => { return layout.keys.row3; }, - getExcludeString: (layout) => { - const topRowExclude = layout.keys.row2; - const bottomRowExclude = layout.keys.row4; - return [...topRowExclude, ...bottomRowExclude]; - }, + exactMatch: true, }, topRow: { display: "top row", getIncludeString: (layout) => { return layout.keys.row2; }, - getExcludeString: (layout) => { - const homeRowExclude = layout.keys.row3; - const bottomRowExclude = layout.keys.row4; - return [...homeRowExclude, ...bottomRowExclude]; - }, + exactMatch: true, }, bottomRow: { display: "bottom row", getIncludeString: (layout) => { return layout.keys.row4; }, - getExcludeString: (layout) => { - const topRowExclude = layout.keys.row2; - const homeRowExclude = layout.keys.row3; - return [...topRowExclude, ...homeRowExclude]; - }, + exactMatch: true, }, }; @@ -165,10 +146,18 @@ function hide(hideOptions?: HideOptions): void { } async function filter(language: Language): Promise { + const exactMatchOnly = exactMatchCheckbox.is(":checked"); let filterin = $("#wordFilterModal .wordIncludeInput").val() as string; filterin = Misc.escapeRegExp(filterin?.trim()); filterin = filterin.replace(/\s+/gi, "|"); - const regincl = new RegExp(filterin, "i"); + let regincl; + + if (exactMatchOnly) { + regincl = new RegExp("^[" + filterin + "]+$", "i"); + } else { + regincl = new RegExp(filterin, "i"); + } + let filterout = $("#wordFilterModal .wordExcludeInput").val() as string; filterout = Misc.escapeRegExp(filterout.trim()); filterout = filterout.replace(/\s+/gi, "|"); @@ -202,7 +191,7 @@ async function filter(language: Language): Promise { } for (const word of languageWordList.words) { const test1 = regincl.test(word); - const test2 = regexcl.test(word); + const test2 = exactMatchOnly ? false : regexcl.test(word); if ( ((test1 && !test2) || (test1 && filterout === "")) && word.length <= maxLength && @@ -236,6 +225,19 @@ async function apply(set: boolean): Promise { }); } +function setExactMatchInput(disable: boolean): void { + const wordExcludeInputEl = $("#wordFilterModal #wordExcludeInput"); + + if (disable) { + $("#wordFilterModal #wordExcludeInput").val(""); + wordExcludeInputEl.attr("disabled", "disabled"); + } else { + wordExcludeInputEl.removeAttr("disabled"); + } + + exactMatchCheckbox.prop("checked", disable); +} + function disableButtons(): void { for (const button of modal.getModal().querySelectorAll("button")) { button.setAttribute("disabled", "true"); @@ -270,13 +272,26 @@ async function setup(): Promise { .map((x) => x[0]) .join(" "), ); - $("#wordExcludeInput").val( - presetToApply - .getExcludeString(layout) - .map((x) => x[0]) - .join(" "), - ); + + if (presetToApply.exactMatch === true) { + setExactMatchInput(true); + } else { + setExactMatchInput(false); + if (presetToApply.getExcludeString !== undefined) { + $("#wordExcludeInput").val( + presetToApply + .getExcludeString(layout) + .map((x) => x[0]) + .join(" "), + ); + } + } }); + + exactMatchCheckbox.on("change", () => { + setExactMatchInput(exactMatchCheckbox.is(":checked")); + }); + $("#wordFilterModal button.addButton").on("click", () => { $("#wordFilterModal .loadingIndicator").removeClass("hidden"); disableButtons();