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