migrate to unified "capabilities" API

This commit is contained in:
ari melody 2024-06-21 04:55:24 +01:00
parent 7779845056
commit 191212c940
Signed by: ari
GPG key ID: CF99829C92678188
6 changed files with 198 additions and 246 deletions

View file

@ -1,4 +1,5 @@
import { Client, server_types } from '../client/client.js';
import { Client } from '../client/client.js';
import { capabilities, server_types } from '../client/instance.js';
import { parseOne as parseEmoji, EMOJI_REGEX } from '../emoji.js';
export default class Post {
@ -20,33 +21,36 @@ export default class Post {
async rich_text() {
let text = this.text;
if (!text) return text;
let client = Client.get();
const markdown_tokens = [
{ tag: "pre", token: "```" },
{ tag: "code", token: "`" },
{ tag: "strong", token: "**", regex: /\*{2}/g },
{ tag: "strong", token: "**" },
{ tag: "strong", token: "__" },
{ tag: "em", token: "*", regex: /\*/g },
{ tag: "em", token: "*" },
{ tag: "em", token: "_" },
];
let response = "";
let current;
let md_layer;
let index = 0;
while (index < text.length) {
let sample = text.substring(index);
let allow_new = !current || !current.nostack;
let md_nostack = !(md_layer && md_layer.nostack);
// handle newlines
if (allow_new && sample.startsWith('\n')) {
if (md_nostack && sample.startsWith('\n')) {
response += "<br>";
index++;
continue;
}
// handle mentions
// TODO: setup a better system for handling different server capabilities
if (Client.get().instance.type !== server_types.MASTODON && allow_new && sample.match(/^@[\w\-.]+@[\w\-.]+/g)) {
if (client.instance.capabilities.includes(capabilities.MARKDOWN_CONTENT)
&& md_nostack
&& sample.match(/^@[\w\-.]+@[\w\-.]+/g)
) {
// find end of the mention
let length = 1;
while (index + length < text.length && /[a-z0-9-_.]/.test(text[index + length])) length++;
@ -56,12 +60,12 @@ export default class Post {
let mention = text.substring(index, index + length);
// attempt to resolve mention to a user
let user = await Client.get().getUserByMention(mention);
let user = await client.getUserByMention(mention);
if (user) {
const out = `<a href="/${user.mention}" class="mention">` +
`<img src="${user.avatar_url}" class="mention-avatar" width="20" height="20">` +
'@' + user.username + '@' + user.host + "</a>";
if (current) current.text += out;
if (md_layer) md_layer.text += out;
else response += out;
} else {
response += mention;
@ -71,72 +75,75 @@ export default class Post {
}
// handle links
if (Client.get().instance.type !== server_types.MASTODON && allow_new && sample.match(/^[a-z]{3,6}:\/\/[^\s]+/g)) {
if (client.instance.capabilities.includes(capabilities.MARKDOWN_CONTENT)
&& md_nostack
&& sample.match(/^[a-z]{3,6}:\/\/[^\s]+/g)
) {
// get length of link
let length = text.substring(index).search(/\s|$/g);
let url = text.substring(index, index + length);
let out = `<a href="${url}">${url}</a>`;
if (current) current.text += out;
if (md_layer) md_layer.text += out;
else response += out;
index += length;
continue;
}
// handle emojis
if (allow_new && sample.match(/^:[\w\-.]{0,32}:/g)) {
if (md_nostack && sample.match(/^:[\w\-.]{0,32}:/g)) {
// find the emoji name
let length = text.substring(index + 1).search(':');
if (length <= 0) return text;
let emoji_name = text.substring(index + 1, index + length + 1);
let emoji = Client.get().getEmoji(emoji_name + '@' + this.user.host);
let emoji = client.getEmoji(emoji_name + '@' + this.user.host);
index += length + 2;
if (!emoji) {
let out = ':' + emoji_name + ':';
if (current) current.text += out;
if (md_layer) md_layer.text += out;
else response += out;
continue;
}
let out = emoji.html;
if (current) current.text += out;
if (md_layer) md_layer.text += out;
else response += out;
continue;
}
// handle markdown
// TODO: handle misskey-flavoured markdown
if (current) {
// try to pop stack
if (sample.startsWith(current.token)) {
index += current.token.length;
let out = `<${current.tag}>${current.text}</${current.tag}>`;
if (current.token === '```')
out = `<code><pre>${current.text}</pre></code>`;
if (current.parent) current.parent.text += out;
// TODO: handle misskey-flavoured markdown(?)
if (md_layer) {
// try to pop layer
if (sample.startsWith(md_layer.token)) {
index += md_layer.token.length;
let out = `<${md_layer.tag}>${md_layer.text}</${md_layer.tag}>`;
if (md_layer.token === '```')
out = `<code><pre>${md_layer.text}</pre></code>`;
if (md_layer.parent) md_layer.parent.text += out;
else response += out;
current = current.parent;
md_layer = md_layer.parent;
} else {
current.text += sample[0];
md_layer.text += sample[0];
index++;
}
} else if (allow_new) {
// can we add to stack?
} else if (md_nostack) {
// should we add a layer?
let pushed = false;
for (let i = 0; i < markdown_tokens.length; i++) {
let item = markdown_tokens[i];
if (sample.startsWith(item.token)) {
let new_current = {
let new_md_layer = {
token: item.token,
tag: item.tag,
text: "",
parent: current,
parent: md_layer,
};
if (item.token === '```' || item.token === '`') new_current.nostack = true;
current = new_current;
if (item.token === '```' || item.token === '`') new_md_layer.nostack = true;
md_layer = new_md_layer;
pushed = true;
index += current.token.length;
index += md_layer.token.length;
break;
}
}
@ -148,11 +155,11 @@ export default class Post {
}
// destroy the remaining stack
while (current) {
let out = current.token + current.text;
if (current.parent) current.parent.text += out;
while (md_layer) {
let out = md_layer.token + md_layer.text;
if (md_layer.parent) md_layer.parent.text += out;
else response += out;
current = current.parent;
md_layer = md_layer.parent;
}
return response;