UNPKG

4.78 kBJavaScriptView Raw
1'use strict';
2
3const SocketPlugins = require.main.require('./src/socket.io/plugins');
4const SocketAdmin = require.main.require('./src/socket.io/admin').plugins;
5SocketAdmin['composer-quill'] = require('./lib/adminsockets.js');
6const defaultComposer = require.main.require('nodebb-plugin-composer-default');
7const plugins = module.parent.exports;
8const meta = require.main.require('./src/meta');
9const posts = require.main.require('./src/posts');
10const messaging = require.main.require('./src/messaging');
11const helpers = require.main.require('./src/controllers/helpers');
12
13const async = require('async');
14const winston = require.main.require('winston');
15const nconf = require.main.require('nconf');
16
17const controllers = require('./lib/controllers');
18const migrator = require('./lib/migrator');
19
20const plugin = {};
21
22plugin.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 // Expose the default composer's socket method calls for this composer as well
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
46plugin.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, // plugin disabled
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
60plugin.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
70plugin.build = function (data, callback) {
71 // No plans for a standalone composer route, so handle redirection on f5
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
91plugin.savePost = async (data, path = 'post') => {
92 if (typeof path === 'function') {
93 path = 'post';
94 }
95
96 if (migrator.isDelta(data[path].content)) {
97 // Optimistic case: regular post via quill composer
98 data[path].quillDelta = data[path].content;
99 data[path].content = migrator.toHtml(data[path].content);
100 } else {
101 // Fallback to handle write-api and such
102 data[path] = migrator.toQuill(data[path]);
103 }
104
105 return data;
106};
107
108plugin.savePostQueue = async (data) => {
109 data = await plugin.savePost(data, 'data');
110 return data;
111};
112
113plugin.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
123plugin.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
131plugin.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
139plugin.handleMessageEdit = async (data) => {
140 // Only handle situations where message content is requested
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
150plugin.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
169module.exports = plugin;