1// Copyright 2021 The Tint Authors. 2// 3// Licensed under the Apache License, Version 2.0 (the "License"); 4// you may not use this file except in compliance with the License. 5// You may obtain a copy of the License at 6// 7// http://www.apache.org/licenses/LICENSE-2.0 8// 9// Unless required by applicable law or agreed to in writing, software 10// distributed under the License is distributed on an "AS IS" BASIS, 11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12// See the License for the specific language governing permissions and 13// limitations under the License. 14 15package substr 16 17import ( 18 diff "github.com/sergi/go-diff/diffmatchpatch" 19) 20 21// Fix attempts to reconstruct substr by comparing it to body. 22// substr is a fuzzy substring of body. 23// Fix returns a new exact substring of body, by calculating a diff of the text. 24// If no match could be made, Fix() returns an empty string. 25func Fix(body, substr string) string { 26 dmp := diff.New() 27 28 diffs := dmp.DiffMain(body, substr, false) 29 if len(diffs) == 0 { 30 return "" 31 } 32 33 front := func() diff.Diff { return diffs[0] } 34 back := func() diff.Diff { return diffs[len(diffs)-1] } 35 36 start, end := 0, len(body) 37 38 // Trim edits that remove text from body start 39 for len(diffs) > 0 && front().Type == diff.DiffDelete { 40 start += len(front().Text) 41 diffs = diffs[1:] 42 } 43 44 // Trim edits that remove text from body end 45 for len(diffs) > 0 && back().Type == diff.DiffDelete { 46 end -= len(back().Text) 47 diffs = diffs[:len(diffs)-1] 48 } 49 50 // New substring is the span for the remainder of the edits 51 return body[start:end] 52} 53