From a8149c0f1ab4d166c8fcada860b4bc9355b807ad Mon Sep 17 00:00:00 2001 From: Reto Brunner Date: Sun, 29 Jan 2023 16:58:33 +0100 Subject: [PATCH] Extract linkify to shared directory This is the first step to sever any dependency of the server on the client --- server/plugins/irc-events/link.ts | 2 +- server/tsconfig.json | 3 +- shared/linkify.ts | 84 +++++++++++++++++++++++++++++++ shared/tsconfig.json | 13 +++++ 4 files changed, 100 insertions(+), 2 deletions(-) create mode 100644 shared/linkify.ts create mode 100644 shared/tsconfig.json diff --git a/server/plugins/irc-events/link.ts b/server/plugins/irc-events/link.ts index e370fc7a..9755d556 100644 --- a/server/plugins/irc-events/link.ts +++ b/server/plugins/irc-events/link.ts @@ -5,7 +5,7 @@ import mime from "mime-types"; import log from "../../log"; import Config from "../../config"; -import {findLinksWithSchema} from "../../../client/js/helpers/ircmessageparser/findLinks"; +import {findLinksWithSchema} from "../../../shared/linkify"; import storage from "../storage"; import Client from "../../client"; import Chan from "../../models/chan"; diff --git a/server/tsconfig.json b/server/tsconfig.json index b62bf9eb..1c012b95 100644 --- a/server/tsconfig.json +++ b/server/tsconfig.json @@ -2,7 +2,8 @@ "extends": "../tsconfig.base.json" /* Path to base configuration file to inherit from. Requires TypeScript version 2.1 or later. */, "include": [ "**/*", - "../client/js/helpers/ircmessageparser/*.ts" + "../client/js/helpers/ircmessageparser/*.ts", + "../shared/" ] /* Specifies a list of glob patterns that match files to be included in compilation. If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. Requires TypeScript version 2.0 or later. */, "files": [ "../client/js/constants.ts", diff --git a/shared/linkify.ts b/shared/linkify.ts new file mode 100644 index 00000000..b403b533 --- /dev/null +++ b/shared/linkify.ts @@ -0,0 +1,84 @@ +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, + }; +} diff --git a/shared/tsconfig.json b/shared/tsconfig.json new file mode 100644 index 00000000..fedb8212 --- /dev/null +++ b/shared/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../tsconfig.base.json" /* Path to base configuration file to inherit from. Requires TypeScript version 2.1 or later. */, + "include": [ + "*" + ] /* Specifies a list of glob patterns that match files to be included in compilation. If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. Requires TypeScript version 2.0 or later. */, + "files": [] /* If no 'files' or 'include' property is present in a tsconfig.json, the compiler defaults to including all files in the containing directory and subdirectories except those specified by 'exclude'. When a 'files' property is specified, only those files and those specified by 'include' are included. */, + "ts-node": { + "files": true + }, + "compilerOptions": { + "noEmit": false /* Disable emitting file from a compilation. See more: https://www.typescriptlang.org/tsconfig#noEmit */ + } +}