Merge branch 'master' of git://github.com/Pita/etherpad-lite

Conflicts:
	static/index.html
This commit is contained in:
Eric Martindale 2011-11-14 10:10:48 +00:00
commit 5185804f70
11 changed files with 189 additions and 53 deletions

View file

@ -20,13 +20,6 @@ hash node > /dev/null 2>&1 || {
exit 1 exit 1
} }
#check node version
NODE_VERSION=$(node --version)
if [ ! $(echo $NODE_VERSION | cut -d "." -f 1-2) = "v0.4" ]; then
echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.4.x" >&2
exit 1
fi
#Is npm installed? #Is npm installed?
hash npm > /dev/null 2>&1 || { hash npm > /dev/null 2>&1 || {
echo "Please install npm ( http://npmjs.org )" >&2 echo "Please install npm ( http://npmjs.org )" >&2

View file

@ -25,6 +25,7 @@ var groupManager = require("./GroupManager");
var authorManager = require("./AuthorManager"); var authorManager = require("./AuthorManager");
var sessionManager = require("./SessionManager"); var sessionManager = require("./SessionManager");
var async = require("async"); var async = require("async");
var exportHtml = require("../utils/ExportHtml");
/**********************/ /**********************/
/**GROUP FUNCTIONS*****/ /**GROUP FUNCTIONS*****/
@ -169,6 +170,90 @@ exports.setText = function(padID, text, callback)
}); });
} }
/**
getHTML(padID, [rev]) returns the html of a pad
Example returns:
{code: 0, message:"ok", data: {text:"Welcome <strong>Text</strong>"}}
{code: 1, message:"padID does not exist", data: null}
*/
exports.getHTML = function(padID, rev, callback)
{
if(typeof rev == "function")
{
callback = rev;
rev = undefined;
}
if (rev !== undefined && typeof rev != "number")
{
if (!isNaN(parseInt(rev)))
{
rev = parseInt(rev);
}
else
{
callback({stop: "rev is not a number"});
return;
}
}
if(rev !== undefined && rev < 0)
{
callback({stop: "rev is a negative number"});
return;
}
if(rev !== undefined && !is_int(rev))
{
callback({stop: "rev is a float value"});
return;
}
getPadSafe(padID, true, function(err, pad)
{
if(err)
{
callback(err);
return;
}
//the client asked for a special revision
if(rev !== undefined)
{
//check if this is a valid revision
if(rev > pad.getHeadRevisionNumber())
{
callback({stop: "rev is higher than the head revision of the pad"});
return;
}
//get the html of this revision
exportHtml.getPadHTML(pad, rev, function(err, html)
{
if(!err)
{
data = {html: html};
}
callback(err, data);
});
}
//the client wants the latest text, lets return it to him
else
{
exportHtml.getPadHTML(pad, undefined, function (err, html)
{
if(!err)
{
data = {html: html};
}
callback(err, data);
});
}
});
}
/*****************/ /*****************/
/**PAD FUNCTIONS */ /**PAD FUNCTIONS */
/*****************/ /*****************/

View file

@ -50,6 +50,7 @@ var functions = {
"listSessionsOfAuthor" : ["authorID"], "listSessionsOfAuthor" : ["authorID"],
"getText" : ["padID", "rev"], "getText" : ["padID", "rev"],
"setText" : ["padID", "text"], "setText" : ["padID", "text"],
"getHTML" : ["padID", "rev"],
"getRevisionsCount" : ["padID"], "getRevisionsCount" : ["padID"],
"deletePad" : ["padID"], "deletePad" : ["padID"],
"getReadOnlyID" : ["padID"], "getReadOnlyID" : ["padID"],

View file

@ -81,10 +81,9 @@ exports.doExport = function(req, res, padId, type)
res.send(html); res.send(html);
callback("stop"); callback("stop");
} }
//write the html export to a file else //write the html export to a file
else
{ {
randNum = Math.floor(Math.random()*new Date().getTime()); randNum = Math.floor(Math.random()*0xFFFFFFFF);
srcFile = tempDirectory + "/eplite_export_" + randNum + ".html"; srcFile = tempDirectory + "/eplite_export_" + randNum + ".html";
fs.writeFile(srcFile, html, callback); fs.writeFile(srcFile, html, callback);
} }
@ -114,10 +113,13 @@ exports.doExport = function(req, res, padId, type)
function(callback) function(callback)
{ {
//100ms delay to accomidate for slow windows fs //100ms delay to accomidate for slow windows fs
setTimeout(function() if(os.type().indexOf("Windows") > -1)
{ {
fs.unlink(destFile, callback); setTimeout(function()
}, 100); {
fs.unlink(destFile, callback);
}, 100);
}
} }
], callback); ], callback);
} }

