mirror of
https://github.com/LemmyNet/lemmy-ui.git
synced 2024-11-12 19:06:13 +00:00
Update community link markdown parsing
Remove links without remote servers, add kbin support, add user support
This commit is contained in:
parent
07235d7a5b
commit
c5779cd9b1
|
@ -8,7 +8,6 @@ import { CustomEmojiView } from "lemmy-js-client";
|
||||||
import { default as MarkdownIt } from "markdown-it";
|
import { default as MarkdownIt } from "markdown-it";
|
||||||
import markdown_it_container from "markdown-it-container";
|
import markdown_it_container from "markdown-it-container";
|
||||||
// import markdown_it_emoji from "markdown-it-emoji/bare";
|
// import markdown_it_emoji from "markdown-it-emoji/bare";
|
||||||
import { getHttpBase } from "@utils/env";
|
|
||||||
import markdown_it_footnote from "markdown-it-footnote";
|
import markdown_it_footnote from "markdown-it-footnote";
|
||||||
import markdown_it_html5_embed from "markdown-it-html5-embed";
|
import markdown_it_html5_embed from "markdown-it-html5-embed";
|
||||||
import markdown_it_sub from "markdown-it-sub";
|
import markdown_it_sub from "markdown-it-sub";
|
||||||
|
@ -74,73 +73,66 @@ const html5EmbedConfig = {
|
||||||
};
|
};
|
||||||
|
|
||||||
function localCommunityLinkParser(md) {
|
function localCommunityLinkParser(md) {
|
||||||
const pattern =
|
|
||||||
/(!\b[^@\s]+@[^@\s]+\.[^.\s]+\b)|\/c\/([^@\s]+)(@[^@\s]+\.[^.\s]+\b)?/g;
|
|
||||||
|
|
||||||
md.core.ruler.push("replace-text", state => {
|
md.core.ruler.push("replace-text", state => {
|
||||||
const tokens = state.tokens;
|
/**
|
||||||
|
* Accepted formats:
|
||||||
|
* !community@server.com
|
||||||
|
* /c/community@server.com
|
||||||
|
* /m/community@server.com
|
||||||
|
* /u/username@server.com
|
||||||
|
*/
|
||||||
|
const pattern =
|
||||||
|
/(\/[c|m|u]\/[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}|![a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,})/g;
|
||||||
|
|
||||||
for (let i = 0; i < tokens.length; i++) {
|
for (let i = 0; i < state.tokens.length; i++) {
|
||||||
if (tokens[i].type === "inline") {
|
if (state.tokens[i].type !== "inline") {
|
||||||
const token = tokens[i];
|
continue;
|
||||||
|
}
|
||||||
|
const inlineTokens = state.tokens[i].children;
|
||||||
|
for (let j = inlineTokens.length - 1; j >= 0; j--) {
|
||||||
|
if (
|
||||||
|
inlineTokens[j].type === "text" &&
|
||||||
|
pattern.test(inlineTokens[j].content)
|
||||||
|
) {
|
||||||
|
const textParts = inlineTokens[j].content.split(pattern);
|
||||||
|
const newTokens: Token[] = [];
|
||||||
|
|
||||||
const originalContent = token.content;
|
for (const part of textParts) {
|
||||||
|
let linkClass = "community-link";
|
||||||
|
if (pattern.test(part)) {
|
||||||
|
// Rewrite !community@server.com and KBin /m/community@server.com to local urls
|
||||||
|
let href;
|
||||||
|
if (part.startsWith("!")) {
|
||||||
|
href = "/c/" + part.substring(1);
|
||||||
|
} else if (part.startsWith("/m/")) {
|
||||||
|
href = "/c/" + part.substring(3);
|
||||||
|
} else {
|
||||||
|
href = part;
|
||||||
|
if (part.startsWith("/u/")) {
|
||||||
|
linkClass = "user-link";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
let lastIndex = 0;
|
const linkOpenToken = new state.Token("link_open", "a", 1);
|
||||||
originalContent.replace(
|
linkOpenToken.attrs = [
|
||||||
pattern,
|
["href", href],
|
||||||
(match, fullDomainMatch, name, domainTld, index) => {
|
["class", linkClass],
|
||||||
let url;
|
];
|
||||||
// ex: !Testing@example.com
|
const textToken = new state.Token("text", "", 0);
|
||||||
if (fullDomainMatch) {
|
textToken.content = part;
|
||||||
const [name, domain, tld] = fullDomainMatch
|
const linkCloseToken = new state.Token("link_close", "a", -1);
|
||||||
.slice(1)
|
|
||||||
.split("@")
|
newTokens.push(linkOpenToken, textToken, linkCloseToken);
|
||||||
.join(".")
|
|
||||||
.split(".");
|
|
||||||
url = `${getHttpBase()}/c/${name}@${domain}.${tld}`;
|
|
||||||
} else {
|
} else {
|
||||||
// ex: /c/Testing or /c/Testing@example.com
|
const textToken = new state.Token("text", "", 0);
|
||||||
url = `${getHttpBase()}/c/${name}${domainTld || ""}`;
|
textToken.content = part;
|
||||||
|
newTokens.push(textToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
const beforeContent = originalContent.slice(lastIndex, index);
|
|
||||||
lastIndex = index + match.length;
|
|
||||||
|
|
||||||
const beforeToken = new state.Token("text", "", 0);
|
|
||||||
beforeToken.content = beforeContent;
|
|
||||||
|
|
||||||
const linkOpenToken = new state.Token("link_open", "a", 1);
|
|
||||||
linkOpenToken.attrs = [
|
|
||||||
["href", url],
|
|
||||||
["class", "community-link"],
|
|
||||||
];
|
|
||||||
|
|
||||||
const textToken = new state.Token("text", "", 0);
|
|
||||||
textToken.content = match;
|
|
||||||
|
|
||||||
const linkCloseToken = new state.Token("link_close", "a", -1);
|
|
||||||
|
|
||||||
const afterContent = originalContent.slice(lastIndex);
|
|
||||||
const afterToken = new state.Token("text", "", 0);
|
|
||||||
afterToken.content = afterContent;
|
|
||||||
|
|
||||||
tokens.splice(i, 1);
|
|
||||||
|
|
||||||
tokens.splice(
|
|
||||||
i,
|
|
||||||
0,
|
|
||||||
beforeToken,
|
|
||||||
linkOpenToken,
|
|
||||||
textToken,
|
|
||||||
linkCloseToken,
|
|
||||||
afterToken
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update i to skip the newly added tokens
|
|
||||||
i += 4;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
// Replace the original token with the new tokens
|
||||||
|
inlineTokens.splice(j, 1, ...newTokens);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in a new issue