1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const fs_1 = require("fs");
|
4 | const async_1 = require("async");
|
5 | const build_1 = require("./build");
|
6 | const nconf = require.main.require('nconf');
|
7 | const url = nconf.get('url');
|
8 | let metaCache = null;
|
9 | function clearCache() {
|
10 | metaCache = null;
|
11 | }
|
12 | exports.clearCache = clearCache;
|
13 | const escapeRegExpChars = (text) => text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
14 | const getTable = (callback) => {
|
15 | if (metaCache) {
|
16 | callback(null, metaCache);
|
17 | return;
|
18 | }
|
19 | async_1.parallel({
|
20 | table: next => fs_1.readFile(build_1.tableFile, next),
|
21 | aliases: next => fs_1.readFile(build_1.aliasesFile, next),
|
22 | ascii: next => fs_1.readFile(build_1.asciiFile, next),
|
23 | characters: next => fs_1.readFile(build_1.charactersFile, next),
|
24 | }, (err, results) => {
|
25 | if (err) {
|
26 | callback(err);
|
27 | return;
|
28 | }
|
29 | try {
|
30 | const ascii = JSON.parse(results.ascii.toString());
|
31 | const asciiPattern = Object.keys(ascii)
|
32 | .sort((a, b) => b.length - a.length)
|
33 | .map(escapeRegExpChars)
|
34 | .join('|');
|
35 | const characters = JSON.parse(results.characters.toString());
|
36 | const charPattern = Object.keys(characters)
|
37 | .sort((a, b) => b.length - a.length)
|
38 | .map(escapeRegExpChars)
|
39 | .join('|');
|
40 | metaCache = {
|
41 | ascii,
|
42 | characters,
|
43 | table: JSON.parse(results.table.toString()),
|
44 | aliases: JSON.parse(results.aliases.toString()),
|
45 | asciiPattern: new RegExp(`(?:^|\\s)(${asciiPattern})(?=\\s|$)`, 'g'),
|
46 | charPattern: new RegExp(charPattern, 'g'),
|
47 | };
|
48 | }
|
49 | catch (e) {
|
50 | callback(e);
|
51 | return;
|
52 | }
|
53 | callback(null, metaCache);
|
54 | });
|
55 | };
|
56 | const outsideCode = /(^|<\/code>)([^<]*|<(?!code[^>]*>))*(<code[^>]*>|$)/g;
|
57 | const emojiPattern = /:([a-z\-.+0-9_]+):/g;
|
58 | const buildEmoji = (emoji, whole) => {
|
59 | if (emoji.image) {
|
60 | const route = `${url}/plugins/nodebb-plugin-emoji/emoji/${emoji.pack}`;
|
61 | return `<img
|
62 | src="${route}/${emoji.image}"
|
63 | class="not-responsive emoji emoji-${emoji.pack} emoji--${emoji.name}"
|
64 | title="${whole}"
|
65 | alt="${emoji.character}"
|
66 | />`;
|
67 | }
|
68 | return `<span
|
69 | class="emoji emoji-${emoji.pack} emoji--${emoji.name}"
|
70 | title="${whole}"
|
71 | ><span>${emoji.character}</span></span>`;
|
72 | };
|
73 | const replaceAscii = (str, { ascii, asciiPattern, table }) => {
|
74 | return str.replace(asciiPattern, (full, text) => {
|
75 | const emoji = ascii[text] && table[ascii[text]];
|
76 | if (emoji) {
|
77 | return full.replace(text, buildEmoji(emoji, text));
|
78 | }
|
79 | return text;
|
80 | });
|
81 | };
|
82 | const replaceNative = (str, { characters, charPattern }) => {
|
83 | return str.replace(charPattern, (char) => `:${characters[char]}:`);
|
84 | };
|
85 | const options = {
|
86 | ascii: false,
|
87 | native: false,
|
88 | };
|
89 | function setOptions(newOptions) {
|
90 | Object.assign(options, newOptions);
|
91 | }
|
92 | exports.setOptions = setOptions;
|
93 | const parse = (content, callback) => {
|
94 | getTable((err, store) => {
|
95 | if (err) {
|
96 | callback(err);
|
97 | return;
|
98 | }
|
99 | const { table, aliases } = store;
|
100 | const parsed = content.replace(outsideCode, (str) => {
|
101 | let output = str;
|
102 | if (options.native) {
|
103 |
|
104 |
|
105 | output = output.replace(/(<[^>]+>)|([^0-9a-zA-Z`~!@#$%^&*()\-=_+{}|[\]\\:";'<>?,./\s\n]+)/g, (full, tag, text) => {
|
106 | if (text) {
|
107 | return replaceNative(text, store);
|
108 | }
|
109 | return full;
|
110 | });
|
111 | }
|
112 | output = output.replace(emojiPattern, (whole, text) => {
|
113 | const name = text.toLowerCase();
|
114 | const emoji = table[name] || table[aliases[name]];
|
115 | if (emoji) {
|
116 | return buildEmoji(emoji, whole);
|
117 | }
|
118 | return whole;
|
119 | });
|
120 | if (options.ascii) {
|
121 |
|
122 | output = output.replace(/(<[^>]+>)|([^<]+)/g, (full, tag, text) => {
|
123 | if (text) {
|
124 | return replaceAscii(text, store);
|
125 | }
|
126 | return full;
|
127 | });
|
128 | }
|
129 | return output;
|
130 | });
|
131 | callback(null, parsed);
|
132 | });
|
133 | };
|
134 | function raw(content, callback) {
|
135 | parse(content, callback);
|
136 | }
|
137 | exports.raw = raw;
|
138 | function post(data, callback) {
|
139 | parse(data.postData.content, (err, content) => {
|
140 | if (err) {
|
141 | callback(err);
|
142 | return;
|
143 | }
|
144 | data.postData.content = content;
|
145 | callback(null, data);
|
146 | });
|
147 | }
|
148 | exports.post = post;
|
149 |
|
\ | No newline at end of file |