Skip to content

Commit 15e10a8

Browse files
committed
v2.10.0
2 parents b731f07 + ac0e1ff commit 15e10a8

File tree

18 files changed

+1347
-3
lines changed

18 files changed

+1347
-3
lines changed

app/server.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ var qr = require('qr-image');
2020
var machineId = require('node-machine-id').machineId;
2121

2222
const store = require('./store');
23+
store.mods.editor && (store.mods.editor.root = () => git.root())
2324

2425
var server = http.Server(app);
2526
var visitor = ua('UA-99239389-1');
@@ -224,6 +225,8 @@ app.post('/set/:file/:name/:prop/:value', function (req, res) {
224225

225226
app.use('/', require('./services'));
226227

228+
require('./services/ot').init(server, '/ws');
229+
227230
var serve = (http, port) =>
228231
new Promise((resolve, reject) => {
229232
http.on('error', reject);

app/services/editor.js

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
const router = module.exports = require('express').Router();
2+
const git = require('../git-tool');
3+
const store = require('../store').mods.editor;
4+
const path = require('path');
5+
const promisify = require('../helpers').promisify;
6+
const fs = require('fs');
7+
const formidable = require('formidable');
8+
9+
const safePath = val => decodeURI(val).replace(/|\.\.|\/\//g, '');
10+
const getRoot = req => Promise.resolve(store.root(req))
11+
12+
//create
13+
router.post('/file/*', (req, res) => {
14+
const f = req.query.type == 'file';
15+
const p = safePath(req.url.slice(5));
16+
return getRoot(req)
17+
.then(root => promisify(f && fs.writeFile || fs.mkdir)(path.join(root, p), f ? '' : 0o777)) //TODO: check if exists
18+
.then(a => ({id: p}))
19+
.catch(e => res.status(501).send(e.message))
20+
.then(data => res.send(data))
21+
})
22+
23+
//remove
24+
router.delete('/file/*', (req, res) => {
25+
const p = safePath(req.url.slice(5));
26+
return getRoot(req)
27+
.then(root => promisify(fs.stat)(path.join(root, p)).then(stats => promisify(stats.isDirectory() ? fs.rmdir : fs.unlink)(path.join(root, p)) ))
28+
.then(a => ({id: p}))
29+
.catch(e => res.status(501).send(e.message))
30+
.then(data => res.send(data))
31+
})
32+
33+
//move //TODO check if destenation not exists ?
34+
router.put('/file/*', (req, res) => {
35+
const p = safePath(req.url.slice(5));
36+
const t = safePath(req.body.to);
37+
return getRoot(req)
38+
.then(root => promisify(fs.rename)(path.join(root, p), path.join(root, t)))
39+
.then(a => ({id: t}))
40+
.catch(e => res.status(501).send(e.message))
41+
.then(data => res.send(data))
42+
})
43+
44+
//TODO:copy
45+
46+
//list
47+
router.get('/tree', function(req, res) {
48+
var dir = req.query.id == '#' && '/' || req.query.id || '';
49+
dir = dir.replace(/\.\./g, '');
50+
return getRoot(req)
51+
.then(root => promisify(fs.readdir)(path.join(root, dir))
52+
.then(list => list.filter(name => name && (name != '.' || name != '..')))
53+
.then(list => Promise.all(list.map(name => promisify(fs.stat)(path.join(root, dir, name))
54+
.then(stats => ({
55+
children: stats.isDirectory(),
56+
type: stats.isDirectory() ? 'default' : "file",
57+
text: name,
58+
id: path.join(dir, name),
59+
// icon: stats.isDirectory() ? 'jstree-folder' : "jstree-file",
60+
}))))
61+
)
62+
)
63+
.then(list => dir != '/' && list || {text: store.name(req), children: list, id: '/', type: 'default', state: {opened: true, disabled: true}})
64+
.catch(e => res.status(501).send(e.message))
65+
.then(data => res.send(data))
66+
})
67+
68+
//content
69+
router.get('/file/*', function(req, res) {
70+
const p = safePath(req.url.slice(5));
71+
return getRoot(req)
72+
.then(root => promisify(fs.stat)(path.join(root, p)).then(stats => !stats.isDirectory() && promisify(fs.readFile)(path.join(root, p)) || '' ))
73+
.catch(e => res.status(501).send(e.message))
74+
.then(data => res.send(data))
75+
})
76+
77+
const parseForm = req => new Promise((resolve, reject) => {
78+
var form = new formidable.IncomingForm();
79+
form.parse(req, function (err, fields, files) {
80+
return err && reject(err) || resolve([fields, files]);
81+
})
82+
})
83+
84+
router.post('/upload/*', function(req, res) {
85+
const p = safePath(req.url.slice(7));
86+
return getRoot(req)
87+
.then(root => parseForm(req).then(ff => promisify(fs.rename)(ff[1].data.path, path.join(root, p)).then(a => p) ))
88+
.catch(e => res.status(501).send(e.message))
89+
.then(data => res.send(data))
90+
});
91+
92+
93+
//git file TODO: git for multiproject
94+
router.get('/git/*', function(req, res) {
95+
git.Tag()
96+
.then(tag => git.Show(tag, req.originalUrl.replace(/.*git\//, '')))
97+
.catch(e => res.status(501).send(e.message))
98+
.then(data => res.send(data))
99+
})

app/services/index.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
const router = module.exports = require('express').Router();
22
const store = require('../store');
33

4-
//router.use('/s/editor', require('./editor'));
54
router.use('/', require('./sse'));
5+
if (store.mods.editor)
6+
router.use('/s/editor', require('./editor'));
67
if (store.mods.upnp)
78
router.use('/upnp', require('./upnp'));
89
if (store.mods.serial)

app/services/ot.js

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
const fs = require('fs');
2+
const path = require('path');
3+
const sio = require('socket.io');
4+
const ot = require('ot');
5+
const store = require('../store').mods.editor;
6+
const promisify = require('../helpers').promisify;
7+
8+
var ns = {};
9+
const getFile = file => store.root().then(root => promisify(fs.readFile)(path.join(root, file)))
10+
const setFile = (file, data) => store.root().then(root => promisify(fs.writeFile)(path.join(root, file), data))
11+
12+
exports.init = (server, url) => {
13+
const io = new sio(server, {path: url});
14+
io.on('connection', function(socket) {
15+
socket.on('ns', function (docId) {
16+
if (ns[docId])
17+
socket.emit('ns', docId);
18+
else {
19+
getFile(docId)
20+
.then(text => {
21+
var doc = ns[docId] = new ot.EditorSocketIOServer(text.toString(), 0, docId)
22+
socket.emit('ns', docId);
23+
io.of(docId)
24+
.on('connection', function(socket) {
25+
function clients(mode) {
26+
socket.broadcast.in(docId).emit('clients', {clients: doc.users, mode: mode});
27+
}
28+
doc.getClient(socket.id);
29+
doc.addClient(socket);
30+
clients('enter');
31+
socket.in(docId)
32+
.on('disconnect', function() {
33+
console.log('disconnect');
34+
delete doc.users[socket.id];
35+
clients('leave');
36+
})
37+
.on('name', function (name) {
38+
doc.setName(socket, name);
39+
console.log('set name')
40+
clients('name');
41+
})
42+
.on('operation', function (name) {
43+
console.log('saving...');
44+
setFile(docId, doc.document);
45+
});
46+
})
47+
})
48+
}
49+
});
50+
});
51+
}

app/store.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ exports.config = {
1010

1111
exports.mods = {
1212
sse: {},
13+
editor: {
14+
root(req) {}, //replace it!
15+
name(req) { return 'marlin-conf' },
16+
},
1317
serial: {}, // comment for disabling
1418
upnp: {}, // comment for disabling
1519
};

package.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,12 @@
5656
},
5757
"homepage": "https://github.com/akaJes/marlin-config#readme",
5858
"dependencies": {
59+
"ace-builds": "^1.3.3",
5960
"body-parser": "^1.17.2",
6061
"bootstrap": "4.0.0-alpha.6",
6162
"cropper": "^3.1.5",
6263
"data-store": "^1.0.0",
64+
"diff-match-patch": "^1.0.0",
6365
"express": "^4.16.2",
6466
"fix-path": "^2.1.0",
6567
"font-awesome": "^4.7.0",
@@ -70,13 +72,15 @@
7072
"jquery": "^3.3.1",
7173
"jquery-ui-dist": "^1.12.1",
7274
"js-yaml": "^3.8.4",
75+
"jstree": "^3.3.5",
7376
"marked": "^0.3.16",
7477
"mkdirp": "^0.5.1",
7578
"moment": "^2.20.1",
7679
"nat-upnp": "^1.1.1",
7780
"node-machine-id": "^1.1.10",
7881
"node-notifier": "^5.2.1",
7982
"opn": "^5.2.0",
83+
"ot": "git+https://github.com/Operational-Transformation/ot.js.git",
8084
"platformio-node-helpers": "^0.4.3",
8185
"qr-image": "^3.2.0",
8286
"rtcmulticonnection-v3": "^3.4.4",
@@ -92,7 +96,7 @@
9296
"yauzl": "^2.9.1",
9397
"yazl": "^2.4.3"
9498
},
95-
"devDependenciesOff": {
99+
"devDependencies": {
96100
"devtron": "^1.4.0",
97101
"electron": "=1.7.10",
98102
"electron-builder": "^20.2.0",

0 commit comments

Comments
 (0)