thelounge/shared/linkify.ts
Reto Brunner a8149c0f1a Extract linkify to shared directory
This is the first step to sever any dependency of the server on
the client
2023-01-30 09:14:40 +01:00

85 lines
1.5 KiB
TypeScript

import LinkifyIt, {Match} from "linkify-it";
import tlds from "tlds";
export type NoSchemaMatch = Match & {
noschema: boolean;
};
export type LinkPart = {
start: number;
end: number;
link: string;
};
LinkifyIt.prototype.normalize = function normalize(match: NoSchemaMatch) {
match.noschema = false;
if (!match.schema) {
match.schema = "http:";
match.url = "http://" + match.url;
match.noschema = true;
}
if (match.schema === "//") {
match.schema = "http:";
match.url = "http:" + match.url;
match.noschema = true;
}
if (match.schema === "mailto:" && !/^mailto:/i.test(match.url)) {
match.url = "mailto:" + match.url;
}
};
const linkify = LinkifyIt().tlds(tlds).tlds("onion", true);
// Known schemes to detect in text
const commonSchemes = [
"sftp",
"smb",
"file",
"irc",
"ircs",
"svn",
"git",
"steam",
"mumble",
"ts3server",
"svn+ssh",
"ssh",
"gopher",
"gemini",
];
for (const schema of commonSchemes) {
linkify.add(schema + ":", "http:");
}
export function findLinks(text: string) {
const matches = linkify.match(text) as NoSchemaMatch[];
if (!matches) {
return [];
}
return matches.map(makeLinkPart);
}
export function findLinksWithSchema(text: string) {
const matches = linkify.match(text) as NoSchemaMatch[];
if (!matches) {
return [];
}
return matches.filter((url) => !url.noschema).map(makeLinkPart);
}
function makeLinkPart(url: NoSchemaMatch): LinkPart {
return {
start: url.index,
end: url.lastIndex,
link: url.url,
};
}