In most host applications the DocumentModel can not be used to track the changes the user made to the source content. The lookup is used to adjust the offset changes makde by the user.
        public void ReplaceRanges(IReadOnlyList<MatchWithReplacement> matches, DocumentModel model, Format format)
        {
            var modifiedRanges = new List<IRange>(matches.Select<Match, IRange>(x => model.OriginalToModifiedRange(x.Range)));

            var currentExtraction = Extract(format);

            var lookup = new Lookup(model.Content);
            var searchResult = lookup.Search(currentExtraction, modifiedRanges);

            var lengthDiff = 0;

            if (searchResult.Count == 0)
            {
                throw new MatchesNotFoundException("Lookup returned an empty list. Maybe source document was change by user?", matches, null);
            }

            for (var i = searchResult.Count - 1; i >= 0; i--)
            {
                var match = searchResult[i];
                var replacement = matches[i].Replacement;

                IRange rawRange= ToRawRange(format, currentExtraction, match,false);

                var rawOriginalTextLength = (!EncodeContent && format != Format.Text) ? DecodedLength(currentExtraction.Substring(match.Start, match.Length)) : match.Length;
                var rawReplacement =  (!EncodeContent && format != Format.Text) ? XmlEncode(replacement) : replacement;

                if (rawRange.Length == 0)
                {
                    throw new MatchesNotFoundException("", new Match[]{matches[i]}, null);
                }

                lengthDiff += rawReplacement.Length - rawOriginalTextLength;

                ReplaceRawRange(rawRange, rawReplacement, format);
                model.Update(matches[i].Range, ((format != Format.Text) ? XmlEncode(replacement) : replacement));
            }

            var rangeWithTag = new Range(searchResult[0].Start, searchResult[searchResult.Count - 1].End);
            IRange range = ToRawRange(format, currentExtraction, rangeWithTag, false);
            SelectRawRange(new Range(range.Start, range.End + lengthDiff), format);
        }
        public void SelectRanges(IReadOnlyList<Match> matches, DocumentModel model, Format format)
        {
            var modifiedRanges = new List<IRange>(matches.Select<Match, IRange>(x => model.OriginalToModifiedRange(x.Range)));

            var currentExtraction = Extract(format);

            var lookup = new Lookup(model.Content);
            var searchResult = lookup.Search(currentExtraction, modifiedRanges);

            if(searchResult.Count == 0)
            {
                throw new MatchesNotFoundException("Lookup returned an empty list. Maybe source document was change by user?", matches, null);
            }

            var rangeWithTag = new Range(searchResult[0].Start, searchResult[searchResult.Count - 1].End);

            IRange range = ToRawRange(format, currentExtraction, rangeWithTag, false);
            SelectRawRange(range, format);
        }