import { describe, it, expect } from 'vitest' import { Schema, type Node as PMNode } from '@tiptap/pm/model' import { wordAt } from './SpellCheck' // Same minimal schema the suggestion-anchoring tests use: enough of a document // to walk textblocks, none of the editor. const schema = new Schema({ nodes: { doc: { content: 'block+' }, paragraph: { group: 'block', content: 'inline*', toDOM: () => ['p', 0] }, text: { group: 'inline' }, }, }) const para = (text: string): PMNode => schema.node('doc', null, [schema.node('paragraph', null, text ? [schema.text(text)] : [])]) // posOf turns a plain-text offset into a ProseMirror position inside the single // paragraph (+1 for the paragraph's opening token). const posOf = (offset: number) => offset + 1 describe('wordAt and the pair alphabet', () => { it('keeps English-only tokenizing when no accented dictionary is loaded', () => { const doc = para('the river runs') expect(wordAt(doc, posOf(5))?.word).toBe('river') }) it('cuts an accented word into fragments on the narrow alphabet', () => { // Not a hypothetical: this is what every surface did before the pt-PT pair, // and it is why the alphabet had to become a property of the checker rather // than a constant. "coração" tokenized as A-Z yields "cora" — a definition // of which would be worse than no popover. const doc = para('o coração dela') expect(wordAt(doc, posOf(3))?.word).toBe('cora') }) it('resolves the whole word once the pair widens the alphabet', () => { const doc = para('o coração dela') expect(wordAt(doc, posOf(3), true)?.word).toBe('coração') // …from either side of the accented letters, not just before them. expect(wordAt(doc, posOf(9), true)?.word).toBe('coração') }) it('never tokenizes CJK, whichever alphabet is in force', () => { // The zh pair's guarantee, and it must survive a change made for another // pair entirely: Chinese is the source language, not something to spellcheck. const doc = para('我在写作 today') expect(wordAt(doc, posOf(1))).toBeNull() expect(wordAt(doc, posOf(1), true)).toBeNull() expect(wordAt(doc, posOf(6), true)?.word).toBe('today') }) it('stops the wide alphabet at the maths symbols hiding in Latin-1', () => { // × (U+00D7) and ÷ (U+00F7) sit inside the accented-letter block. A range // written À-ÿ would swallow them and glue "3×4" into one token. const doc = para('3×4 é isso') expect(wordAt(doc, posOf(4), true)?.word).toBe('é') }) })