1 | function escapeMarkdownPart(input) {
|
2 | return [
|
3 |
|
4 |
|
5 | [/([\#\*\(\)\[\]\_\`\\])/g, '\\$1'],
|
6 |
|
7 |
|
8 | [/\</g, '<'],
|
9 | [/\>/g, '>']
|
10 |
|
11 | ].reduce((input, [replaceFrom, replaceTo]) => input.replace(replaceFrom, replaceTo), input);
|
12 | }
|
13 |
|
14 | function escapeMarkdown(input) {
|
15 | return escapeMarkdownPart(input)
|
16 |
|
17 | .replace(/^(\d+)\./, '$1\\.');
|
18 | }
|
19 |
|
20 | function renderEntityMention(data) {
|
21 | return `[@${escapeMarkdownPart(data.screen_name)}](https://twitter.com/${data.screen_name} "${data.name}")`;
|
22 | }
|
23 |
|
24 | function renderEntityMedia(data) {
|
25 | return `[${escapeMarkdownPart(data.display_url)}](${data.url})`;
|
26 | }
|
27 |
|
28 | function renderEntityHashtag(data) {
|
29 | return `[#${escapeMarkdownPart(data.text)}](https://twitter.com/search?q=%23${data.text})`;
|
30 | }
|
31 |
|
32 | function renderEntityUrl(data) {
|
33 | return `[${escapeMarkdownPart(data.display_url)}](${data.url} "${data.expanded_url}")`;
|
34 | }
|
35 |
|
36 | function renderEntity(type, data) {
|
37 | switch (type) {
|
38 | case 'user_mentions':
|
39 | return renderEntityMention(data);
|
40 | case 'media':
|
41 | return renderEntityMedia(data);
|
42 | case 'hashtags':
|
43 | return renderEntityHashtag(data);
|
44 | case 'urls':
|
45 | return renderEntityUrl(data);
|
46 | default:
|
47 | return null;
|
48 | }
|
49 | }
|
50 |
|
51 | export default function render(tweet) {
|
52 | const { text, entities = { } } = tweet;
|
53 | const replacements = [];
|
54 |
|
55 | Object.keys(entities).forEach(entityKey => {
|
56 | replacements.push(
|
57 | ...entities[entityKey].map(entity => [
|
58 | renderEntity(entityKey, entity),
|
59 | entity.indices[0],
|
60 | entity.indices[1]
|
61 | ])
|
62 | );
|
63 | });
|
64 |
|
65 | if (0 === replacements.length) {
|
66 | return escapeMarkdown(tweet.text);
|
67 | }
|
68 |
|
69 | let lastPos = text.length;
|
70 | const parts = replacements.sort((a, b) => b[1] - a[1]).map(replacement => {
|
71 | let output = [replacement[0]];
|
72 |
|
73 | if (replacement[2] < lastPos) {
|
74 | output.push(
|
75 | escapeMarkdownPart(
|
76 | text.substr(
|
77 | replacement[2],
|
78 | lastPos - replacement[2]
|
79 | )
|
80 | )
|
81 | );
|
82 | }
|
83 |
|
84 | lastPos = replacement[1];
|
85 |
|
86 | return output.join('');
|
87 | });
|
88 |
|
89 | if (lastPos > 0) {
|
90 | parts.push(
|
91 | escapeMarkdown(
|
92 | text.substr(0, lastPos)
|
93 | )
|
94 | );
|
95 | }
|
96 |
|
97 | return parts.reverse().join('');
|
98 | }
|