UNPKG

ethercalc

Version:

Multi-User Spreadsheet Server

811 lines (810 loc) 29.3 kB
// Generated by LiveScript 1.6.0 (function(){ var vm, fs, path, FindBin, bootSC, argv, IsThreaded, Worker, e, replace$ = ''.replace; vm = require('vm'); fs = require('fs'); path = require('path'); FindBin = path.dirname(fs.realpathSync(__filename)); if (fs.existsSync(FindBin + "/node_modules/socialcalc/dist/SocialCalc.js", 'utf8')) { bootSC = fs.readFileSync(FindBin + "/node_modules/socialcalc/dist/SocialCalc.js", 'utf8'); } else { bootSC = fs.readFileSync(FindBin + "/node_modules/socialcalc/SocialCalc.js", 'utf8'); } bootSC = bootSC.replace(/document\.createElement\(/g, 'SocialCalc.document.createElement('); bootSC = bootSC.replace(/alert\(/g, '(function(){})('); global.SC == null && (global.SC = { console: console }); argv = (function(){ try { return require('optimist').boolean(['vm', 'polling']).argv; } catch (e$) {} }()) || {}; bootSC += ";var navigator = {language: '', userAgent: ''}; var SocialCalc = this.SocialCalc; var window = this;(" + function(){ var Node; Node = (function(){ Node.displayName = 'Node'; var prototype = Node.prototype, constructor = Node; function Node(tag, attrs, style, elems, raw){ this.tag = tag != null ? tag : "div"; this.attrs = attrs != null ? attrs : {}; this.style = style != null ? style : {}; this.elems = elems != null ? elems : []; this.raw = raw != null ? raw : ''; } Object.defineProperty(Node.prototype, 'id', { set: function(id){ this.attrs.id = id; }, configurable: true, enumerable: true }); Object.defineProperty(Node.prototype, 'width', { set: function(width){ this.attrs.width = width; }, configurable: true, enumerable: true }); Object.defineProperty(Node.prototype, 'height', { set: function(height){ this.attrs.height = height; }, configurable: true, enumerable: true }); Object.defineProperty(Node.prototype, 'className', { set: function($class){ this.attrs['class'] = $class; }, configurable: true, enumerable: true }); Object.defineProperty(Node.prototype, 'colSpan', { set: function(colspan){ this.attrs.colspan = colspan; }, configurable: true, enumerable: true }); Object.defineProperty(Node.prototype, 'rowSpan', { set: function(rowspan){ this.attrs.rowspan = rowspan; }, configurable: true, enumerable: true }); Object.defineProperty(Node.prototype, 'title', { set: function(title){ this.attrs.title = title; }, configurable: true, enumerable: true }); Object.defineProperty(Node.prototype, 'innerHTML', { set: function(raw){ this.raw = raw; }, get: function(){ var e; return this.raw || (function(){ var i$, ref$, len$, results$ = []; for (i$ = 0, len$ = (ref$ = this.elems).length; i$ < len$; ++i$) { e = ref$[i$]; results$.push(e.outerHTML); } return results$; }.call(this)).join("\n"); }, configurable: true, enumerable: true }); Object.defineProperty(Node.prototype, 'outerHTML', { get: function(){ var tag, attrs, style, css, k, v; tag = this.tag, attrs = this.attrs, style = this.style; css = style.cssText || (function(){ var ref$, results$ = []; for (k in ref$ = style) { v = ref$[k]; results$.push(k.replace(/[A-Z]/g, '-$&').toLowerCase() + ":" + v); } return results$; }()).join(";"); if (css) { attrs.style = css; } else { delete attrs.style; } return "<" + tag + (function(){ var ref$, results$ = []; for (k in ref$ = attrs) { v = ref$[k]; results$.push(" " + k + "=\"" + v + "\""); } return results$; }()).join('') + ">" + this.innerHTML + "</" + tag + ">"; }, configurable: true, enumerable: true }); Node.prototype.appendChild = function(it){ return this.elems.push(it); }; return Node; }()); SocialCalc.document == null && (SocialCalc.document = {}); return SocialCalc.document.createElement = function(it){ return new Node(it); }; } + ")();"; IsThreaded = true; Worker = (function(){ try { if (argv.vm) { throw 'vm'; } console.log("Starting backend using webworker-threads"); return require('webworker-threads').Worker; } catch (e$) { e = e$; console.log("Falling back to vm.CreateContext backend"); return IsThreaded = false; } }()); Worker || (Worker = (function(){ Worker.displayName = 'Worker'; var prototype = Worker.prototype, constructor = Worker; function Worker(code){ var cxt, sandbox, this$ = this; cxt = { console: console, self: { onmessage: function(){} }, alert: function(){} }; cxt.window = { setTimeout: function(cb, ms){ return process.nextTick(cb); }, alert: function(){}, clearTimeout: function(){} }; this.postMessage = function(data){ return sandbox.self.onmessage({ data: data }); }; this.thread = cxt.thread = { nextTick: function(cb){ return process.nextTick(cb); }, eval: function(src, cb){ var rv, e; try { rv = vm.runInContext(src, sandbox); return typeof cb == 'function' ? cb(null, rv) : void 8; } catch (e$) { e = e$; console.log("e " + e); return typeof cb == 'function' ? cb(e) : void 8; } } }; this.terminate = function(){}; this.sandbox = sandbox = vm.createContext(cxt); sandbox.postMessage = function(data){ return typeof this$.onmessage == 'function' ? this$.onmessage({ data: data }) : void 8; }; if (code) { vm.runInContext("(" + code + ")()", sandbox); } return this; } return Worker; }())); this.include = function(){ var DB, EXPIRE, emailer, dataDir; DB = this.include('db'); EXPIRE = this.EXPIRE; emailer = this.include('emailer'); dataDir = process.env.OPENSHIFT_DATA_DIR; SC._csvToSave = function(csv, cb){ var w; w = new Worker; return w.thread.eval(bootSC, function(){ return w.thread.eval("SocialCalc.ConvertOtherFormatToSave(" + JSON.stringify(csv) + ", 'csv')", function(arg$, rv){ return cb(rv); }); }); }; SC._get = function(room, io, cb){ var ref$; if ((ref$ = SC[room]) != null && ref$._snapshot) { return cb({ snapshot: SC[room]._snapshot }); } return DB.multi().get("snapshot-" + room).lrange("log-" + room, 0, -1).exec(function(arg$, arg1$){ var snapshot, log; snapshot = arg1$[0], log = arg1$[1]; if (EXPIRE) { DB.expire("snapshot-" + room, EXPIRE); } if ((snapshot || log.length) && io) { SC[room] = SC._init(snapshot, log, DB, room, io); } return cb({ log: log, snapshot: snapshot }); }); }; SC._put = function(room, snapshot, cb){ if (!snapshot) { return typeof cb == 'function' ? cb() : void 8; } return DB.multi().set("snapshot-" + room, snapshot).del(["log-" + room, "chat-" + room, "ecell-" + room, "audit-" + room]).bgsave().exec(function(){ if (EXPIRE) { DB.expire("snapshot-" + room, EXPIRE); } return typeof cb == 'function' ? cb() : void 8; }); }; SC._del = function(room, cb){ return DB.multi().del(["snapshot-" + room, "log-" + room, "chat-" + room, "ecell-" + room, "audit-" + room]).bgsave().exec(function(){ return typeof cb == 'function' ? cb() : void 8; }); }; SC._rooms = function(cb){ return DB.multi().keys('snapshot-*').exec(function(arg$, arg1$){ var rooms; rooms = arg1$[0]; return cb((function(){ var i$, x$, ref$, len$, results$ = []; for (i$ = 0, len$ = (ref$ = rooms).length; i$ < len$; ++i$) { x$ = ref$[i$]; results$.push(x$.replace(/^snapshot-/, "")); } return results$; }())); }); }; SC._roomtimes = function(cb){ return DB.hgetall("timestamps", function(_, res){ return cb(res); }); }; SC._exists = function(room, cb){ return DB.multi().exists("snapshot-" + room).exec(function(arg$, arg1$){ var x; x = arg1$[0]; return cb(x); }); }; SC._init = function(snapshot, log, DB, room, io){ var w; log == null && (log = []); if (SC[room] != null) { SC[room]._doClearCache(); return SC[room]; } w = new Worker(function(){ return self.onmessage = function(arg$){ var ref$, type, ref, snapshot, command, room, log, ref1$, commandParameters, csv, alert, ss, parts, cmdstr, line; ref$ = arg$.data, type = ref$.type, ref = ref$.ref, snapshot = ref$.snapshot, command = ref$.command, room = ref$.room, log = (ref1$ = ref$.log) != null ? ref1$ : []; switch (type) { case 'cmd': commandParameters = command.split(" "); if (commandParameters[0] === 'settimetrigger') { postMessage({ type: 'setcrontrigger', timetriggerdata: { cell: commandParameters[1], times: commandParameters[2] } }); } if (commandParameters[0] === 'sendemail') { postMessage({ type: 'sendemailout', emaildata: { to: commandParameters[1].replace(/%20/g, ' '), subject: commandParameters[2].replace(/%20/g, ' '), body: commandParameters[3].replace(/%20/g, ' ') } }); } return window.ss.ExecuteCommand(command); case 'recalc': return SocialCalc.RecalcLoadedSheet(ref, snapshot, true); case 'clearCache': return SocialCalc.Formula.SheetCache.sheets = {}; case 'exportSave': return postMessage({ type: 'save', save: window.ss.CreateSheetSave() }); case 'exportHTML': return postMessage({ type: 'html', html: window.ss.CreateSheetHTML() }); case 'exportCSV': csv = window.ss.SocialCalc.ConvertSaveToOtherFormat(window.ss.CreateSheetSave(), 'csv'); return postMessage({ type: 'csv', csv: csv }); case 'exportCells': return postMessage({ type: 'cells', cells: window.ss.cells }); case 'init': SocialCalc.CreateAuditString = function(){ return ""; }; SocialCalc.CalculateEditorPositions = function(){}; SocialCalc.Popup.Types.List.Create = function(){}; SocialCalc.Popup.Types.ColorChooser.Create = function(){}; SocialCalc.Popup.Initialize = function(){}; SocialCalc.RecalcInfo.LoadSheet = function(ref){ if (/[^.=_a-zA-Z0-9]/.exec(ref)) { return; } ref = ref.toLowerCase(); postMessage({ type: 'load-sheet', ref: ref }); return true; }; window.setTimeout = function(cb, ms){ return thread.nextTick(cb); }; window.clearTimeout = function(){}; window.alert = alert = function(){}; window.ss = ss = new SocialCalc.SpreadsheetControl; ss.SocialCalc = SocialCalc; ss._room = room; if (snapshot) { parts = ss.DecodeSpreadsheetSave(snapshot); } ss.editor.StatusCallback.EtherCalc = { func: function(editor, status, arg){ var newSnapshot; if (status !== 'doneposcalc') { return; } newSnapshot = ss.CreateSpreadsheetSave(); if (ss._snapshot === newSnapshot) { return; } ss._snapshot = newSnapshot; return postMessage({ type: 'snapshot', snapshot: newSnapshot }); } }; if (parts != null) { if (parts.sheet) { ss.sheet.ResetSheet(); ss.ParseSheetSave(snapshot.substring(parts.sheet.start, parts.sheet.end)); } if (parts.edit) { ss.editor.LoadEditorSettings(snapshot.substring(parts.edit.start, parts.edit.end)); } } cmdstr = (function(){ var i$, ref$, len$, results$ = []; for (i$ = 0, len$ = (ref$ = log).length; i$ < len$; ++i$) { line = ref$[i$]; if (!/^re(calc|display)$/.test(line)) { results$.push(line); } } return results$; }()).join("\n"); if (cmdstr.length) { cmdstr += "\n"; } return ss.context.sheetobj.ScheduleSheetCommands("set sheet defaulttextvalueformat text-wiki\n" + cmdstr + "recalc\n", false, true); } }; }); w._snapshot = snapshot; w.onSnapshot = function(newSnapshot){ io.sockets['in']("recalc." + room).emit('data', { type: 'recalc', snapshot: newSnapshot, force: true, room: room }); w._snapshot = newSnapshot; return DB.multi().set("snapshot-" + room, newSnapshot).hset('timestamps', "timestamp-" + room, Date.now()).del("log-" + room).bgsave().exec(function(){ if (EXPIRE) { return DB.expire("snapshot-" + room, EXPIRE); } }); }; w.onerror = function(it){ return console.log(it); }; w.onmessage = function(arg$){ var ref$, type, snapshot, html, csv, ref, parts, save, emaildata, timetriggerdata; ref$ = arg$.data, type = ref$.type, snapshot = ref$.snapshot, html = ref$.html, csv = ref$.csv, ref = ref$.ref, parts = ref$.parts, save = ref$.save, emaildata = ref$.emaildata, timetriggerdata = ref$.timetriggerdata; switch (type) { case 'snapshot': return w.onSnapshot(snapshot); case 'save': return w.onSave(save); case 'html': return w.onHtml(html); case 'csv': return w.onCsv(csv); case 'setcrontrigger': console.log("set cron " + room); return DB.get("cron-nextTriggerTime", function(arg$, nextTriggerTime){ var scheduledNextTriggerTime, timeNowMins, triggerTimeList, res$, i$, ref$, len$, nextTime; scheduledNextTriggerTime = nextTriggerTime; timeNowMins = Math.floor(new Date().getTime() / (1000 * 60)); console.log("timeNowMins " + timeNowMins + " .dataDir " + dataDir); nextTriggerTime == null && (nextTriggerTime = 2147483647); res$ = []; for (i$ = 0, len$ = (ref$ = timetriggerdata.times.split(",")).length; i$ < len$; ++i$) { nextTime = ref$[i$]; if (nextTime >= timeNowMins) { if (nextTriggerTime > nextTime) { nextTriggerTime = nextTime; } res$.push(nextTime); } } triggerTimeList = res$; if (scheduledNextTriggerTime !== nextTriggerTime) { fs.writeFileSync(dataDir + "/nextTriggerTime.txt", nextTriggerTime, 'utf8'); } if (triggerTimeList.length === 0) { return DB.hdel("cron-list", room + "!" + timetriggerdata.cell, function(){}); } else { return DB.multi().hset("cron-list", room + "!" + timetriggerdata.cell, triggerTimeList.toString()).set("cron-nextTriggerTime", nextTriggerTime).bgsave().exec(function(){ return DB.hgetall("cron-list", function(arg$, allTimeTriggers){ return console.log("allTimeTriggers", (import$({}, allTimeTriggers)), " nextTriggerTime " + nextTriggerTime); }); }); } }); case 'sendemailout': console.log("onmessage " + emaildata.to); return emailer != null ? emailer.sendemail(emaildata.to, emaildata.subject, emaildata.body, function(message){ return io.sockets['in']("log-" + room).emit('data', { type: 'confirmemailsent', message: message }); }) : void 8; case 'load-sheet': return SC._get(ref, io, function(){ if (SC[ref]) { return SC[ref].exportSave(function(save){ return w.postMessage({ type: 'recalc', ref: ref, snapshot: save }); }); } else { return w.postMessage({ type: 'recalc', ref: ref, snapshot: '' }); } }); } }; w._doClearCache = function(){ return this.postMessage({ type: 'clearCache' }); }; w.ExecuteCommand = function(command){ return this.postMessage({ type: 'cmd', command: command }); }; w.exportHTML = function(cb){ return w.thread.eval("window.ss.CreateSheetHTML()", function(arg$, html){ return cb(html); }); }; w.exportCSV = function(cb){ return w.thread.eval("window.ss.SocialCalc.ConvertSaveToOtherFormat(\n window.ss.CreateSheetSave(), \"csv\"\n)", function(arg$, csv){ return cb(csv); }); }; if (IsThreaded) { w.exportHTML = function(cb){ var x; x = new Worker(function(){ return this.onmessage = function(arg$){ var ref$, snapshot, log, ref1$, parts, save, ss, cmdstr, line, e; ref$ = arg$.data, snapshot = ref$.snapshot, log = (ref1$ = ref$.log) != null ? ref1$ : []; try { parts = SocialCalc.SpreadsheetControlDecodeSpreadsheetSave("", snapshot); save = snapshot.substring(parts.sheet.start, parts.sheet.end); window.setTimeout = function(cb, ms){ return thread.nextTick(cb); }; window.clearTimeout = function(){}; window.ss = ss = new SocialCalc.SpreadsheetControl; ss.sheet.ResetSheet(); ss.ParseSheetSave(save); if (log != null && log.length) { cmdstr = (function(){ var i$, ref$, len$, results$ = []; for (i$ = 0, len$ = (ref$ = log).length; i$ < len$; ++i$) { line = ref$[i$]; if (!/^re(calc|display)$/.test(line) && line !== "set sheet defaulttextvalueformat text-wiki") { results$.push(line); } } return results$; }()).join("\n"); if (cmdstr.length) { cmdstr += "\n"; } ss.editor.StatusCallback.EtherCalc = { func: function(editor, status, arg){ if (status !== 'doneposcalc') { return; } return postMessage(ss.CreateSheetHTML()); } }; return ss.context.sheetobj.ScheduleSheetCommands(cmdstr, false, true); } else { return postMessage(ss.CreateSheetHTML()); } } catch (e$) { e = e$; return postMessage("ERROR: " + e); } }; }); x.onmessage = function(arg$){ var data; data = arg$.data; x.thread.destroy(); return cb(data); }; DB.lrange("log-" + room, 0, -1, function(arg$, log){ return x.thread.eval(bootSC, function(){ return x.postMessage({ snapshot: w._snapshot, log: log }); }); }); }; } if (IsThreaded) { w.exportCSV = function(cb){ var x; x = new Worker(function(){ return this.onmessage = function(arg$){ var ref$, snapshot, log, ref1$, parts, save, cmdstr, line, ss, e; ref$ = arg$.data, snapshot = ref$.snapshot, log = (ref1$ = ref$.log) != null ? ref1$ : []; try { parts = SocialCalc.SpreadsheetControlDecodeSpreadsheetSave("", snapshot); save = snapshot.substring(parts.sheet.start, parts.sheet.end); if (log != null && log.length) { cmdstr = (function(){ var i$, ref$, len$, results$ = []; for (i$ = 0, len$ = (ref$ = log).length; i$ < len$; ++i$) { line = ref$[i$]; if (!/^re(calc|display)$/.test(line) && line !== "set sheet defaulttextvalueformat text-wiki") { results$.push(line); } } return results$; }()).join("\n"); if (cmdstr.length) { cmdstr += "\n"; } window.setTimeout = function(cb, ms){ return thread.nextTick(cb); }; window.clearTimeout = function(){}; window.ss = ss = new SocialCalc.SpreadsheetControl; ss.sheet.ResetSheet(); ss.ParseSheetSave(save); ss.editor.StatusCallback.EtherCalc = { func: function(editor, status, arg){ var save; if (status !== 'doneposcalc') { return; } save = ss.CreateSheetSave(); return postMessage(SocialCalc.ConvertSaveToOtherFormat(save, 'csv')); } }; return ss.context.sheetobj.ScheduleSheetCommands(cmdstr, false, true); } else { return postMessage(SocialCalc.ConvertSaveToOtherFormat(save, 'csv')); } } catch (e$) { e = e$; return postMessage("ERROR: " + e); } }; }); x.onmessage = function(arg$){ var data; data = arg$.data; x.thread.destroy(); return cb(data); }; DB.lrange("log-" + room, 0, -1, function(arg$, log){ return x.thread.eval(bootSC, function(){ return x.postMessage({ snapshot: w._snapshot, log: log }); }); }); }; } w._eval = function(code, cb){ return setTimeout(function(){ return w.thread.eval(code, function(arg$, rv){ if (rv != null) { return cb(rv); } return w.thread.eval(code, function(arg$, rv){ return cb(rv); }); }); }, 100); }; if (IsThreaded) { w._eval = function(code, cb){ var x; x = new Worker(function(){ return this.onmessage = function(arg$){ var ref$, snapshot, log, ref1$, code, parts, save, ss, cmdstr, line, e; ref$ = arg$.data, snapshot = ref$.snapshot, log = (ref1$ = ref$.log) != null ? ref1$ : [], code = ref$.code; try { parts = SocialCalc.SpreadsheetControlDecodeSpreadsheetSave("", snapshot); save = snapshot.substring(parts.sheet.start, parts.sheet.end); window.setTimeout = function(cb, ms){ return thread.nextTick(cb); }; window.clearTimeout = function(){}; window.ss = ss = new SocialCalc.SpreadsheetControl; ss.sheet.ResetSheet(); ss.ParseSheetSave(save); if (log != null && log.length) { cmdstr = (function(){ var i$, ref$, len$, results$ = []; for (i$ = 0, len$ = (ref$ = log).length; i$ < len$; ++i$) { line = ref$[i$]; if (!/^re(calc|display)$/.test(line) && line !== "set sheet defaulttextvalueformat text-wiki") { results$.push(line); } } return results$; }()).join("\n"); if (cmdstr.length) { cmdstr += "\n"; } ss.editor.StatusCallback.EtherCalc = { func: function(editor, status, arg){ if (status !== 'doneposcalc') { return; } return postMessage(eval(code)); } }; return ss.context.sheetobj.ScheduleSheetCommands(cmdstr, false, true); } else { return postMessage(eval(code)); } } catch (e$) { e = e$; return postMessage("ERROR: " + e); } }; }); x.onmessage = function(arg$){ var data; data = arg$.data; x.thread.destroy(); return cb(data); }; return DB.lrange("log-" + room, 0, -1, function(arg$, log){ return x.thread.eval(bootSC, function(){ return x.postMessage({ snapshot: w._snapshot, log: log, code: code }); }); }); }; } w.exportSave = function(cb){ return w._eval("window.ss.CreateSheetSave()", cb); }; w.exportCell = function(coord, cb){ return w._eval("JSON.stringify(window.ss.sheet.cells[" + (replace$.call(JSON.stringify(coord), /\s/g, '')) + "])", function(cell){ if (cell === 'undefined') { return cb('null'); } else { return cb(cell); } }); }; w.exportCells = function(cb){ return w._eval("JSON.stringify(window.ss.sheet.cells)", cb); }; w.exportAttribs = function(cb){ return w._eval("window.ss.sheet.attribs", cb); }; w.triggerActionCell = function(coord, cb){ return w._eval("window.ss.SocialCalc.TriggerIoAction.Email('" + coord + "')", function(emailcmd){ var i$, len$, nextEmail, res$, j$, len1$, addSpaces, emailto, subject, body; for (i$ = 0, len$ = emailcmd.length; i$ < len$; ++i$) { nextEmail = emailcmd[i$]; res$ = []; for (j$ = 0, len1$ = nextEmail.length; j$ < len1$; ++j$) { addSpaces = nextEmail[j$]; res$.push(addSpaces.replace(/%20/g, ' ')); } nextEmail = res$; emailto = nextEmail[0], subject = nextEmail[1], body = nextEmail[2]; if (emailer != null) { emailer.sendemail(emailto, subject, body, fn$); } } return cb(emailcmd); function fn$(message){} }); }; w.thread.eval(bootSC, function(){ return w.postMessage({ type: 'init', room: room, log: log, snapshot: snapshot }); }); return w; }; return SC; }; function import$(obj, src){ var own = {}.hasOwnProperty; for (var key in src) if (own.call(src, key)) obj[key] = src[key]; return obj; } }).call(this);