Files
edentext/tests/unit/autocorrect.test.ts
Steffen Becker 8d8bb858de feat: AutoCorrect while typing
LibreOffice's rule set: typographic quotes per document language, its
dash matrix, its replacement table, sentence capitalization with an
abbreviation exception list, and TWo INitials. One handleTextInput
plugin listed last, so every input rule still fires first; the rule
table itself is a pure function under test. Auto-URL and auto-list were
already TipTap's and now answer to the same checkboxes.
2026-08-14 00:53:57 +02:00

74 lines
3.0 KiB
TypeScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { describe, it, expect } from 'vitest';
import { autoCorrectFix } from '../../src/lib/editor/extensions/autoCorrect';
import { DEFAULT_AUTOCORRECT, type AutoCorrectOptions } from '../../src/lib/storage/autoCorrect';
// `before` is the block text up to and including the character just typed; the fix is
// applied to it, so a case reads as "type this, get that".
function typed(before: string, lang = 'en', opts: AutoCorrectOptions = DEFAULT_AUTOCORRECT): string {
const fix = autoCorrectFix(before, opts, lang);
if (!fix) return before;
return before.slice(0, fix.offset) + fix.text + before.slice(fix.offset + fix.length);
}
describe('autoCorrectFix', () => {
it('replaces LibreOffice\'s default table entries', () => {
expect(typed('a --> ')).toBe('a --> '); // only on the closing character
expect(typed('a -->')).toBe('a →');
expect(typed('a <--')).toBe('a ←');
expect(typed('a <-->')).toBe('a ↔');
expect(typed('a ==>')).toBe('a ⇒');
expect(typed('a <==>')).toBe('a ⇔');
expect(typed('(C)')).toBe('©');
expect(typed('x (tm)')).toBe('x ™');
expect(typed('and...')).toBe('and…');
expect(typed('+/-')).toBe('±');
});
it('replaces dashes the way LibreOffice does', () => {
expect(typed('A - B ')).toBe('A – B ');
expect(typed('A -- B ')).toBe('A – B ');
expect(typed('A--B ')).toBe('A—B ');
expect(typed('A-B ')).toBe('A-B ');
expect(typed('A - B')).toBe('A - B'); // not until the word is finished
});
it('opens and closes quotes per language', () => {
expect(typed('"')).toBe('“');
expect(typed('say "')).toBe('say “');
expect(typed('say “word"')).toBe('say “word”');
expect(typed('"', 'de')).toBe('„');
expect(typed('sag „Wort"', 'de')).toBe('sag „Wort“');
expect(typed("don'")).toBe('don’'); // an apostrophe mid-word closes, as in LibreOffice
expect(typed("'")).toBe('‘');
});
it('capitalizes the first letter of a sentence', () => {
expect(typed('hello ')).toBe('Hello ');
expect(typed('Done. now ')).toBe('Done. Now ');
expect(typed('Really? yes ')).toBe('Really? Yes ');
expect(typed('Hello ')).toBe('Hello ');
});
it('leaves an abbreviation and an initial alone', () => {
expect(typed('z.B. der ', 'de')).toBe('z.B. der ');
expect(typed('etc. and ')).toBe('etc. and ');
expect(typed('A. muster ')).toBe('A. muster ');
});
it('fixes TWo INitial CApitals', () => {
expect(typed('WOrd ')).toBe('Word ');
expect(typed('the WOrd.')).toBe('the Word.');
expect(typed('ABC ')).toBe('ABC ');
expect(typed('Word ')).toBe('Word ');
});
it('honours the switches', () => {
const off = { ...DEFAULT_AUTOCORRECT, quotes: false, dashes: false, replacements: false, capitalize: false, twoInitials: false };
expect(typed('"', 'en', off)).toBe('"');
expect(typed('A - B ', 'en', off)).toBe('A - B ');
expect(typed('a -->', 'en', off)).toBe('a -->');
expect(typed('hello ', 'en', off)).toBe('hello ');
expect(typed('WOrd ', 'en', off)).toBe('WOrd ');
});
});