class Word { final int start; final int end; final String text; Word({required this.start, required this.end, required this.text}); } class WordDelta { Word? old; Word? modified; WordDelta({this.old, this.modified}); } class TextDelta { final List wordDeltas = []; } class Utility { static List splitToWords(String text) { List words = []; String currentWord = ""; for (int i = 0; i < text.length; i++) { if (text[i] == " " || text[i] == "\n" || text[i] == "\r" || text[i] == "\t") { if (currentWord.isNotEmpty) { words.add( Word(start: i - currentWord.length, end: i, text: currentWord)); currentWord = ""; } } else { currentWord += text[i]; } } if (currentWord.isNotEmpty) { words.add(Word( start: text.length - currentWord.length, end: text.length, text: currentWord)); } return words; } static List compare(String oldText, String newText) { var oldWords = splitToWords(oldText); var newWords = splitToWords(newText); int oldIndex = 0; int newIndex = 0; List textDeltas = []; while ((oldIndex < oldWords.length) && (newIndex < newWords.length)) { var oldWord = oldWords[oldIndex]; var newWord = newWords[newIndex]; if (oldWord.text == newWord.text) { oldIndex++; newIndex++; } else { var delta = TextDelta(); delta.wordDeltas.add(WordDelta(old: oldWord, modified: newWord)); textDeltas.add(delta); oldIndex++; newIndex++; if (oldIndex < oldWords.length && newIndex < newWords.length) { var nextOldWord = oldWords[oldIndex]; var newSubIndex = newIndex; var oldSubIndex = oldIndex; while (newSubIndex < newWords.length && newWords[newSubIndex].text != nextOldWord.text) { WordDelta wordDelta = WordDelta(old: nextOldWord, modified: newWords[newSubIndex]); delta.wordDeltas.add(wordDelta); newSubIndex++; oldSubIndex++; } if (newIndex != newSubIndex) { newIndex = newSubIndex; oldIndex = oldSubIndex; } } } } if (newIndex < newWords.length) { var delta = TextDelta(); while (newIndex < newWords.length) { delta.wordDeltas.add(WordDelta(modified: newWords[newIndex])); newIndex++; } textDeltas.add(delta); } if (oldIndex < oldWords.length) { var delta = TextDelta(); while (oldIndex < oldWords.length) { delta.wordDeltas.add(WordDelta(old: oldWords[oldIndex])); oldIndex++; } textDeltas.add(delta); } return textDeltas; } }