Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[GlossWithSuggestions] Use ... for all but last word #3226

Merged
merged 5 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Key } from "ts-key-enum";

import { type WritingSystem } from "api/models";
import { LiWithFont, TextFieldWithFont } from "utilities/fontComponents";
import SpellChecker from "utilities/spellChecker";
import SpellCheckerContext from "utilities/spellCheckerContext";

interface GlossWithSuggestionsProps {
Expand Down Expand Up @@ -84,7 +85,7 @@ export default function GlossWithSuggestions(
aria-selected={selected}
lang={props.analysisLang.bcp47}
>
{option}
{SpellChecker.replaceAllButLastWordWithEllipses(option)}
</LiWithFont>
)}
onKeyPress={(e: KeyboardEvent) => {
Expand Down
15 changes: 14 additions & 1 deletion src/utilities/spellChecker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,9 @@ export default class SpellChecker {
});
}

/** Trim whitespace from the start and non-letter/-mark/-number characters from the end,
* then split off the final word. */
static cleanAndSplit(word: string): SplitWord {
// Trim whitespace from the start and non-letter/-mark/-number characters from the end.
// Use of \p{L}\p{M}\p{N} here matches that in split_dictionary.py.
// Cf. https://en.wikipedia.org/wiki/Unicode_character_property
word = word.trimStart().replace(/[^\p{L}\p{M}\p{N}]*$/u, "");
Expand All @@ -89,6 +90,18 @@ export default class SpellChecker {
return { allButFinal, final };
}

/** If the given string, split by separator (non-letter/-mark/-number) characters,
* is multiple words, replace all but the last word with ellipses (...).
* (Assumes all end-of-string separator characters have been removed,
* which is the case for suggestions from this SpellChecker.) */
public static replaceAllButLastWordWithEllipses(word: string): string {
// Split by non-letter/-mark/-number characters
const words = word.split(/[^\p{L}\p{M}\p{N}]/u).filter((w) => w);
// Find the last non-letter/-mark/-number character
const finalSep = word.match(/[^\p{L}\p{M}\p{N}]/gu)?.pop();
return words.length > 1 ? `...${finalSep}${words[words.length - 1]}` : word;
}

// If the word string is multiple words, separate and
// find spelling suggestions for the last word.
getSpellingSuggestions(word: string): string[] {
Expand Down
26 changes: 26 additions & 0 deletions src/utilities/tests/spellChecker.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -114,4 +114,30 @@ describe("SpellChecker", () => {
}, 500);
});
});

describe("replaceAllButLastWordWithEllipses", () => {
it("handles empty string", () => {
expect(SpellChecker.replaceAllButLastWordWithEllipses("")).toEqual("");
});

it("does nothing if only 1 word", () => {
const word = " *(- #/;-something";
const result = SpellChecker.replaceAllButLastWordWithEllipses(word);
expect(result).toEqual(word);
});

it("replaces with ellipses when multiple words", () => {
expect(
SpellChecker.replaceAllButLastWordWithEllipses("double-word")
).toEqual("...-word");

expect(
SpellChecker.replaceAllButLastWordWithEllipses("now 3 words")
).toEqual("... words");

expect(
SpellChecker.replaceAllButLastWordWithEllipses("paren before (end")
).toEqual("...(end");
});
});
});
Loading