View file

@ -61,10 +61,19 @@ exports.doImport = function(req, res, padId)
form.parse(req, function(err, fields, files) form.parse(req, function(err, fields, files)
{ {
//save the path of the uploaded file //the upload failed, stop at this point
srcFile = files.file.path; if(err || files.file === undefined)
{
callback(err); console.warn("Uploading Error: " + err.stack);
callback("uploadFailed");
}
//everything ok, continue
else
{
//save the path of the uploaded file
srcFile = files.file.path;
callback();
}
}); });
}, },
@ -157,6 +166,13 @@ exports.doImport = function(req, res, padId)
} }
], function(err) ], function(err)
{ {
//the upload failed, there is nothing we can do, send a 500
if(err == "uploadFailed")
{
res.send(500);
return;
}
if(err) throw err; if(err) throw err;
//close the connection //close the connection

View file

@ -136,7 +136,7 @@ exports.handleDisconnect = function(client)
{ {
if(pad2sessions[sessionPad][i] == client.id) if(pad2sessions[sessionPad][i] == client.id)
{ {
delete pad2sessions[sessionPad][i]; pad2sessions[sessionPad].splice(i, 1);
break; break;
} }
} }
@ -193,7 +193,7 @@ exports.handleMessage = function(client, message)
//if the message type is unkown, throw an exception //if the message type is unkown, throw an exception
else else
{ {
messageLogger.warn("Droped message, unkown Message Type " + message.type); messageLogger.warn("Dropped message, unkown Message Type " + message.type + ": " + JSON.stringify(message));
} }
} }
@ -272,12 +272,12 @@ function handleSuggestUserName(client, message)
//check if all ok //check if all ok
if(message.data.payload.newName == null) if(message.data.payload.newName == null)
{ {
messageLogger.warn("Droped message, suggestUserName Message has no newName!"); messageLogger.warn("Dropped message, suggestUserName Message has no newName!");
return; return;
} }
if(message.data.payload.unnamedId == null) if(message.data.payload.unnamedId == null)
{ {
messageLogger.warn("Droped message, suggestUserName Message has no unnamedId!"); messageLogger.warn("Dropped message, suggestUserName Message has no unnamedId!");
return; return;
} }
@ -304,7 +304,7 @@ function handleUserInfoUpdate(client, message)
//check if all ok //check if all ok
if(message.data.userInfo.colorId == null) if(message.data.userInfo.colorId == null)
{ {
messageLogger.warn("Droped message, USERINFO_UPDATE Message has no colorId!"); messageLogger.warn("Dropped message, USERINFO_UPDATE Message has no colorId!");
return; return;
} }
@ -348,17 +348,17 @@ function handleUserChanges(client, message)
//check if all ok //check if all ok
if(message.data.baseRev == null) if(message.data.baseRev == null)
{ {
messageLogger.warn("Droped message, USER_CHANGES Message has no baseRev!"); messageLogger.warn("Dropped message, USER_CHANGES Message has no baseRev!");
return; return;
} }
if(message.data.apool == null) if(message.data.apool == null)
{ {
messageLogger.warn("Droped message, USER_CHANGES Message has no apool!"); messageLogger.warn("Dropped message, USER_CHANGES Message has no apool!");
return; return;
} }
if(message.data.changeset == null) if(message.data.changeset == null)
{ {
messageLogger.warn("Droped message, USER_CHANGES Message has no changeset!"); messageLogger.warn("Dropped message, USER_CHANGES Message has no changeset!");
return; return;
} }
@ -600,22 +600,22 @@ function handleClientReady(client, message)
//check if all ok //check if all ok
if(!message.token) if(!message.token)
{ {
messageLogger.warn("Droped message, CLIENT_READY Message has no token!"); messageLogger.warn("Dropped message, CLIENT_READY message has no token!");
return; return;
} }
if(!message.padId) if(!message.padId)
{ {
messageLogger.warn("Droped message, CLIENT_READY Message has no padId!"); messageLogger.warn("Dropped message, CLIENT_READY message has no padId!");
return; return;
} }
if(!message.protocolVersion) if(!message.protocolVersion)
{ {
messageLogger.warn("Droped message, CLIENT_READY Message has no protocolVersion!"); messageLogger.warn("Dropped message, CLIENT_READY message has no protocolVersion!");
return; return;
} }
if(message.protocolVersion != 2) if(message.protocolVersion != 2)
{ {
messageLogger.warn("Droped message, CLIENT_READY Message has a unkown protocolVersion '" + message.protocolVersion + "'!"); messageLogger.warn("Dropped message, CLIENT_READY message has an unkown protocolVersion '" + message.protocolVersion + "'!");
return; return;
} }

