Sharkey/src/mfm/html.ts

128 lines
3.5 KiB
TypeScript
Raw Normal View History

2018-06-17 13:55:39 +03:00
const { lib: emojilib } = require('emojilib');
2018-08-04 05:39:59 +03:00
const jsdom = require('jsdom');
const { JSDOM } = jsdom;
2018-05-17 02:14:30 +03:00
import config from '../config';
2018-06-17 09:58:23 +03:00
import { INote } from '../models/note';
2018-06-17 13:55:39 +03:00
import { TextElement } from './parse';
2018-09-05 20:28:04 +03:00
import { intersperse } from '../prelude/array';
2018-08-18 18:31:25 +03:00
2018-06-18 08:28:43 +03:00
const handlers: { [key: string]: (window: any, token: any, mentionedRemoteUsers: INote['mentionedRemoteUsers']) => void } = {
2018-03-31 13:53:30 +03:00
bold({ document }, { bold }) {
const b = document.createElement('b');
b.textContent = bold;
document.body.appendChild(b);
},
2018-08-03 17:27:37 +03:00
big({ document }, { big }) {
const b = document.createElement('strong');
b.textContent = big;
document.body.appendChild(b);
},
2018-08-05 06:33:51 +03:00
motion({ document }, { big }) {
const b = document.createElement('strong');
b.textContent = big;
document.body.appendChild(b);
},
2018-03-31 13:53:30 +03:00
code({ document }, { code }) {
const pre = document.createElement('pre');
const inner = document.createElement('code');
inner.innerHTML = code;
pre.appendChild(inner);
document.body.appendChild(pre);
},
emoji({ document }, { content, emoji }) {
const found = emojilib[emoji];
const node = document.createTextNode(found ? found.char : content);
document.body.appendChild(node);
},
hashtag({ document }, { hashtag }) {
2018-06-09 21:55:51 +03:00
const a = document.createElement('a');
2018-09-01 17:12:51 +03:00
a.href = `${config.url}/tags/${hashtag}`;
a.textContent = `#${hashtag}`;
2018-06-09 21:55:51 +03:00
a.setAttribute('rel', 'tag');
document.body.appendChild(a);
2018-03-31 13:53:30 +03:00
},
'inline-code'({ document }, { code }) {
const element = document.createElement('code');
element.textContent = code;
document.body.appendChild(element);
},
2018-11-16 10:03:52 +02:00
math({ document }, { formula }) {
const element = document.createElement('code');
element.textContent = formula;
document.body.appendChild(element);
},
2018-03-31 13:53:30 +03:00
link({ document }, { url, title }) {
const a = document.createElement('a');
a.href = url;
a.textContent = title;
document.body.appendChild(a);
},
2018-06-17 09:58:23 +03:00
mention({ document }, { content, username, host }, mentionedRemoteUsers) {
2018-03-31 13:53:30 +03:00
const a = document.createElement('a');
2018-06-17 09:58:23 +03:00
const remoteUserInfo = mentionedRemoteUsers.find(remoteUser => remoteUser.username === username && remoteUser.host === host);
a.href = remoteUserInfo ? remoteUserInfo.uri : `${config.url}/${content}`;
2018-03-31 13:53:30 +03:00
a.textContent = content;
document.body.appendChild(a);
},
quote({ document }, { quote }) {
const blockquote = document.createElement('blockquote');
blockquote.textContent = quote;
document.body.appendChild(blockquote);
},
2018-04-21 12:25:25 +03:00
title({ document }, { content }) {
2018-04-19 09:05:39 +03:00
const h1 = document.createElement('h1');
2018-04-21 12:25:25 +03:00
h1.textContent = content;
2018-04-19 09:05:39 +03:00
document.body.appendChild(h1);
},
2018-03-31 13:53:30 +03:00
text({ document }, { content }) {
2018-08-18 18:31:25 +03:00
const nodes = (content as string).split('\n').map(x => document.createTextNode(x));
2018-09-16 20:45:30 +03:00
for (const x of intersperse('br', nodes)) {
if (x === 'br') {
document.body.appendChild(document.createElement('br'));
} else {
document.body.appendChild(x);
}
2018-03-31 13:53:30 +03:00
}
},
url({ document }, { url }) {
const a = document.createElement('a');
a.href = url;
a.textContent = url;
document.body.appendChild(a);
2018-04-21 12:59:16 +03:00
},
search({ document }, { content, query }) {
const a = document.createElement('a');
a.href = `https://www.google.com/?#q=${query}`;
a.textContent = content;
document.body.appendChild(a);
2018-03-31 13:53:30 +03:00
}
};
2018-06-17 13:55:39 +03:00
export default (tokens: TextElement[], mentionedRemoteUsers: INote['mentionedRemoteUsers'] = []) => {
2018-07-01 07:46:34 +03:00
if (tokens == null) {
return null;
}
2018-03-31 13:53:30 +03:00
const { window } = new JSDOM('');
for (const token of tokens) {
2018-06-17 09:58:23 +03:00
handlers[token.type](window, token, mentionedRemoteUsers);
2018-03-31 13:53:30 +03:00
}
return `<p>${window.document.body.innerHTML}</p>`;
};