Skip to content

Commit 073e262

Browse files
authoredSep 24, 2024··
Fix custom annotation link (#741)
* - Fix link adding logic * - Add clarity comment
1 parent 7d4f317 commit 073e262

File tree

1 file changed

+67
-50
lines changed

1 file changed

+67
-50
lines changed
 

‎frontend/src/pages/ontologies/entities/entityPageSections/addLinksToText.tsx

+67-50
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import { randomString } from "../../../../app/util";
44
import EntityLink from "../../../../components/EntityLink";
55
import Entity from "../../../../model/Entity";
66
import LinkedEntities from "../../../../model/LinkedEntities";
7-
import Image3D from "../../../../components/Image3D";
87

98
export default function addLinksToText(
109
text: string,
@@ -13,15 +12,53 @@ export default function addLinksToText(
1312
currentEntity: Entity | undefined,
1413
entityType: "ontologies" | "classes" | "properties" | "individuals"
1514
) {
16-
let linksToSplice: Array<{ start: number; end: number; link: JSX.Element }> =
17-
[];
1815

16+
let linksToSplice: Array<{ start: number; end: number; link: JSX.Element }> = [];
17+
let urlMatches: Array<{ start: number; end: number }> = []; // To store the ranges of URLs
18+
19+
// First, find all URLs and record their ranges
20+
const urlRe = /[A-z]+:\/\/[^\s]+/g;
21+
for (let match = urlRe.exec(text); match; match = urlRe.exec(text)) {
22+
const url = match[0];
23+
linksToSplice.push({
24+
start: match.index,
25+
end: match.index + url.length,
26+
link: (
27+
<span key={url + randomString()}>
28+
<Link
29+
to={url}
30+
className="link-default pr-1"
31+
target="_blank"
32+
rel="noopener noreferrer"
33+
>
34+
{url}
35+
</Link>
36+
</span>
37+
),
38+
});
39+
urlMatches.push({ start: match.index, end: match.index + url.length });
40+
}
41+
42+
// Then, process entity IDs
1943
for (let entityId of Object.keys(linkedEntities.linkedEntities)) {
2044
for (
2145
let n = text.indexOf(entityId, 0);
2246
n !== -1;
2347
n = text.indexOf(entityId, n)
2448
) {
49+
// We need to handle this case when entity ID is part of a URL and it then gets linked to an entity but
50+
// resulting url is broken. So, we need to keep the URL as is if the entity ID is part of a URL.
51+
// Check if the entity ID is within any URL range
52+
let isWithinURL = urlMatches.some(
53+
(urlRange) =>
54+
n >= urlRange.start && n + entityId.length <= urlRange.end
55+
);
56+
if (isWithinURL) {
57+
// Skip this entity ID because it's part of a URL
58+
n += entityId.length;
59+
continue;
60+
}
61+
2562
linksToSplice.push({
2663
start: n,
2764
end: n + entityId.length,
@@ -41,65 +78,45 @@ export default function addLinksToText(
4178
}
4279
}
4380

44-
const urlRe = /[A-z]+:\/\/[^\s]+/g;
45-
for (let match = urlRe.exec(text); match; match = urlRe.exec(text)) {
46-
const url = match[0];
47-
// console.log("found match " + url);
48-
linksToSplice.push({
49-
start: match.index,
50-
end: match.index + url.length,
51-
link: (
52-
<span>
53-
<Link
54-
key={url + randomString()}
55-
to={url}
56-
className="link-default pr-1"
57-
target="_blank"
58-
rel="noopener noreferrer"
59-
>
60-
{url}
61-
</Link>
62-
</span>
63-
),
64-
});
65-
}
66-
67-
removeOverlapping: for (let n = 0; n < linksToSplice.length; ) {
68-
for (let n2 = 0; n2 < linksToSplice.length; ++n2) {
69-
let spliceA = linksToSplice[n];
70-
let spliceB = linksToSplice[n2];
81+
// Remove overlapping links by sorting and keeping the first one
82+
linksToSplice.sort((a, b) => a.start - b.start);
7183

72-
if (spliceA === spliceB) continue;
73-
74-
// The splices overlap if neither ends before the other starts
75-
if (spliceA.end >= spliceB.start && spliceB.end >= spliceA.start) {
76-
// console.log("Removing overlapping");
77-
linksToSplice.splice(n2, 1);
78-
continue removeOverlapping;
79-
}
84+
// Remove overlaps
85+
for (let i = 0; i < linksToSplice.length - 1; i++) {
86+
const current = linksToSplice[i];
87+
const next = linksToSplice[i + 1];
88+
if (current.end > next.start) {
89+
// Overlap detected, remove the next link
90+
linksToSplice.splice(i + 1, 1);
91+
i--; // Adjust index after removal
8092
}
81-
++n;
8293
}
8394

8495
if (linksToSplice.length === 0) return text;
8596

86-
// linksToSplice.sort((a, b) => a.start - b.start);
87-
// console.dir(linksToSplice);
97+
// Build the final result
8898
let res: JSX.Element[] = [];
89-
let n = 0;
99+
let lastIndex = 0;
90100

91101
for (let link of linksToSplice) {
102+
if (lastIndex < link.start) {
103+
res.push(
104+
<Fragment key={randomString()}>
105+
{text.substring(lastIndex, link.start)}
106+
</Fragment>
107+
);
108+
}
109+
res.push(link.link);
110+
lastIndex = link.end;
111+
}
112+
113+
if (lastIndex < text.length) {
92114
res.push(
93-
<Fragment key={text.substring(n, link.start) + randomString()}>
94-
{text.substring(n, link.start)}
95-
</Fragment>
115+
<Fragment key={text.substring(lastIndex) + randomString()}>
116+
{text.substring(lastIndex)}
117+
</Fragment>
96118
);
97-
res.push(link.link);
98-
n = link.end;
99119
}
100-
res.push(
101-
<Fragment key={text.slice(n) + randomString()}>{text.slice(n)}</Fragment>
102-
);
103120

104121
return res;
105122
}

0 commit comments

Comments
 (0)
Please sign in to comment.