]> Untitled Git - lemmy-ui.git/commitdiff
Merge branch 'main' into main
authorZetaphor <Zetaphor@users.noreply.github.com>
Thu, 22 Jun 2023 18:53:50 +0000 (15:53 -0300)
committerGitHub <noreply@github.com>
Thu, 22 Jun 2023 18:53:50 +0000 (15:53 -0300)
src/shared/config.ts
src/shared/markdown.ts

index 28e8ce5119a5046125e62c4f9b0e98f088926188..c56c64b0c2c3f1afce182f3598d1afebf432f1c5 100644 (file)
@@ -25,4 +25,14 @@ export const fetchLimit = 40;
 export const relTags = "noopener nofollow";
 export const emDash = "\u2014";
 
+/**
+ * Accepted formats:
+ * !community@server.com
+ * /c/community@server.com
+ * /m/community@server.com
+ * /u/username@server.com
+ */
+export const instanceLinkRegex =
+  /(\/[cmu]\/|!)[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}/g;
+
 export const testHost = "0.0.0.0:8536";
index 8f4d5c238ac5bf8a71015ece3520deedc50ac399..ececf47996c253e5a9b93a8212bf998ad330cecf 100644 (file)
@@ -14,6 +14,7 @@ import markdown_it_sub from "markdown-it-sub";
 import markdown_it_sup from "markdown-it-sup";
 import Renderer from "markdown-it/lib/renderer";
 import Token from "markdown-it/lib/token";
+import { instanceLinkRegex } from "./config";
 
 export let Tribute: any;
 
@@ -72,6 +73,78 @@ const html5EmbedConfig = {
   },
 };
 
+function localCommunityLinkParser(md: MarkdownIt) {
+  md.core.ruler.push("replace-text", state => {
+    for (let i = 0; i < state.tokens.length; i++) {
+      if (state.tokens[i].type !== "inline") {
+        continue;
+      }
+      const inlineTokens: Token[] = state.tokens[i].children || [];
+      for (let j = inlineTokens.length - 1; j >= 0; j--) {
+        if (
+          inlineTokens[j].type === "text" &&
+          new RegExp(instanceLinkRegex).test(inlineTokens[j].content)
+        ) {
+          const text = inlineTokens[j].content;
+          const matches = Array.from(text.matchAll(instanceLinkRegex));
+
+          let lastIndex = 0;
+          const newTokens: Token[] = [];
+
+          let linkClass = "community-link";
+
+          for (const match of matches) {
+            // If there is plain text before the match, add it as a separate token
+            if (match.index !== undefined && match.index > lastIndex) {
+              const textToken = new state.Token("text", "", 0);
+              textToken.content = text.slice(lastIndex, match.index);
+              newTokens.push(textToken);
+            }
+
+            // Determine the new href
+            let href;
+            if (match[0].startsWith("!")) {
+              href = "/c/" + match[0].substring(1);
+            } else if (match[0].startsWith("/m/")) {
+              href = "/c/" + match[0].substring(3);
+            } else {
+              href = match[0];
+            }
+
+            if (match[0].startsWith("/u/")) {
+              linkClass = "user-link";
+            }
+
+            const linkOpenToken = new state.Token("link_open", "a", 1);
+            linkOpenToken.attrs = [
+              ["href", href],
+              ["class", linkClass],
+            ];
+            const textToken = new state.Token("text", "", 0);
+            textToken.content = match[0];
+            const linkCloseToken = new state.Token("link_close", "a", -1);
+
+            newTokens.push(linkOpenToken, textToken, linkCloseToken);
+
+            lastIndex =
+              (match.index !== undefined ? match.index : 0) + match[0].length;
+          }
+
+          // If there is plain text after the last match, add it as a separate token
+          if (lastIndex < text.length) {
+            const textToken = new state.Token("text", "", 0);
+            textToken.content = text.slice(lastIndex);
+            newTokens.push(textToken);
+          }
+
+          // Replace the original token with the new tokens
+          inlineTokens.splice(j, 1, ...newTokens);
+        }
+      }
+    }
+  });
+}
+
 export function setupMarkdown() {
   const markdownItConfig: MarkdownIt.Options = {
     html: false,
@@ -88,7 +161,8 @@ export function setupMarkdown() {
     .use(markdown_it_sup)
     .use(markdown_it_footnote)
     .use(markdown_it_html5_embed, html5EmbedConfig)
-    .use(markdown_it_container, "spoiler", spoilerConfig);
+    .use(markdown_it_container, "spoiler", spoilerConfig)
+    .use(localCommunityLinkParser);
   // .use(markdown_it_emoji, {
   //   defs: emojiDefs,
   // });
@@ -99,6 +173,7 @@ export function setupMarkdown() {
     .use(markdown_it_footnote)
     .use(markdown_it_html5_embed, html5EmbedConfig)
     .use(markdown_it_container, "spoiler", spoilerConfig)
+    .use(localCommunityLinkParser)
     // .use(markdown_it_emoji, {
     //   defs: emojiDefs,
     // })