View file

@ -77,7 +77,7 @@ exports.handleMessage = function(client, message)
//if the message type is unkown, throw an exception //if the message type is unkown, throw an exception
else else
{ {
messageLogger.warn("Droped message, unkown Message Type: '" + message.type + "'"); messageLogger.warn("Dropped message, unkown Message Type: '" + message.type + "'");
} }
} }
@ -85,7 +85,7 @@ function handleClientReady(client, message)
{ {
if(message.padId == null) if(message.padId == null)
{ {
messageLogger.warn("Droped message, changeset request has no padId!"); messageLogger.warn("Dropped message, changeset request has no padId!");
return; return;
} }
@ -106,27 +106,27 @@ function handleChangesetRequest(client, message)
//check if all ok //check if all ok
if(message.data == null) if(message.data == null)
{ {
messageLogger.warn("Droped message, changeset request has no data!"); messageLogger.warn("Dropped message, changeset request has no data!");
return; return;
} }
if(message.padId == null) if(message.padId == null)
{ {
messageLogger.warn("Droped message, changeset request has no padId!"); messageLogger.warn("Dropped message, changeset request has no padId!");
return; return;
} }
if(message.data.granularity == null) if(message.data.granularity == null)
{ {
messageLogger.warn("Droped message, changeset request has no granularity!"); messageLogger.warn("Dropped message, changeset request has no granularity!");
return; return;
} }
if(message.data.start == null) if(message.data.start == null)
{ {
messageLogger.warn("Droped message, changeset request has no start!"); messageLogger.warn("Dropped message, changeset request has no start!");
return; return;
} }
if(message.data.requestID == null) if(message.data.requestID == null)
{ {
messageLogger.warn("Droped message, changeset request has no requestID!"); messageLogger.warn("Dropped message, changeset request has no requestID!");
return; return;
} }

View file

@ -85,6 +85,8 @@ function getPadHTML(pad, revNum, callback)
}); });
} }
exports.getPadHTML = getPadHTML;
function getHTMLFromAtext(pad, atext) function getHTMLFromAtext(pad, atext)
{ {
var apool = pad.apool(); var apool = pad.apool();
@ -119,8 +121,10 @@ function getHTMLFromAtext(pad, atext)
var taker = Changeset.stringIterator(text); var taker = Changeset.stringIterator(text);
var assem = Changeset.stringAssembler(); var assem = Changeset.stringAssembler();
var openTags = [];
function emitOpenTag(i) function emitOpenTag(i)
{ {
openTags.unshift(i);
assem.append('<'); assem.append('<');
assem.append(tags[i]); assem.append(tags[i]);
assem.append('>'); assem.append('>');
@ -128,11 +132,28 @@ function getHTMLFromAtext(pad, atext)
function emitCloseTag(i) function emitCloseTag(i)
{ {
openTags.shift();
assem.append('</'); assem.append('</');
assem.append(tags[i]); assem.append(tags[i]);
assem.append('>'); assem.append('>');
} }
function orderdCloseTags(tags2close)
{
for(var i=0;i<openTags.length;i++)
{
for(var j=0;j<tags2close.length;j++)
{
if(tags2close[j] == openTags[i])
{
emitCloseTag(tags2close[j]);
i--;
break;
}
}
}
}
var urls = _findURLs(text); var urls = _findURLs(text);
var idx = 0; var idx = 0;
@ -204,18 +225,25 @@ function getHTMLFromAtext(pad, atext)
} }
} }
var tags2close = [];
for (var i = propVals.length - 1; i >= 0; i--) for (var i = propVals.length - 1; i >= 0; i--)
{ {
if (propVals[i] === LEAVE) if (propVals[i] === LEAVE)
{ {
emitCloseTag(i); //emitCloseTag(i);
tags2close.push(i);
propVals[i] = false; propVals[i] = false;
} }
else if (propVals[i] === STAY) else if (propVals[i] === STAY)
{ {
emitCloseTag(i); //emitCloseTag(i);
tags2close.push(i);
} }
} }
orderdCloseTags(tags2close);
for (var i = 0; i < propVals.length; i++) for (var i = 0; i < propVals.length; i++)
{ {
if (propVals[i] === ENTER || propVals[i] === STAY) if (propVals[i] === ENTER || propVals[i] === STAY)
@ -231,18 +259,27 @@ function getHTMLFromAtext(pad, atext)
{ {
chars--; // exclude newline at end of line, if present chars--; // exclude newline at end of line, if present
} }
var s = taker.take(chars); var s = taker.take(chars);
//removes the characters with the code 12. Don't know where they come
//from but they break the abiword parser and are completly useless
s = s.replace(String.fromCharCode(12), "");
assem.append(_escapeHTML(s)); assem.append(_escapeHTML(s));
} // end iteration over spans in line } // end iteration over spans in line
var tags2close = [];
for (var i = propVals.length - 1; i >= 0; i--) for (var i = propVals.length - 1; i >= 0; i--)
{ {
if (propVals[i]) if (propVals[i])
{ {
emitCloseTag(i); tags2close.push(i);
propVals[i] = false; propVals[i] = false;
} }
} }
orderdCloseTags(tags2close);
} // end processNextChars } // end processNextChars
if (urls) if (urls)
{ {

View file

@ -3,23 +3,23 @@
"description" : "A Etherpad based on node.js", "description" : "A Etherpad based on node.js",
"homepage" : "https://github.com/Pita/etherpad-lite", "homepage" : "https://github.com/Pita/etherpad-lite",
"keywords" : ["etherpad", "realtime", "collaborative", "editor"], "keywords" : ["etherpad", "realtime", "collaborative", "editor"],
"author" : "Peter 'Pita' Martischka <petermartischka@googlemail.com>", "author" : "Peter 'Pita' Martischka <petermartischka@googlemail.com> - Primary Technology Ltd",
"contributors": [ "contributors": [
{ "name": "John McLear", { "name": "John McLear",
"name": "Hans Pinckaers", "name": "Hans Pinckaers",
"name": "Robin Buse"} "name": "Robin Buse"}
], ],
"dependencies" : { "dependencies" : {
"socket.io" : "0.7.9", "socket.io" : "0.8.7",
"ueberDB" : "0.1.2", "ueberDB" : "0.1.3",
"async" : "0.1.9", "async" : "0.1.15",
"joose" : "3.18.0", "joose" : "3.50.0",
"express" : "2.4.5", "express" : "2.5.0",
"clean-css" : "0.2.4", "clean-css" : "0.2.4",
"uglify-js" : "1.0.7", "uglify-js" : "1.1.1",
"gzip" : "0.1.0", "gzip" : "0.1.0",
"formidable" : "1.0.2", "formidable" : "1.0.7",
"log4js" : "0.3.8" "log4js" : "0.3.9"
}, },
"version" : "1.0.0" "version" : "1.0.0"
} }

