feat(config): add subtitle CSS editor, nPlusOne.enabled flag, and fix se

- subtitleStyle.css / subtitleStyle.secondary.css replace flat style fields in the settings window
- ankiConnect.nPlusOne.enabled gates known-word cache independently of knownWords.highlightEnabled
- Settings search now covers all categories, narrows on multi-word terms, and hides editor-owned fields
- Default note-type picker to Kiku then Lapis; rename isLapis.sentenceCardModel default to "Lapis"
This commit is contained in:
2026-05-17 04:13:02 -07:00
parent 3447103857
commit 81830b3372
39 changed files with 1147 additions and 86 deletions
+18 -7
View File
@@ -6,7 +6,7 @@ import type {
} from '../types/settings';
export interface SettingsFilter {
category: ConfigSettingsCategory;
category?: ConfigSettingsCategory;
query?: string;
}
@@ -20,6 +20,15 @@ function normalizeQuery(query: string | undefined): string {
return (query ?? '').trim().toLowerCase();
}
function searchableText(parts: Array<string | undefined>): string {
return parts
.filter(Boolean)
.join(' ')
.replace(/([a-z0-9])([A-Z])/g, '$1 $2')
.replace(/[^a-zA-Z0-9]+/g, ' ')
.toLowerCase();
}
function valuesEqual(a: unknown, b: unknown): boolean {
return JSON.stringify(a) === JSON.stringify(b);
}
@@ -29,24 +38,26 @@ export function filterSettingsFields(
filter: SettingsFilter,
): ConfigSettingsField[] {
const query = normalizeQuery(filter.query);
const terms = query.length > 0 ? query.split(/\s+/) : [];
return fields.filter((field) => {
if (field.category !== filter.category || field.legacyHidden) {
if (field.legacyHidden || field.settingsHidden) {
return false;
}
if (filter.category && field.category !== filter.category) {
return false;
}
if (!query) {
return true;
}
const haystack = [
const haystack = searchableText([
field.label,
field.description,
field.configPath,
field.section,
field.subsection ?? '',
field.enumValues?.join(' ') ?? '',
]
.join(' ')
.toLowerCase();
return haystack.includes(query);
]);
return terms.every((term) => haystack.includes(term));
});
}