Spaces:
Running
Running
| /** | |
| * | |
| * Copyright 2023-2024 InspectorRAGet Team | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| * | |
| **/ | |
| import { StringMatchObject } from '@/src/types'; | |
| export function extractMatchesInTarget( | |
| matches: StringMatchObject[], | |
| ): { start: number; end: number; text: string }[] { | |
| // Step 1: Sort matches based on starting index of matches in the target | |
| const orderedMatches: StringMatchObject[] = Array.from(matches).toSorted( | |
| function (a: StringMatchObject, b: StringMatchObject) { | |
| return a.matchesInTarget[0].start - b.matchesInTarget[0].start; | |
| }, | |
| ); | |
| // Step 2: Return first match from target | |
| return orderedMatches.map((entry: StringMatchObject) => { | |
| return { | |
| start: entry.matchesInTarget[0].start, | |
| end: entry.matchesInTarget[0].end, | |
| text: entry.text, | |
| }; | |
| }); | |
| } | |
| /** | |
| * Add span tags in the text to create highlighting effect | |
| * @param text | |
| * @param matches | |
| * @param type | |
| * @returns | |
| */ | |
| export function mark( | |
| text: string, | |
| matches: StringMatchObject[], | |
| type: 'source' | 'target', | |
| ) { | |
| let markedText = ''; | |
| let curTextPos = 0; | |
| let curMatchListIdx = 0; | |
| const matchesToMark = | |
| type === 'source' ? matches : extractMatchesInTarget(matches); | |
| while (curTextPos < text.length && curMatchListIdx < matches.length) { | |
| let currentMatch = matchesToMark[curMatchListIdx]; | |
| let currentMatchStart = currentMatch.start; | |
| let currentMatchEnd = currentMatch.end; | |
| if (curTextPos < currentMatchStart) { | |
| if (type == 'source') { | |
| markedText += `<span>${text.substring( | |
| curTextPos, | |
| currentMatchStart, | |
| )}</span>`; | |
| } else if (type == 'target') { | |
| markedText += text.substring(curTextPos, currentMatchStart); | |
| } | |
| curTextPos = currentMatchStart - 1; | |
| } | |
| if (currentMatchStart >= curTextPos) { | |
| // Add info on the context match mapping | |
| if (type == 'source') { | |
| // @ts-expect-error | |
| const contextMatchStart = currentMatch.matchesInTarget[0].start; | |
| // @ts-expect-error | |
| const contextMatchEnd = currentMatch.matchesInTarget[0].end; | |
| markedText += `<span class='copiedText' context-match-id='${contextMatchStart}-${contextMatchEnd}'>${text.substring( | |
| currentMatchStart, | |
| currentMatchEnd, | |
| )}</span>`; | |
| } else if (type == 'target') { | |
| markedText += `<span class='copiedText' id='${currentMatchStart}-${currentMatchEnd}'>${text.substring( | |
| currentMatchStart, | |
| currentMatchEnd, | |
| )}</span>`; | |
| } | |
| curTextPos = currentMatchEnd; | |
| } | |
| curMatchListIdx++; | |
| } | |
| if (curTextPos < text.length) { | |
| if (type == 'source') { | |
| markedText += `<span>${text.substring(curTextPos, text.length)}</span>`; | |
| } else if (type == 'target') { | |
| markedText += text.substring(curTextPos, text.length); | |
| } | |
| } | |
| return markedText; | |
| } | |