View file

@ -93,7 +93,7 @@ a img
} }
input[type="file"] { input[type="file"] {
color: #fff; color: #000;
} }
#editbar ul li.separator #editbar ul li.separator

View file

@ -86,12 +86,13 @@
input[type="submit"]::-moz-focus-inner { border: 0 } input[type="submit"]::-moz-focus-inner { border: 0 }
@-moz-document url-prefix() { input[type="submit"] { padding: 7px } } @-moz-document url-prefix() { input[type="submit"] { padding: 7px } }
</style> </style>
<body onload="document.mainform.padname.focus();">
<link href="static/custom/index.css" rel="stylesheet"> <link href="static/custom/index.css" rel="stylesheet">
<script src="static/custom/index.js"></script> <script src="static/custom/index.js"></script>
<div id="container"> <div id="container">
<div id="button" onclick="go2Random()">New Pad</div><br><div id="label">or create/open a Pad with the name</div> <div id="button" onclick="go2Random()">New Pad</div><br><div id="label">or create/open a Pad with the name</div>
<form action="#" onsubmit="go2Name();return false;"> <form action="#" name="mainform" onsubmit="go2Name();return false;">
<input type="text" id="padname" autofocus> <input type="text" name="padname" id="padname" autofocus>
<input type="submit" value="OK"> <input type="submit" value="OK">
</form> </form>
</div> </div>
@ -123,4 +124,5 @@
//start the costum js //start the costum js
if(typeof costumStart == "function") costumStart(); if(typeof costumStart == "function") costumStart();
</script> </script>
</body>
</html> </html>