1 | 'use strict';
|
2 |
|
3 | const SocketPlugins = require.main.require('./src/socket.io/plugins');
|
4 | const SocketAdmin = require.main.require('./src/socket.io/admin').plugins;
|
5 | SocketAdmin['composer-quill'] = require('./lib/adminsockets.js');
|
6 | const defaultComposer = require.main.require('nodebb-plugin-composer-default');
|
7 | const plugins = module.parent.exports;
|
8 | const meta = require.main.require('./src/meta');
|
9 | const posts = require.main.require('./src/posts');
|
10 | const messaging = require.main.require('./src/messaging');
|
11 | const helpers = require.main.require('./src/controllers/helpers');
|
12 |
|
13 | const async = require('async');
|
14 | const winston = require.main.require('winston');
|
15 | const nconf = require.main.require('nconf');
|
16 |
|
17 | const controllers = require('./lib/controllers');
|
18 | const migrator = require('./lib/migrator');
|
19 |
|
20 | const plugin = {};
|
21 |
|
22 | plugin.init = function (data, callback) {
|
23 | const router = data.router;
|
24 | const hostMiddleware = data.middleware;
|
25 |
|
26 | router.get('/admin/plugins/composer-quill', hostMiddleware.admin.buildHeader, controllers.renderAdminPage);
|
27 | router.get('/api/admin/plugins/composer-quill', controllers.renderAdminPage);
|
28 |
|
29 |
|
30 | plugin.checkCompatibility(function (err, checks) {
|
31 | if (err) {
|
32 | return winston.error('[plugin/composer-quill] Error initialising plugin: ' + err.message);
|
33 | }
|
34 |
|
35 | if (checks.composer) {
|
36 | SocketPlugins.composer = defaultComposer.socketMethods;
|
37 | SocketPlugins['composer-quill'] = require('./lib/websockets');
|
38 | } else {
|
39 | winston.warn('[plugin/composer-quill] Another composer plugin is active! Please disable all other composers.');
|
40 | }
|
41 | });
|
42 |
|
43 | callback();
|
44 | };
|
45 |
|
46 | plugin.checkCompatibility = function (callback) {
|
47 | async.parallel({
|
48 | active: async.apply(plugins.getActive),
|
49 | markdown: async.apply(meta.settings.get, 'markdown'),
|
50 | }, function (err, data) {
|
51 | callback(err, {
|
52 | markdown: data.active.indexOf('nodebb-plugin-markdown') === -1,
|
53 | composer: data.active.filter(function (plugin) {
|
54 | return plugin.startsWith('nodebb-plugin-composer-') && plugin !== 'nodebb-plugin-composer-quill';
|
55 | }).length === 0,
|
56 | });
|
57 | });
|
58 | };
|
59 |
|
60 | plugin.addAdminNavigation = function (header, callback) {
|
61 | header.plugins.push({
|
62 | route: '/plugins/composer-quill',
|
63 | icon: 'fa-edit',
|
64 | name: 'Quill (Composer)',
|
65 | });
|
66 |
|
67 | callback(null, header);
|
68 | };
|
69 |
|
70 | plugin.build = function (data, callback) {
|
71 |
|
72 | var req = data.req;
|
73 | var res = data.res;
|
74 |
|
75 | if (req.query.p) {
|
76 | if (!res.locals.isAPI) {
|
77 | if (req.query.p.startsWith(nconf.get('relative_path'))) {
|
78 | req.query.p = req.query.p.replace(nconf.get('relative_path'), '');
|
79 | }
|
80 |
|
81 | return helpers.redirect(res, req.query.p);
|
82 | }
|
83 | return res.render('', {});
|
84 | } else if (!req.query.pid && !req.query.tid && !req.query.cid) {
|
85 | return helpers.redirect(res, '/');
|
86 | }
|
87 |
|
88 | callback(null, data);
|
89 | };
|
90 |
|
91 | plugin.savePost = async (data, path = 'post') => {
|
92 | if (typeof path === 'function') {
|
93 | path = 'post';
|
94 | }
|
95 |
|
96 | if (migrator.isDelta(data[path].content)) {
|
97 |
|
98 | data[path].quillDelta = data[path].content;
|
99 | data[path].content = migrator.toHtml(data[path].content);
|
100 | } else {
|
101 |
|
102 | data[path] = migrator.toQuill(data[path]);
|
103 | }
|
104 |
|
105 | return data;
|
106 | };
|
107 |
|
108 | plugin.savePostQueue = async (data) => {
|
109 | data = await plugin.savePost(data, 'data');
|
110 | return data;
|
111 | };
|
112 |
|
113 | plugin.saveChat = (data, callback) => {
|
114 | if (data.system) {
|
115 | return setImmediate(callback, null, data);
|
116 | }
|
117 |
|
118 | data.quillDelta = data.content;
|
119 | data.content = migrator.toHtml(data.content);
|
120 | callback(null, data);
|
121 | };
|
122 |
|
123 | plugin.append = async (data) => {
|
124 | const delta = await posts.getPostField(data.pid, 'quillDelta');
|
125 | if (delta) {
|
126 | data.body = delta;
|
127 | }
|
128 | return data;
|
129 | };
|
130 |
|
131 | plugin.handleRawPost = async (data) => {
|
132 | const delta = await posts.getPostField(data.postData.pid, 'quillDelta');
|
133 | if (delta) {
|
134 | data.postData.content = delta;
|
135 | }
|
136 | return data;
|
137 | };
|
138 |
|
139 | plugin.handleMessageEdit = async (data) => {
|
140 |
|
141 | if (data.fields.length > 1 || data.fields[0] !== 'content') {
|
142 | return data;
|
143 | }
|
144 |
|
145 | const delta = await messaging.getMessageField(data.mid, 'quillDelta');
|
146 | data.message.content = delta;
|
147 | return data;
|
148 | };
|
149 |
|
150 | plugin.handleMessageCheck = async ({ content, length }) => {
|
151 | try {
|
152 | const delta = JSON.parse(content);
|
153 | if (!delta.ops) {
|
154 | throw new Error();
|
155 | }
|
156 |
|
157 | content = delta.ops.reduce((memo, cur) => {
|
158 | memo += cur.insert ? cur.insert : '';
|
159 | return memo;
|
160 | }, '');
|
161 | length = String(content).trim().length;
|
162 | } catch (e) {
|
163 | winston.warn('[plugins/quill/handleMessageCheck] Did not receive a delta, ignoring...');
|
164 | }
|
165 |
|
166 | return { content, length };
|
167 | };
|
168 |
|
169 | module.exports = plugin;
|