Fix highlighting for hyphenated values. Improve highlighting text matching logic. Handle text split across items.

pull/92/head
s8613 2025-06-24 12:49:47 +02:00
parent 82f02c0772
commit ed34687dc4
3 changed files with 68 additions and 42 deletions

View File

@ -184,10 +184,10 @@ export default function KennzahlenTable({
<Table>
<TableHead>
<TableRow>
<TableCell width="25%">
<TableCell width="30%">
<strong>Kennzahl</strong>
</TableCell>
<TableCell width="60%">
<TableCell width="55%">
<strong>Wert</strong>
</TableCell>
<TableCell align="center" width="15%">

View File

@ -95,53 +95,78 @@ export default function PDFViewer({
useEffect(() => {
const tmpPos: string[] = [];
const tmpPosHighlight: string[] = [];
const textItems = textContent.filter(
(e) => e.text !== "" && e.text !== " ",
);
textItems.forEach((e, i) => {
for (const s of highlight
.filter((h) => h.page === pageNumber)
.map((h) => h.text)) {
if (s.split(" ")[0] === e.text) {
if (
s.split(" ").reduce((prev, curr, j) => {
return prev && curr === textItems[i + j].text;
}, true)
) {
for (
let k = textItems[i].i;
k < textItems[i + s.split(" ").length]?.i ||
k < textItems[i + s.split(" ").length - 1]?.i;
k++
if (textContent.length === 0) {
setPosHighlight([]);
setPosHighlightFocus([]);
return;
}
const findTextPositions = (searchText: string): number[] => {
const positions: number[] = [];
const normalizedSearch = searchText.toLowerCase().trim();
textContent.forEach((item, index) => {
if (item.text.toLowerCase().trim() === normalizedSearch) {
positions.push(index);
}
});
if (positions.length === 0) {
let cumulativeText = '';
const textBoundaries: { start: number; end: number; index: number }[] = [];
textContent.forEach((item, index) => {
const start = cumulativeText.length;
cumulativeText += item.text;
const end = cumulativeText.length;
textBoundaries.push({ start, end, index });
});
const lowerCumulative = cumulativeText.toLowerCase();
let searchIndex = lowerCumulative.indexOf(normalizedSearch);
while (searchIndex !== -1) {
const endIndex = searchIndex + normalizedSearch.length;
textBoundaries.forEach(boundary => {
if (
(boundary.start <= searchIndex && searchIndex < boundary.end) || // Search starts in this item
(boundary.start < endIndex && endIndex <= boundary.end) || // Search ends in this item
(searchIndex <= boundary.start && boundary.end <= endIndex) // This item is completely within search
) {
tmpPos.push(textContent[k].posKey);
if (!positions.includes(boundary.index)) {
positions.push(boundary.index);
}
}
}
});
searchIndex = lowerCumulative.indexOf(normalizedSearch, searchIndex + 1);
}
}
if (focusHighlight?.page === pageNumber) {
if (focusHighlight.text.split(" ")[0] === e.text) {
if (
focusHighlight.text.split(" ").reduce((prev, curr, j) => {
return prev && curr === textItems[i + j].text;
}, true)
) {
for (
let k = textItems[i].i;
k < textItems[i + focusHighlight.text.split(" ").length]?.i ||
k < textItems[i + focusHighlight.text.split(" ").length - 1]?.i;
k++
) {
tmpPosHighlight.push(textContent[k].posKey);
}
return positions.sort((a, b) => a - b);
};
highlight
.filter(h => h.page === pageNumber)
.forEach(highlightItem => {
const positions = findTextPositions(highlightItem.text);
positions.forEach(pos => {
if (pos >= 0 && pos < textContent.length) {
tmpPos.push(textContent[pos].posKey);
}
});
});
if (focusHighlight?.page === pageNumber && focusHighlight.text) {
const positions = findTextPositions(focusHighlight.text);
positions.forEach(pos => {
if (pos >= 0 && pos < textContent.length) {
tmpPosHighlight.push(textContent[pos].posKey);
}
}
});
setPosHighlight(tmpPos);
setPosHighlightFocus(tmpPosHighlight);
});
}
setPosHighlight([...new Set(tmpPos)]);
setPosHighlightFocus([...new Set(tmpPosHighlight)]);
}, [highlight, focusHighlight, pageNumber, textContent]);
const onGetTextSuccess: OnGetTextSuccess = useCallback((fullText) => {

View File

@ -183,6 +183,7 @@ function ExtractedResultsPage() {
setCustomValue(value);
setSelectedIndex(-1);
setFocusHighlightOverride(null);
}
const handleCustomPageChange = (
event: React.ChangeEvent<HTMLInputElement>,