Skip to content
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
9 changes: 9 additions & 0 deletions src/gui/GenericSuggester/genericSuggester.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,13 @@ describe("GenericSuggester", () => {
expect(() => suggester.getSuggestions("1")).not.toThrow();
});

it("tolerates undefined query input", () => {
const items = ["Alpha", "Beta"];
const suggester = new GenericSuggester(app, items, items);

expect(() =>
suggester.getSuggestions(undefined as unknown as string),
).not.toThrow();
});

});
7 changes: 6 additions & 1 deletion src/gui/GenericSuggester/genericSuggester.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FuzzySuggestModal } from "obsidian";
import type { FuzzyMatch, App } from "obsidian";
import { log, toError } from "src/logger/logManager";
import { normalizeDisplayItem } from "../suggesters/utils";
import { normalizeDisplayItem, normalizeQuery } from "../suggesters/utils";

type SuggestRender<T> = (value: T, el: HTMLElement) => void;

Expand Down Expand Up @@ -86,6 +86,11 @@ export default class GenericSuggester<T> extends FuzzySuggestModal<T> {
return this.items;
}

getSuggestions(query: string): FuzzyMatch<T>[] {
const safeQuery = normalizeQuery(query);
return super.getSuggestions(safeQuery);
}

selectSuggestion(
value: FuzzyMatch<T>,
evt: MouseEvent | KeyboardEvent
Expand Down
12 changes: 12 additions & 0 deletions src/gui/InputSuggester/inputSuggester.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,18 @@ describe("InputSuggester", () => {
expect(matchingEntries).toHaveLength(1);
});

it("tolerates undefined query input", () => {
const suggester = new InputSuggester(
app,
["Alpha file", "Beta note"],
["Alpha file", "Beta note"]
);

expect(() =>
suggester.getSuggestions(undefined as unknown as string),
).not.toThrow();
});

it("aligns displayItems length with items length", () => {
const shortDisplay = ["Alpha"];
const shortItems = ["Alpha", "Beta", "Gamma"];
Expand Down
7 changes: 4 additions & 3 deletions src/gui/InputSuggester/inputSuggester.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { FuzzySuggestModal } from "obsidian";
import type { FuzzyMatch, App } from "obsidian";
import { log, toError } from "src/logger/logManager";
import { normalizeDisplayItem } from "../suggesters/utils";
import { normalizeDisplayItem, normalizeQuery } from "../suggesters/utils";

type SuggestRender<T> = (value: T, el: HTMLElement) => void;

Expand Down Expand Up @@ -113,8 +113,9 @@ export default class InputSuggester extends FuzzySuggestModal<string> {
}

getSuggestions(query: string): FuzzyMatch<string>[] {
const suggestions = super.getSuggestions(query);
const customValue = this.inputEl.value;
const safeQuery = normalizeQuery(query);
const suggestions = super.getSuggestions(safeQuery);
const customValue = normalizeQuery(this.inputEl.value);

if (!customValue) return suggestions;

Expand Down
6 changes: 4 additions & 2 deletions src/gui/suggesters/SuggesterInputSuggest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { App } from "obsidian";
import { TextInputSuggest } from "./suggest";
import { normalizeDisplayItem, normalizeQuery } from "./utils";

export class SuggesterInputSuggest extends TextInputSuggest<string> {
private options: string[];
Expand All @@ -14,7 +15,7 @@ export class SuggesterInputSuggest extends TextInputSuggest<string> {
multiSelect = false,
) {
super(app, inputEl);
this.options = options;
this.options = options.map((option) => normalizeDisplayItem(option));
this.caseSensitive = caseSensitive;
this.multiSelect = multiSelect;

Expand Down Expand Up @@ -44,7 +45,8 @@ export class SuggesterInputSuggest extends TextInputSuggest<string> {
}

getSuggestions(query: string): string[] {
const { alreadySelected, activeTerm } = this.parseMultiSelectInput(query);
const safeQuery = normalizeQuery(query);
const { alreadySelected, activeTerm } = this.parseMultiSelectInput(safeQuery);
const searchQuery = this.caseSensitive ? activeTerm : activeTerm.toLowerCase();

const available = this.getRemainingOptions(alreadySelected);
Expand Down
6 changes: 4 additions & 2 deletions src/gui/suggesters/genericTextSuggester.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { TextInputSuggest } from "./suggest";
import type { App } from "obsidian";
import { TextInputSuggest } from "./suggest";
import { normalizeDisplayItem, normalizeQuery } from "./utils";

export class GenericTextSuggester extends TextInputSuggest<string> {
constructor(
Expand All @@ -9,10 +10,11 @@ export class GenericTextSuggester extends TextInputSuggest<string> {
private maxSuggestions = Infinity
) {
super(app, inputEl);
this.items = items.map((item) => normalizeDisplayItem(item));
}

getSuggestions(inputStr: string): string[] {
const inputLowerCase: string = inputStr.toLowerCase();
const inputLowerCase = normalizeQuery(inputStr).toLowerCase();

const filtered = this.items.filter((item) => {
return item.toLowerCase().includes(inputLowerCase);
Expand Down
4 changes: 4 additions & 0 deletions src/gui/suggesters/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export function normalizeDisplayItem(value: unknown): string {
return String(value);
}

export function normalizeQuery(value: unknown): string {
return normalizeDisplayItem(value);
}

export function normalizeForSearch(value: string): string {
return value.normalize("NFC").toLowerCase();
}
Expand Down
2 changes: 2 additions & 0 deletions src/quickAddApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import GenericWideInputPrompt from "./gui/GenericWideInputPrompt/GenericWideInpu
import GenericYesNoPrompt from "./gui/GenericYesNoPrompt/GenericYesNoPrompt";
import InputSuggester from "./gui/InputSuggester/inputSuggester";
import VDateInputPrompt from "./gui/VDateInputPrompt/VDateInputPrompt";
import { normalizeDisplayItem } from "./gui/suggesters/utils";
import type { IChoiceExecutor } from "./IChoiceExecutor";
import type QuickAdd from "./main";
import { OnePageInputModal } from "./preflight/OnePageInputModal";
Expand Down Expand Up @@ -671,6 +672,7 @@ export class QuickAddApi {
} else {
displayedItems = displayItems;
}
displayedItems = displayedItems.map((item) => normalizeDisplayItem(item));

if (allowCustomInput) {
return await InputSuggester.Suggest(
Expand Down