mirror of
https://github.com/thelounge/thelounge
synced 2024-11-28 15:00:37 +00:00
dd24cb1300
Overriding the built in is poor form, as this prevents adding a new type handler with its own normalize handler. We only ever want to override protocol-less URLs to http, so we just do so explicitly in the "//" schema normalizer. This also means that we don't need all that type conversion dance, we simply set the schema to null when we patch it and filter on the schema directly
95 lines
1.8 KiB
TypeScript
95 lines
1.8 KiB
TypeScript
import LinkifyIt, {Match} from "linkify-it";
|
|
import tlds from "tlds";
|
|
|
|
export type LinkPart = {
|
|
start: number;
|
|
end: number;
|
|
link: string;
|
|
};
|
|
|
|
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:");
|
|
}
|
|
|
|
linkify.add("web+", {
|
|
validate(text: string, pos: number, self: LinkifyIt.LinkifyIt) {
|
|
const webSchemaRe = /^[a-z]+:/gi;
|
|
|
|
if (!webSchemaRe.test(text.slice(pos))) {
|
|
return 0;
|
|
}
|
|
|
|
const linkEnd = self.testSchemaAt(text, "http:", pos + webSchemaRe.lastIndex);
|
|
|
|
if (linkEnd === 0) {
|
|
return 0;
|
|
}
|
|
|
|
return webSchemaRe.lastIndex + linkEnd;
|
|
},
|
|
normalize(match) {
|
|
match.schema = match.text.slice(0, match.text.indexOf(":") + 1);
|
|
},
|
|
});
|
|
|
|
// we must rewrite protocol less urls to http, else if TL is hosted
|
|
// on https, this would incorrectly use https for the remote link.
|
|
// See https://github.com/thelounge/thelounge/issues/2525
|
|
//
|
|
// We take the validation logic from linkify and just add our own
|
|
// normalizer.
|
|
linkify.add("//", {
|
|
validate: (linkify as any).__schemas__["//"].validate,
|
|
normalize(match) {
|
|
match.schema = ""; // this counts as not having a schema
|
|
match.url = "http:" + match.url;
|
|
},
|
|
});
|
|
|
|
export function findLinks(text: string) {
|
|
const matches = linkify.match(text);
|
|
|
|
if (!matches) {
|
|
return [];
|
|
}
|
|
|
|
return matches.map(makeLinkPart);
|
|
}
|
|
|
|
export function findLinksWithSchema(text: string) {
|
|
const matches = linkify.match(text);
|
|
|
|
if (!matches) {
|
|
return [];
|
|
}
|
|
|
|
return matches.filter((url) => !!url.schema).map(makeLinkPart);
|
|
}
|
|
|
|
function makeLinkPart(url: Match): LinkPart {
|
|
return {
|
|
start: url.index,
|
|
end: url.lastIndex,
|
|
link: url.url,
|
|
};
|
|
}
|