Skip to content

Commit

Permalink
Fix custom annotation link (#741)
Browse files Browse the repository at this point in the history
* - Fix link adding logic

* - Add clarity comment
  • Loading branch information
haideriqbal authored Sep 24, 2024
1 parent 7d4f317 commit 073e262
Showing 1 changed file with 67 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { randomString } from "../../../../app/util";
import EntityLink from "../../../../components/EntityLink";
import Entity from "../../../../model/Entity";
import LinkedEntities from "../../../../model/LinkedEntities";
import Image3D from "../../../../components/Image3D";

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

let linksToSplice: Array<{ start: number; end: number; link: JSX.Element }> = [];
let urlMatches: Array<{ start: number; end: number }> = []; // To store the ranges of URLs

// First, find all URLs and record their ranges
const urlRe = /[A-z]+:\/\/[^\s]+/g;
for (let match = urlRe.exec(text); match; match = urlRe.exec(text)) {
const url = match[0];
linksToSplice.push({
start: match.index,
end: match.index + url.length,
link: (
<span key={url + randomString()}>
<Link
to={url}
className="link-default pr-1"
target="_blank"
rel="noopener noreferrer"
>
{url}
</Link>
</span>
),
});
urlMatches.push({ start: match.index, end: match.index + url.length });
}

// Then, process entity IDs
for (let entityId of Object.keys(linkedEntities.linkedEntities)) {
for (
let n = text.indexOf(entityId, 0);
n !== -1;
n = text.indexOf(entityId, n)
) {
// We need to handle this case when entity ID is part of a URL and it then gets linked to an entity but
// resulting url is broken. So, we need to keep the URL as is if the entity ID is part of a URL.
// Check if the entity ID is within any URL range
let isWithinURL = urlMatches.some(
(urlRange) =>
n >= urlRange.start && n + entityId.length <= urlRange.end
);
if (isWithinURL) {
// Skip this entity ID because it's part of a URL
n += entityId.length;
continue;
}

linksToSplice.push({
start: n,
end: n + entityId.length,
Expand All @@ -41,65 +78,45 @@ export default function addLinksToText(
}
}

const urlRe = /[A-z]+:\/\/[^\s]+/g;
for (let match = urlRe.exec(text); match; match = urlRe.exec(text)) {
const url = match[0];
// console.log("found match " + url);
linksToSplice.push({
start: match.index,
end: match.index + url.length,
link: (
<span>
<Link
key={url + randomString()}
to={url}
className="link-default pr-1"
target="_blank"
rel="noopener noreferrer"
>
{url}
</Link>
</span>
),
});
}

removeOverlapping: for (let n = 0; n < linksToSplice.length; ) {
for (let n2 = 0; n2 < linksToSplice.length; ++n2) {
let spliceA = linksToSplice[n];
let spliceB = linksToSplice[n2];
// Remove overlapping links by sorting and keeping the first one
linksToSplice.sort((a, b) => a.start - b.start);

if (spliceA === spliceB) continue;

// The splices overlap if neither ends before the other starts
if (spliceA.end >= spliceB.start && spliceB.end >= spliceA.start) {
// console.log("Removing overlapping");
linksToSplice.splice(n2, 1);
continue removeOverlapping;
}
// Remove overlaps
for (let i = 0; i < linksToSplice.length - 1; i++) {
const current = linksToSplice[i];
const next = linksToSplice[i + 1];
if (current.end > next.start) {
// Overlap detected, remove the next link
linksToSplice.splice(i + 1, 1);
i--; // Adjust index after removal
}
++n;
}

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

// linksToSplice.sort((a, b) => a.start - b.start);
// console.dir(linksToSplice);
// Build the final result
let res: JSX.Element[] = [];
let n = 0;
let lastIndex = 0;

for (let link of linksToSplice) {
if (lastIndex < link.start) {
res.push(
<Fragment key={randomString()}>
{text.substring(lastIndex, link.start)}
</Fragment>
);
}
res.push(link.link);
lastIndex = link.end;
}

if (lastIndex < text.length) {
res.push(
<Fragment key={text.substring(n, link.start) + randomString()}>
{text.substring(n, link.start)}
</Fragment>
<Fragment key={text.substring(lastIndex) + randomString()}>
{text.substring(lastIndex)}
</Fragment>
);
res.push(link.link);
n = link.end;
}
res.push(
<Fragment key={text.slice(n) + randomString()}>{text.slice(n)}</Fragment>
);

return res;
}

0 comments on commit 073e262

Please sign in to comment.