mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-05-10 08:55:00 -04:00
Merge 0b6709392b
into e1edc8079f
This commit is contained in:
commit
be4505d7fc
104 changed files with 1479 additions and 1479 deletions
|
@ -13,7 +13,7 @@ IRC channels: [#etherpad](irc://freenode/#etherpad) ([webchat](http://webchat.fr
|
||||||
* easy to use for people
|
* easy to use for people
|
||||||
* using less resources on server side
|
* using less resources on server side
|
||||||
* easy to embed for admins
|
* easy to embed for admins
|
||||||
* also runable as etherpad lite only
|
* also runable as etherpad lite only
|
||||||
* keep it maintainable, we don't wanna end ob as the monster Etherpad was
|
* keep it maintainable, we don't wanna end ob as the monster Etherpad was
|
||||||
* extensible, as much functionality should be extendable with plugins so changes don't have to be done in core
|
* extensible, as much functionality should be extendable with plugins so changes don't have to be done in core
|
||||||
|
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -3,7 +3,7 @@ outdoc_files = $(addprefix out/,$(doc_sources:.md=.html))
|
||||||
|
|
||||||
docassets = $(addprefix out/,$(wildcard doc/assets/*))
|
docassets = $(addprefix out/,$(wildcard doc/assets/*))
|
||||||
|
|
||||||
VERSION = $(shell node -e "console.log( require('./src/package.json').version )")
|
VERSION = $(shell node -e "console.log( require('./src/package.json').version )")
|
||||||
|
|
||||||
docs: $(outdoc_files) $(docassets)
|
docs: $(outdoc_files) $(docassets)
|
||||||
|
|
||||||
|
|
18
README.md
18
README.md
|
@ -1,10 +1,10 @@
|
||||||
# Making collaborative editing the standard on the web
|
# Making collaborative editing the standard on the web
|
||||||
|
|
||||||
# About
|
# About
|
||||||
Etherpad lite is a really-real time collaborative editor spawned from the Hell fire of Etherpad.
|
Etherpad lite is a really-real time collaborative editor spawned from the Hell fire of Etherpad.
|
||||||
We're reusing the well tested Etherpad easysync library to make it really realtime. Etherpad Lite
|
We're reusing the well tested Etherpad easysync library to make it really realtime. Etherpad Lite
|
||||||
is based on node.js ergo is much lighter and more stable than the original Etherpad. Our hope
|
is based on node.js ergo is much lighter and more stable than the original Etherpad. Our hope
|
||||||
is that this will encourage more users to use and install a realtime collaborative editor. A smaller, manageable and well
|
is that this will encourage more users to use and install a realtime collaborative editor. A smaller, manageable and well
|
||||||
documented codebase makes it easier for developers to improve the code and contribute towards the project.
|
documented codebase makes it easier for developers to improve the code and contribute towards the project.
|
||||||
|
|
||||||
**Etherpad vs Etherpad lite**
|
**Etherpad vs Etherpad lite**
|
||||||
|
@ -24,10 +24,10 @@ documented codebase makes it easier for developers to improve the code and contr
|
||||||
<tr>
|
<tr>
|
||||||
<td align="right">RAM Usage immediately after start</td><td>257 MB (grows to ~1GB)</td><td>16 MB (grows to ~30MB)</td>
|
<td align="right">RAM Usage immediately after start</td><td>257 MB (grows to ~1GB)</td><td>16 MB (grows to ~30MB)</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
|
|
||||||
Etherpad Lite is designed to be easily embeddable and provides a [HTTP API](https://github.com/Pita/etherpad-lite/wiki/HTTP-API)
|
Etherpad Lite is designed to be easily embeddable and provides a [HTTP API](https://github.com/Pita/etherpad-lite/wiki/HTTP-API)
|
||||||
that allows your web application to manage pads, users and groups. It is recommended to use the client implementations available for this API, listed on [this wiki page](https://github.com/Pita/etherpad-lite/wiki/HTTP-API-client-libraries).
|
that allows your web application to manage pads, users and groups. It is recommended to use the client implementations available for this API, listed on [this wiki page](https://github.com/Pita/etherpad-lite/wiki/HTTP-API-client-libraries).
|
||||||
There is also a [jQuery plugin](https://github.com/johnyma22/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website
|
There is also a [jQuery plugin](https://github.com/johnyma22/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website
|
||||||
|
|
||||||
|
@ -62,8 +62,8 @@ Update to the latest version with `git pull origin`, then run `bin\installOnWind
|
||||||
[Next steps](#next-steps).
|
[Next steps](#next-steps).
|
||||||
|
|
||||||
## Linux
|
## Linux
|
||||||
You'll need gzip, git, curl, libssl develop libraries, python and gcc.
|
You'll need gzip, git, curl, libssl develop libraries, python and gcc.
|
||||||
*For Debian/Ubuntu*: `apt-get install gzip git-core curl python libssl-dev pkg-config build-essential`
|
*For Debian/Ubuntu*: `apt-get install gzip git-core curl python libssl-dev pkg-config build-essential`
|
||||||
*For Fedora/CentOS*: `yum install gzip git-core curl python openssl-devel && yum groupinstall "Development Tools"`
|
*For Fedora/CentOS*: `yum install gzip git-core curl python openssl-devel && yum groupinstall "Development Tools"`
|
||||||
|
|
||||||
Additionally, you'll need [node.js](http://nodejs.org).
|
Additionally, you'll need [node.js](http://nodejs.org).
|
||||||
|
@ -73,7 +73,7 @@ Additionally, you'll need [node.js](http://nodejs.org).
|
||||||
1. Move to a folder where you want to install Etherpad Lite. Clone the git repository `git clone git://github.com/Pita/etherpad-lite.git`
|
1. Move to a folder where you want to install Etherpad Lite. Clone the git repository `git clone git://github.com/Pita/etherpad-lite.git`
|
||||||
2. Change into the new directory containing the cloned source code `cd etherpad-lite`
|
2. Change into the new directory containing the cloned source code `cd etherpad-lite`
|
||||||
|
|
||||||
Now, run `bin\run.sh` and open <http://127.0.0.1:9001> in your browser.
|
Now, run `bin\run.sh` and open <http://127.0.0.1:9001> in your browser.
|
||||||
|
|
||||||
Update to the latest version with `git pull origin`. The next start with bin/run.sh will update the dependencies.
|
Update to the latest version with `git pull origin`. The next start with bin/run.sh will update the dependencies.
|
||||||
|
|
||||||
|
|
|
@ -11,26 +11,26 @@ if [ -d "../bin" ]; then
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#Is wget installed?
|
#Is wget installed?
|
||||||
hash wget > /dev/null 2>&1 || {
|
hash wget > /dev/null 2>&1 || {
|
||||||
echo "Please install wget" >&2
|
echo "Please install wget" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#Is zip installed?
|
#Is zip installed?
|
||||||
hash zip > /dev/null 2>&1 || {
|
hash zip > /dev/null 2>&1 || {
|
||||||
echo "Please install zip" >&2
|
echo "Please install zip" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#Is zip installed?
|
#Is zip installed?
|
||||||
hash unzip > /dev/null 2>&1 || {
|
hash unzip > /dev/null 2>&1 || {
|
||||||
echo "Please install unzip" >&2
|
echo "Please install unzip" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
START_FOLDER=$(pwd);
|
START_FOLDER=$(pwd);
|
||||||
|
|
||||||
echo "create a clean environment in /tmp/etherpad-lite-win..."
|
echo "create a clean environment in /tmp/etherpad-lite-win..."
|
||||||
rm -rf /tmp/etherpad-lite-win
|
rm -rf /tmp/etherpad-lite-win
|
||||||
cp -ar . /tmp/etherpad-lite-win
|
cp -ar . /tmp/etherpad-lite-win
|
||||||
cd /tmp/etherpad-lite-win
|
cd /tmp/etherpad-lite-win
|
||||||
|
|
|
@ -25,11 +25,11 @@ async.series([
|
||||||
{
|
{
|
||||||
db.init(callback);
|
db.init(callback);
|
||||||
},
|
},
|
||||||
//get the pad
|
//get the pad
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
padManager = require('../src/node/db/PadManager');
|
padManager = require('../src/node/db/PadManager');
|
||||||
|
|
||||||
padManager.doesPadExists(padId, function(err, exists)
|
padManager.doesPadExists(padId, function(err, exists)
|
||||||
{
|
{
|
||||||
if(!exists)
|
if(!exists)
|
||||||
|
@ -37,8 +37,8 @@ async.series([
|
||||||
console.error("Pad does not exist");
|
console.error("Pad does not exist");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
padManager.getPad(padId, function(err, _pad)
|
padManager.getPad(padId, function(err, _pad)
|
||||||
{
|
{
|
||||||
pad = _pad;
|
pad = _pad;
|
||||||
callback(err);
|
callback(err);
|
||||||
|
@ -46,7 +46,7 @@ async.series([
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
//create an array with key kevisions
|
//create an array with key kevisions
|
||||||
//key revisions always save the full pad atext
|
//key revisions always save the full pad atext
|
||||||
var head = pad.getHeadRevisionNumber();
|
var head = pad.getHeadRevisionNumber();
|
||||||
|
@ -55,7 +55,7 @@ async.series([
|
||||||
{
|
{
|
||||||
keyRevisions.push(i);
|
keyRevisions.push(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//run trough all key revisions
|
//run trough all key revisions
|
||||||
async.forEachSeries(keyRevisions, function(keyRev, callback)
|
async.forEachSeries(keyRevisions, function(keyRev, callback)
|
||||||
{
|
{
|
||||||
|
@ -65,10 +65,10 @@ async.series([
|
||||||
{
|
{
|
||||||
revisionsNeeded.push(i);
|
revisionsNeeded.push(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//this array will hold all revision changesets
|
//this array will hold all revision changesets
|
||||||
var revisions = [];
|
var revisions = [];
|
||||||
|
|
||||||
//run trough all needed revisions and get them from the database
|
//run trough all needed revisions and get them from the database
|
||||||
async.forEach(revisionsNeeded, function(revNum, callback)
|
async.forEach(revisionsNeeded, function(revNum, callback)
|
||||||
{
|
{
|
||||||
|
@ -84,14 +84,14 @@ async.series([
|
||||||
callback(err);
|
callback(err);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if the pad has a pool
|
//check if the pad has a pool
|
||||||
if(pad.pool === undefined )
|
if(pad.pool === undefined )
|
||||||
{
|
{
|
||||||
console.error("Attribute pool is missing");
|
console.error("Attribute pool is missing");
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if there is a atext in the keyRevisions
|
//check if there is a atext in the keyRevisions
|
||||||
if(revisions[keyRev] === undefined || revisions[keyRev].meta === undefined || revisions[keyRev].meta.atext === undefined)
|
if(revisions[keyRev] === undefined || revisions[keyRev].meta === undefined || revisions[keyRev].meta.atext === undefined)
|
||||||
{
|
{
|
||||||
|
@ -99,10 +99,10 @@ async.series([
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var apool = pad.pool;
|
var apool = pad.pool;
|
||||||
var atext = revisions[keyRev].meta.atext;
|
var atext = revisions[keyRev].meta.atext;
|
||||||
|
|
||||||
for(var i=keyRev+1;i<=keyRev+100 && i<=head; i++)
|
for(var i=keyRev+1;i<=keyRev+100 && i<=head; i++)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -118,7 +118,7 @@ async.series([
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}, callback);
|
}, callback);
|
||||||
|
@ -126,8 +126,8 @@ async.series([
|
||||||
], function (err)
|
], function (err)
|
||||||
{
|
{
|
||||||
if(err) throw err;
|
if(err) throw err;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
console.log("finished");
|
console.log("finished");
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
146
bin/convert.js
146
bin/convert.js
|
@ -27,21 +27,21 @@ log("open output file...");
|
||||||
var sqlOutput = fs.openSync(sqlOutputFile, "w");
|
var sqlOutput = fs.openSync(sqlOutputFile, "w");
|
||||||
var sql = "SET CHARACTER SET UTF8;\n" +
|
var sql = "SET CHARACTER SET UTF8;\n" +
|
||||||
"CREATE TABLE IF NOT EXISTS `store` ( \n" +
|
"CREATE TABLE IF NOT EXISTS `store` ( \n" +
|
||||||
"`key` VARCHAR( 100 ) NOT NULL , \n" +
|
"`key` VARCHAR( 100 ) NOT NULL , \n" +
|
||||||
"`value` LONGTEXT NOT NULL , \n" +
|
"`value` LONGTEXT NOT NULL , \n" +
|
||||||
"PRIMARY KEY ( `key` ) \n" +
|
"PRIMARY KEY ( `key` ) \n" +
|
||||||
") ENGINE = INNODB;\n" +
|
") ENGINE = INNODB;\n" +
|
||||||
"START TRANSACTION;\n\n";
|
"START TRANSACTION;\n\n";
|
||||||
fs.writeSync(sqlOutput, sql);
|
fs.writeSync(sqlOutput, sql);
|
||||||
log("done");
|
log("done");
|
||||||
|
|
||||||
//set setings for ep db
|
//set setings for ep db
|
||||||
var etherpadDB= new mysql.Client();
|
var etherpadDB= new mysql.Client();
|
||||||
etherpadDB.host = settings.etherpadDB.host;
|
etherpadDB.host = settings.etherpadDB.host;
|
||||||
etherpadDB.port = settings.etherpadDB.port;
|
etherpadDB.port = settings.etherpadDB.port;
|
||||||
etherpadDB.database = settings.etherpadDB.database;
|
etherpadDB.database = settings.etherpadDB.database;
|
||||||
etherpadDB.user = settings.etherpadDB.user;
|
etherpadDB.user = settings.etherpadDB.user;
|
||||||
etherpadDB.password = settings.etherpadDB.password;
|
etherpadDB.password = settings.etherpadDB.password;
|
||||||
|
|
||||||
//get the timestamp once
|
//get the timestamp once
|
||||||
var timestamp = new Date().getTime();
|
var timestamp = new Date().getTime();
|
||||||
|
@ -53,7 +53,7 @@ async.series([
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
log("get all padIds out of the database...");
|
log("get all padIds out of the database...");
|
||||||
|
|
||||||
etherpadDB.query("SELECT ID FROM PAD_META", [], function(err, _padIDs)
|
etherpadDB.query("SELECT ID FROM PAD_META", [], function(err, _padIDs)
|
||||||
{
|
{
|
||||||
padIDs = _padIDs;
|
padIDs = _padIDs;
|
||||||
|
@ -63,9 +63,9 @@ async.series([
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
log("done");
|
log("done");
|
||||||
|
|
||||||
//create a queue with a concurrency 100
|
//create a queue with a concurrency 100
|
||||||
var queue = async.queue(function (padId, callback)
|
var queue = async.queue(function (padId, callback)
|
||||||
{
|
{
|
||||||
convertPad(padId, function(err)
|
convertPad(padId, function(err)
|
||||||
{
|
{
|
||||||
|
@ -73,10 +73,10 @@ async.series([
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
||||||
//set the step callback as the queue callback
|
//set the step callback as the queue callback
|
||||||
queue.drain = callback;
|
queue.drain = callback;
|
||||||
|
|
||||||
//add the padids to the worker queue
|
//add the padids to the worker queue
|
||||||
for(var i=0,length=padIDs.length;i<length;i++)
|
for(var i=0,length=padIDs.length;i<length;i++)
|
||||||
{
|
{
|
||||||
|
@ -86,25 +86,25 @@ async.series([
|
||||||
], function(err)
|
], function(err)
|
||||||
{
|
{
|
||||||
if(err) throw err;
|
if(err) throw err;
|
||||||
|
|
||||||
//write the groups
|
//write the groups
|
||||||
var sql = "";
|
var sql = "";
|
||||||
for(var proID in proID2groupID)
|
for(var proID in proID2groupID)
|
||||||
{
|
{
|
||||||
var groupID = proID2groupID[proID];
|
var groupID = proID2groupID[proID];
|
||||||
var subdomain = proID2subdomain[proID];
|
var subdomain = proID2subdomain[proID];
|
||||||
|
|
||||||
sql+="REPLACE INTO store VALUES (" + etherpadDB.escape("group:" + groupID) + ", " + etherpadDB.escape(JSON.stringify(groups[groupID]))+ ");\n";
|
sql+="REPLACE INTO store VALUES (" + etherpadDB.escape("group:" + groupID) + ", " + etherpadDB.escape(JSON.stringify(groups[groupID]))+ ");\n";
|
||||||
sql+="REPLACE INTO store VALUES (" + etherpadDB.escape("mapper2group:subdomain:" + subdomain) + ", " + etherpadDB.escape(groupID)+ ");\n";
|
sql+="REPLACE INTO store VALUES (" + etherpadDB.escape("mapper2group:subdomain:" + subdomain) + ", " + etherpadDB.escape(groupID)+ ");\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
//close transaction
|
//close transaction
|
||||||
sql+="COMMIT;";
|
sql+="COMMIT;";
|
||||||
|
|
||||||
//end the sql file
|
//end the sql file
|
||||||
fs.writeSync(sqlOutput, sql, undefined, "utf-8");
|
fs.writeSync(sqlOutput, sql, undefined, "utf-8");
|
||||||
fs.closeSync(sqlOutput);
|
fs.closeSync(sqlOutput);
|
||||||
|
|
||||||
log("finished.");
|
log("finished.");
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
});
|
});
|
||||||
|
@ -119,7 +119,7 @@ var padsDone = 0;
|
||||||
function incrementPadStats()
|
function incrementPadStats()
|
||||||
{
|
{
|
||||||
padsDone++;
|
padsDone++;
|
||||||
|
|
||||||
if(padsDone%100 == 0)
|
if(padsDone%100 == 0)
|
||||||
{
|
{
|
||||||
var averageTime = Math.round(padsDone/((new Date().getTime() - startTime)/1000));
|
var averageTime = Math.round(padsDone/((new Date().getTime() - startTime)/1000));
|
||||||
|
@ -150,10 +150,10 @@ function convertPad(padId, callback)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var sql = "SELECT * FROM `PAD_CHAT_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_CHAT_META` WHERE ID=?)";
|
var sql = "SELECT * FROM `PAD_CHAT_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_CHAT_META` WHERE ID=?)";
|
||||||
|
|
||||||
etherpadDB.query(sql, [padId], function(err, results)
|
etherpadDB.query(sql, [padId], function(err, results)
|
||||||
{
|
{
|
||||||
if(!err)
|
if(!err)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -164,7 +164,7 @@ function convertPad(padId, callback)
|
||||||
}
|
}
|
||||||
}catch(e) {err = e}
|
}catch(e) {err = e}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -172,10 +172,10 @@ function convertPad(padId, callback)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var sql = "SELECT * FROM `PAD_REVS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVS_META` WHERE ID=?)";
|
var sql = "SELECT * FROM `PAD_REVS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVS_META` WHERE ID=?)";
|
||||||
|
|
||||||
etherpadDB.query(sql, [padId], function(err, results)
|
etherpadDB.query(sql, [padId], function(err, results)
|
||||||
{
|
{
|
||||||
if(!err)
|
if(!err)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -186,7 +186,7 @@ function convertPad(padId, callback)
|
||||||
}
|
}
|
||||||
}catch(e) {err = e}
|
}catch(e) {err = e}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -194,10 +194,10 @@ function convertPad(padId, callback)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var sql = "SELECT * FROM `PAD_REVMETA_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVMETA_META` WHERE ID=?)";
|
var sql = "SELECT * FROM `PAD_REVMETA_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_REVMETA_META` WHERE ID=?)";
|
||||||
|
|
||||||
etherpadDB.query(sql, [padId], function(err, results)
|
etherpadDB.query(sql, [padId], function(err, results)
|
||||||
{
|
{
|
||||||
if(!err)
|
if(!err)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -208,7 +208,7 @@ function convertPad(padId, callback)
|
||||||
}
|
}
|
||||||
}catch(e) {err = e}
|
}catch(e) {err = e}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -216,7 +216,7 @@ function convertPad(padId, callback)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var sql = "SELECT `JSON` FROM `PAD_APOOL` WHERE `ID` = ?";
|
var sql = "SELECT `JSON` FROM `PAD_APOOL` WHERE `ID` = ?";
|
||||||
|
|
||||||
etherpadDB.query(sql, [padId], function(err, results)
|
etherpadDB.query(sql, [padId], function(err, results)
|
||||||
{
|
{
|
||||||
if(!err)
|
if(!err)
|
||||||
|
@ -226,7 +226,7 @@ function convertPad(padId, callback)
|
||||||
apool=JSON.parse(results[0].JSON).x;
|
apool=JSON.parse(results[0].JSON).x;
|
||||||
}catch(e) {err = e}
|
}catch(e) {err = e}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -234,10 +234,10 @@ function convertPad(padId, callback)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var sql = "SELECT * FROM `PAD_AUTHORS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_AUTHORS_META` WHERE ID=?)";
|
var sql = "SELECT * FROM `PAD_AUTHORS_TEXT` WHERE NUMID = (SELECT `NUMID` FROM `PAD_AUTHORS_META` WHERE ID=?)";
|
||||||
|
|
||||||
etherpadDB.query(sql, [padId], function(err, results)
|
etherpadDB.query(sql, [padId], function(err, results)
|
||||||
{
|
{
|
||||||
if(!err)
|
if(!err)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -248,7 +248,7 @@ function convertPad(padId, callback)
|
||||||
}
|
}
|
||||||
}catch(e) {err = e}
|
}catch(e) {err = e}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -256,17 +256,17 @@ function convertPad(padId, callback)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var sql = "SELECT JSON FROM `PAD_META` WHERE ID=?";
|
var sql = "SELECT JSON FROM `PAD_META` WHERE ID=?";
|
||||||
|
|
||||||
etherpadDB.query(sql, [padId], function(err, results)
|
etherpadDB.query(sql, [padId], function(err, results)
|
||||||
{
|
{
|
||||||
if(!err)
|
if(!err)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
padmeta = JSON.parse(results[0].JSON).x;
|
padmeta = JSON.parse(results[0].JSON).x;
|
||||||
}catch(e) {err = e}
|
}catch(e) {err = e}
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -279,19 +279,19 @@ function convertPad(padId, callback)
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the proID out of this padID
|
//get the proID out of this padID
|
||||||
var proID = padId.split("$")[0];
|
var proID = padId.split("$")[0];
|
||||||
|
|
||||||
var sql = "SELECT subDomain FROM pro_domains WHERE ID = ?";
|
var sql = "SELECT subDomain FROM pro_domains WHERE ID = ?";
|
||||||
|
|
||||||
etherpadDB.query(sql, [proID], function(err, results)
|
etherpadDB.query(sql, [proID], function(err, results)
|
||||||
{
|
{
|
||||||
if(!err)
|
if(!err)
|
||||||
{
|
{
|
||||||
subdomain = results[0].subDomain;
|
subdomain = results[0].subDomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(err);
|
callback(err);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -301,105 +301,105 @@ function convertPad(padId, callback)
|
||||||
{
|
{
|
||||||
//saves all values that should be written to the database
|
//saves all values that should be written to the database
|
||||||
var values = {};
|
var values = {};
|
||||||
|
|
||||||
//this is a pro pad, let's convert it to a group pad
|
//this is a pro pad, let's convert it to a group pad
|
||||||
if(padId.indexOf("$") != -1)
|
if(padId.indexOf("$") != -1)
|
||||||
{
|
{
|
||||||
var padIdParts = padId.split("$");
|
var padIdParts = padId.split("$");
|
||||||
var proID = padIdParts[0];
|
var proID = padIdParts[0];
|
||||||
var padName = padIdParts[1];
|
var padName = padIdParts[1];
|
||||||
|
|
||||||
var groupID
|
var groupID
|
||||||
|
|
||||||
//this proID is not converted so far, do it
|
//this proID is not converted so far, do it
|
||||||
if(proID2groupID[proID] == null)
|
if(proID2groupID[proID] == null)
|
||||||
{
|
{
|
||||||
groupID = "g." + randomString(16);
|
groupID = "g." + randomString(16);
|
||||||
|
|
||||||
//create the mappers for this new group
|
//create the mappers for this new group
|
||||||
proID2groupID[proID] = groupID;
|
proID2groupID[proID] = groupID;
|
||||||
proID2subdomain[proID] = subdomain;
|
proID2subdomain[proID] = subdomain;
|
||||||
groups[groupID] = {pads: {}};
|
groups[groupID] = {pads: {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
//use the generated groupID;
|
//use the generated groupID;
|
||||||
groupID = proID2groupID[proID];
|
groupID = proID2groupID[proID];
|
||||||
|
|
||||||
//rename the pad
|
//rename the pad
|
||||||
padId = groupID + "$" + padName;
|
padId = groupID + "$" + padName;
|
||||||
|
|
||||||
//set the value for this pad in the group
|
//set the value for this pad in the group
|
||||||
groups[groupID].pads[padId] = 1;
|
groups[groupID].pads[padId] = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var newAuthorIDs = {};
|
var newAuthorIDs = {};
|
||||||
var oldName2newName = {};
|
var oldName2newName = {};
|
||||||
|
|
||||||
//replace the authors with generated authors
|
//replace the authors with generated authors
|
||||||
// we need to do that cause etherpad saves pad local authors, etherpad lite uses them global
|
// we need to do that cause etherpad saves pad local authors, etherpad lite uses them global
|
||||||
for(var i in apool.numToAttrib)
|
for(var i in apool.numToAttrib)
|
||||||
{
|
{
|
||||||
var key = apool.numToAttrib[i][0];
|
var key = apool.numToAttrib[i][0];
|
||||||
var value = apool.numToAttrib[i][1];
|
var value = apool.numToAttrib[i][1];
|
||||||
|
|
||||||
//skip non authors and anonymous authors
|
//skip non authors and anonymous authors
|
||||||
if(key != "author" || value == "")
|
if(key != "author" || value == "")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//generate new author values
|
//generate new author values
|
||||||
var authorID = "a." + randomString(16);
|
var authorID = "a." + randomString(16);
|
||||||
var authorColorID = authors[i].colorId || Math.floor(Math.random()*32);
|
var authorColorID = authors[i].colorId || Math.floor(Math.random()*32);
|
||||||
var authorName = authors[i].name || null;
|
var authorName = authors[i].name || null;
|
||||||
|
|
||||||
//overwrite the authorID of the attribute pool
|
//overwrite the authorID of the attribute pool
|
||||||
apool.numToAttrib[i][1] = authorID;
|
apool.numToAttrib[i][1] = authorID;
|
||||||
|
|
||||||
//write the author to the database
|
//write the author to the database
|
||||||
values["globalAuthor:" + authorID] = {"colorId" : authorColorID, "name": authorName, "timestamp": timestamp};
|
values["globalAuthor:" + authorID] = {"colorId" : authorColorID, "name": authorName, "timestamp": timestamp};
|
||||||
|
|
||||||
//save in mappers
|
//save in mappers
|
||||||
newAuthorIDs[i] = authorID;
|
newAuthorIDs[i] = authorID;
|
||||||
oldName2newName[value] = authorID;
|
oldName2newName[value] = authorID;
|
||||||
}
|
}
|
||||||
|
|
||||||
//save all revisions
|
//save all revisions
|
||||||
for(var i=0;i<changesets.length;i++)
|
for(var i=0;i<changesets.length;i++)
|
||||||
{
|
{
|
||||||
values["pad:" + padId + ":revs:" + i] = {changeset: changesets[i],
|
values["pad:" + padId + ":revs:" + i] = {changeset: changesets[i],
|
||||||
meta : {
|
meta : {
|
||||||
author: newAuthorIDs[changesetsMeta[i].a],
|
author: newAuthorIDs[changesetsMeta[i].a],
|
||||||
timestamp: changesetsMeta[i].t,
|
timestamp: changesetsMeta[i].t,
|
||||||
atext: changesetsMeta[i].atext || undefined
|
atext: changesetsMeta[i].atext || undefined
|
||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
//save all chat messages
|
//save all chat messages
|
||||||
for(var i=0;i<chatMessages.length;i++)
|
for(var i=0;i<chatMessages.length;i++)
|
||||||
{
|
{
|
||||||
values["pad:" + padId + ":chat:" + i] = {"text": chatMessages[i].lineText,
|
values["pad:" + padId + ":chat:" + i] = {"text": chatMessages[i].lineText,
|
||||||
"userId": oldName2newName[chatMessages[i].userId],
|
"userId": oldName2newName[chatMessages[i].userId],
|
||||||
"time": chatMessages[i].time}
|
"time": chatMessages[i].time}
|
||||||
}
|
}
|
||||||
|
|
||||||
//generate the latest atext
|
//generate the latest atext
|
||||||
var fullAPool = (new AttributePool()).fromJsonable(apool);
|
var fullAPool = (new AttributePool()).fromJsonable(apool);
|
||||||
var keyRev = Math.floor(padmeta.head / padmeta.keyRevInterval) * padmeta.keyRevInterval;
|
var keyRev = Math.floor(padmeta.head / padmeta.keyRevInterval) * padmeta.keyRevInterval;
|
||||||
var atext = changesetsMeta[keyRev].atext;
|
var atext = changesetsMeta[keyRev].atext;
|
||||||
var curRev = keyRev;
|
var curRev = keyRev;
|
||||||
while (curRev < padmeta.head)
|
while (curRev < padmeta.head)
|
||||||
{
|
{
|
||||||
curRev++;
|
curRev++;
|
||||||
var changeset = changesets[curRev];
|
var changeset = changesets[curRev];
|
||||||
atext = Changeset.applyToAText(changeset, atext, fullAPool);
|
atext = Changeset.applyToAText(changeset, atext, fullAPool);
|
||||||
}
|
}
|
||||||
|
|
||||||
values["pad:" + padId] = {atext: atext,
|
values["pad:" + padId] = {atext: atext,
|
||||||
pool: apool,
|
pool: apool,
|
||||||
head: padmeta.head,
|
head: padmeta.head,
|
||||||
chatHead: padmeta.numChatMessages }
|
chatHead: padmeta.numChatMessages }
|
||||||
|
|
||||||
}
|
}
|
||||||
catch(e)
|
catch(e)
|
||||||
{
|
{
|
||||||
|
@ -408,13 +408,13 @@ function convertPad(padId, callback)
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sql = "";
|
var sql = "";
|
||||||
for(var key in values)
|
for(var key in values)
|
||||||
{
|
{
|
||||||
sql+="REPLACE INTO store VALUES (" + etherpadDB.escape(key) + ", " + etherpadDB.escape(JSON.stringify(values[key]))+ ");\n";
|
sql+="REPLACE INTO store VALUES (" + etherpadDB.escape(key) + ", " + etherpadDB.escape(JSON.stringify(values[key]))+ ");\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.writeSync(sqlOutput, sql, undefined, "utf-8");
|
fs.writeSync(sqlOutput, sql, undefined, "utf-8");
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
@ -430,24 +430,24 @@ function parsePage(array, pageStart, offsets, data, json)
|
||||||
{
|
{
|
||||||
var start = 0;
|
var start = 0;
|
||||||
var lengths = offsets.split(",");
|
var lengths = offsets.split(",");
|
||||||
|
|
||||||
for(var i=0;i<lengths.length;i++)
|
for(var i=0;i<lengths.length;i++)
|
||||||
{
|
{
|
||||||
var unitLength = lengths[i];
|
var unitLength = lengths[i];
|
||||||
|
|
||||||
//skip empty units
|
//skip empty units
|
||||||
if(unitLength == "")
|
if(unitLength == "")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
//parse the number
|
//parse the number
|
||||||
unitLength = Number(unitLength);
|
unitLength = Number(unitLength);
|
||||||
|
|
||||||
//cut the unit out of data
|
//cut the unit out of data
|
||||||
var unit = data.substr(start, unitLength);
|
var unit = data.substr(start, unitLength);
|
||||||
|
|
||||||
//put it into the array
|
//put it into the array
|
||||||
array[pageStart + i] = json ? JSON.parse(unit) : unit;
|
array[pageStart + i] = json ? JSON.parse(unit) : unit;
|
||||||
|
|
||||||
//update start
|
//update start
|
||||||
start+=unitLength;
|
start+=unitLength;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
{
|
{
|
||||||
"etherpadDB":
|
"etherpadDB":
|
||||||
{
|
{
|
||||||
"host": "localhost",
|
"host": "localhost",
|
||||||
"port": 3306,
|
"port": 3306,
|
||||||
|
|
|
@ -11,11 +11,11 @@ fi
|
||||||
#prepare the enviroment
|
#prepare the enviroment
|
||||||
bin/installDeps.sh || exit 1
|
bin/installDeps.sh || exit 1
|
||||||
|
|
||||||
hash node-inspector > /dev/null 2>&1 || {
|
hash node-inspector > /dev/null 2>&1 || {
|
||||||
echo "You need to install node-inspector to run the tests!" >&2
|
echo "You need to install node-inspector to run the tests!" >&2
|
||||||
echo "You can install it with npm" >&2
|
echo "You can install it with npm" >&2
|
||||||
echo "Run: npm install -g node-inspector" >&2
|
echo "Run: npm install -g node-inspector" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
node-inspector &
|
node-inspector &
|
||||||
|
@ -24,5 +24,5 @@ echo "If you are new to node-inspector, take a look at this video: http://youtu.
|
||||||
|
|
||||||
node --debug node_modules/ep_etherpad-lite/node/server.js $*
|
node --debug node_modules/ep_etherpad-lite/node/server.js $*
|
||||||
|
|
||||||
#kill node-inspector before ending
|
#kill node-inspector before ending
|
||||||
kill $!
|
kill $!
|
||||||
|
|
|
@ -16,7 +16,7 @@ log4js.setGlobalLogLevel("INFO");
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
var db = require('../node/db/DB');
|
var db = require('../node/db/DB');
|
||||||
var dirty = require("dirty")(padId + ".db");
|
var dirty = require("dirty")(padId + ".db");
|
||||||
var padManager;
|
var padManager;
|
||||||
var pad;
|
var pad;
|
||||||
var neededDBValues = ["pad:"+padId];
|
var neededDBValues = ["pad:"+padId];
|
||||||
|
|
||||||
|
@ -26,12 +26,12 @@ async.series([
|
||||||
{
|
{
|
||||||
db.init(callback);
|
db.init(callback);
|
||||||
},
|
},
|
||||||
//get the pad
|
//get the pad
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
padManager = require('../node/db/PadManager');
|
padManager = require('../node/db/PadManager');
|
||||||
|
|
||||||
padManager.getPad(padId, function(err, _pad)
|
padManager.getPad(padId, function(err, _pad)
|
||||||
{
|
{
|
||||||
pad = _pad;
|
pad = _pad;
|
||||||
callback(err);
|
callback(err);
|
||||||
|
@ -45,21 +45,21 @@ async.series([
|
||||||
{
|
{
|
||||||
neededDBValues.push("globalAuthor:" + authors[i]);
|
neededDBValues.push("globalAuthor:" + authors[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//add all revisions
|
//add all revisions
|
||||||
var revHead = pad.head;
|
var revHead = pad.head;
|
||||||
for(var i=0;i<=revHead;i++)
|
for(var i=0;i<=revHead;i++)
|
||||||
{
|
{
|
||||||
neededDBValues.push("pad:"+padId+":revs:" + i);
|
neededDBValues.push("pad:"+padId+":revs:" + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//get all chat values
|
//get all chat values
|
||||||
var chatHead = pad.chatHead;
|
var chatHead = pad.chatHead;
|
||||||
for(var i=0;i<=chatHead;i++)
|
for(var i=0;i<=chatHead;i++)
|
||||||
{
|
{
|
||||||
neededDBValues.push("pad:"+padId+":chat:" + i);
|
neededDBValues.push("pad:"+padId+":chat:" + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//get and set all values
|
//get and set all values
|
||||||
async.forEach(neededDBValues, function(dbkey, callback)
|
async.forEach(neededDBValues, function(dbkey, callback)
|
||||||
{
|
{
|
||||||
|
@ -67,7 +67,7 @@ async.series([
|
||||||
{
|
{
|
||||||
if(err) { callback(err); return}
|
if(err) { callback(err); return}
|
||||||
dbvalue=JSON.parse(dbvalue);
|
dbvalue=JSON.parse(dbvalue);
|
||||||
|
|
||||||
dirty.set(dbkey, dbvalue, callback);
|
dirty.set(dbkey, dbvalue, callback);
|
||||||
});
|
});
|
||||||
}, callback);
|
}, callback);
|
||||||
|
@ -75,8 +75,8 @@ async.series([
|
||||||
], function (err)
|
], function (err)
|
||||||
{
|
{
|
||||||
if(err) throw err;
|
if(err) throw err;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
console.log("finished");
|
console.log("finished");
|
||||||
process.exit();
|
process.exit();
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,35 +10,35 @@ fi
|
||||||
|
|
||||||
#Is gnu-grep (ggrep) installed on SunOS (Solaris)
|
#Is gnu-grep (ggrep) installed on SunOS (Solaris)
|
||||||
if [ $(uname) = "SunOS" ]; then
|
if [ $(uname) = "SunOS" ]; then
|
||||||
hash ggrep > /dev/null 2>&1 || {
|
hash ggrep > /dev/null 2>&1 || {
|
||||||
echo "Please install ggrep (pkg install gnu-grep)" >&2
|
echo "Please install ggrep (pkg install gnu-grep)" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#Is wget installed?
|
#Is wget installed?
|
||||||
hash curl > /dev/null 2>&1 || {
|
hash curl > /dev/null 2>&1 || {
|
||||||
echo "Please install curl" >&2
|
echo "Please install curl" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#Is node installed?
|
#Is node installed?
|
||||||
hash node > /dev/null 2>&1 || {
|
hash node > /dev/null 2>&1 || {
|
||||||
echo "Please install node.js ( http://nodejs.org )" >&2
|
echo "Please install node.js ( http://nodejs.org )" >&2
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#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
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
#check npm version
|
#check npm version
|
||||||
NPM_VERSION=$(npm --version)
|
NPM_VERSION=$(npm --version)
|
||||||
if [ ! $(echo $NPM_VERSION | cut -d "." -f 1) = "1" ]; then
|
if [ ! $(echo $NPM_VERSION | cut -d "." -f 1) = "1" ]; then
|
||||||
echo "You're running a wrong version of npm, you're using $NPM_VERSION, we need 1.x" >&2
|
echo "You're running a wrong version of npm, you're using $NPM_VERSION, we need 1.x" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#check node version
|
#check node version
|
||||||
|
@ -46,7 +46,7 @@ NODE_VERSION=$(node --version)
|
||||||
NODE_V_MINOR=$(echo $NODE_VERSION | cut -d "." -f 1-2)
|
NODE_V_MINOR=$(echo $NODE_VERSION | cut -d "." -f 1-2)
|
||||||
if [ ! $NODE_V_MINOR = "v0.8" ] && [ ! $NODE_V_MINOR = "v0.6" ]; then
|
if [ ! $NODE_V_MINOR = "v0.8" ] && [ ! $NODE_V_MINOR = "v0.6" ]; then
|
||||||
echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.6.x or v0.8.x" >&2
|
echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.6.x or v0.8.x" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#Get the name of the settings file
|
#Get the name of the settings file
|
||||||
|
@ -70,9 +70,9 @@ echo "Ensure that all dependencies are up to date..."
|
||||||
[ -e ep_etherpad-lite ] || ln -s ../src ep_etherpad-lite
|
[ -e ep_etherpad-lite ] || ln -s ../src ep_etherpad-lite
|
||||||
cd ep_etherpad-lite
|
cd ep_etherpad-lite
|
||||||
npm install
|
npm install
|
||||||
) || {
|
) || {
|
||||||
rm -rf node_modules
|
rm -rf node_modules
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
echo "Ensure jQuery is downloaded and up to date..."
|
echo "Ensure jQuery is downloaded and up to date..."
|
||||||
|
@ -105,7 +105,7 @@ do
|
||||||
if [ ! -f "src/static/custom/$f.js" ]; then
|
if [ ! -f "src/static/custom/$f.js" ]; then
|
||||||
cp "src/static/custom/js.template" "src/static/custom/$f.js" || exit 1
|
cp "src/static/custom/js.template" "src/static/custom/$f.js" || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f "src/static/custom/$f.css" ]; then
|
if [ ! -f "src/static/custom/$f.css" ]; then
|
||||||
cp "src/static/custom/css.template" "src/static/custom/$f.css" || exit 1
|
cp "src/static/custom/css.template" "src/static/custom/$f.css" || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
This load tester is extremely useful for testing how many dormant clients can connect to etherpad lite.
|
This load tester is extremely useful for testing how many dormant clients can connect to etherpad lite.
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
Emulate characters being typed into a pad
|
Emulate characters being typed into a pad
|
||||||
|
@ -14,7 +14,7 @@ Installed Xvfb and PhantomJS
|
||||||
I installed Xvfb following (roughly) this guide: http://blog.martin-lyness.com/archives/installing-xvfb-on-ubuntu-9-10-karmic-koala
|
I installed Xvfb following (roughly) this guide: http://blog.martin-lyness.com/archives/installing-xvfb-on-ubuntu-9-10-karmic-koala
|
||||||
|
|
||||||
#sudo apt-get install xvfb
|
#sudo apt-get install xvfb
|
||||||
#sudo apt-get install xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic
|
#sudo apt-get install xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic
|
||||||
|
|
||||||
Launched two instances of Xvfb directly from the terminal:
|
Launched two instances of Xvfb directly from the terminal:
|
||||||
|
|
||||||
|
@ -58,15 +58,15 @@ And finally a launcher script that uses screen to run 400 instances of PhantomJS
|
||||||
|
|
||||||
### BEGIN SHELL SCRIPT ###
|
### BEGIN SHELL SCRIPT ###
|
||||||
|
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
# connect 200 instances to display :0
|
# connect 200 instances to display :0
|
||||||
for i in {1..200}
|
for i in {1..200}
|
||||||
do
|
do
|
||||||
DISPLAY=:0 screen -d -m phantomjs loader.js http://ec2-50-17-168-xx.compute-1.amazonaws.com:9001/p/pad2 && sleep 2
|
DISPLAY=:0 screen -d -m phantomjs loader.js http://ec2-50-17-168-xx.compute-1.amazonaws.com:9001/p/pad2 && sleep 2
|
||||||
done
|
done
|
||||||
|
|
||||||
# connect 200 instances to display :1
|
# connect 200 instances to display :1
|
||||||
for i in {1..200}
|
for i in {1..200}
|
||||||
do
|
do
|
||||||
DISPLAY=:1 screen -d -m phantomjs loader.js http://ec2-50-17-168-xx.compute-1.amazonaws.com:9001/p/pad2 && sleep 2
|
DISPLAY=:1 screen -d -m phantomjs loader.js http://ec2-50-17-168-xx.compute-1.amazonaws.com:9001/p/pad2 && sleep 2
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
ERROR_HANDLING=0
|
ERROR_HANDLING=0
|
||||||
# Your email address which should recieve the error messages
|
# Your email address which should recieve the error messages
|
||||||
EMAIL_ADDRESS="no-reply@example.com"
|
EMAIL_ADDRESS="no-reply@example.com"
|
||||||
# Sets the minimun amount of time betweens the sending of error emails.
|
# Sets the minimun amount of time betweens the sending of error emails.
|
||||||
# This ensures you not get spamed while a endless reboot loop
|
# This ensures you not get spamed while a endless reboot loop
|
||||||
# It's the time in seconds
|
# It's the time in seconds
|
||||||
TIME_BETWEEN_EMAILS=600 # 10 minutes
|
TIME_BETWEEN_EMAILS=600 # 10 minutes
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ do
|
||||||
if [ ! -f $1 ]; then
|
if [ ! -f $1 ]; then
|
||||||
touch $1 || ( echo "Logfile '$1' is not writeable" && exit 1 )
|
touch $1 || ( echo "Logfile '$1' is not writeable" && exit 1 )
|
||||||
fi
|
fi
|
||||||
|
|
||||||
#check if the file is writeable
|
#check if the file is writeable
|
||||||
if [ ! -w $1 ]; then
|
if [ ! -w $1 ]; then
|
||||||
echo "Logfile '$1' is not writeable"
|
echo "Logfile '$1' is not writeable"
|
||||||
|
@ -46,21 +46,21 @@ do
|
||||||
|
|
||||||
#start the application
|
#start the application
|
||||||
bin/run.sh >>$1 2>>$1
|
bin/run.sh >>$1 2>>$1
|
||||||
|
|
||||||
#Send email
|
#Send email
|
||||||
if [ $ERROR_HANDLING = 1 ]; then
|
if [ $ERROR_HANDLING = 1 ]; then
|
||||||
TIME_NOW=$(date +%s)
|
TIME_NOW=$(date +%s)
|
||||||
TIME_SINCE_LAST_SEND=$(($TIME_NOW - $LAST_EMAIL_SEND))
|
TIME_SINCE_LAST_SEND=$(($TIME_NOW - $LAST_EMAIL_SEND))
|
||||||
|
|
||||||
if [ $TIME_SINCE_LAST_SEND -gt $TIME_BETWEEN_EMAILS ]; then
|
if [ $TIME_SINCE_LAST_SEND -gt $TIME_BETWEEN_EMAILS ]; then
|
||||||
printf "Server was restared at: $(date)\nThe last 50 lines of the log before the error happens:\n $(tail -n 50 $1)" | mail -s "Pad Server was restarted" $EMAIL_ADDRESS
|
printf "Server was restared at: $(date)\nThe last 50 lines of the log before the error happens:\n $(tail -n 50 $1)" | mail -s "Pad Server was restarted" $EMAIL_ADDRESS
|
||||||
|
|
||||||
LAST_EMAIL_SEND=$TIME_NOW
|
LAST_EMAIL_SEND=$TIME_NOW
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "RESTART!" >>$1
|
echo "RESTART!" >>$1
|
||||||
|
|
||||||
#Sleep 10 seconds before restart
|
#Sleep 10 seconds before restart
|
||||||
sleep 10
|
sleep 10
|
||||||
done
|
done
|
||||||
|
|
|
@ -70,11 +70,11 @@ This creates an empty apool. A apool saves which attributes were used during the
|
||||||
```
|
```
|
||||||
> apool.fromJsonable({"numToAttrib":{"0":["author","a.kVnWeomPADAT2pn9"],"1":["bold","true"],"2":["italic","true"]},"nextNum":3});
|
> apool.fromJsonable({"numToAttrib":{"0":["author","a.kVnWeomPADAT2pn9"],"1":["bold","true"],"2":["italic","true"]},"nextNum":3});
|
||||||
> console.log(apool)
|
> console.log(apool)
|
||||||
{ numToAttrib:
|
{ numToAttrib:
|
||||||
{ '0': [ 'author', 'a.kVnWeomPADAT2pn9' ],
|
{ '0': [ 'author', 'a.kVnWeomPADAT2pn9' ],
|
||||||
'1': [ 'bold', 'true' ],
|
'1': [ 'bold', 'true' ],
|
||||||
'2': [ 'italic', 'true' ] },
|
'2': [ 'italic', 'true' ] },
|
||||||
attribToNum:
|
attribToNum:
|
||||||
{ 'author,a.kVnWeomPADAT2pn9': 0,
|
{ 'author,a.kVnWeomPADAT2pn9': 0,
|
||||||
'bold,true': 1,
|
'bold,true': 1,
|
||||||
'italic,true': 2 },
|
'italic,true': 2 },
|
||||||
|
|
|
@ -175,7 +175,7 @@ This hook gets called every time the client receives a message of type `name`. T
|
||||||
|
|
||||||
`collab_client.js` has a pretty extensive list of message types, if you want to take a look.
|
`collab_client.js` has a pretty extensive list of message types, if you want to take a look.
|
||||||
|
|
||||||
##aceStartLineAndCharForPoint-aceEndLineAndCharForPoint
|
##aceStartLineAndCharForPoint-aceEndLineAndCharForPoint
|
||||||
Called from: src/static/js/ace2_inner.js
|
Called from: src/static/js/ace2_inner.js
|
||||||
|
|
||||||
Things in context:
|
Things in context:
|
||||||
|
@ -190,7 +190,7 @@ Things in context:
|
||||||
This hook is provided to allow a plugin to turn DOM node selection into [line,char] selection.
|
This hook is provided to allow a plugin to turn DOM node selection into [line,char] selection.
|
||||||
The return value should be an array of [line,char]
|
The return value should be an array of [line,char]
|
||||||
|
|
||||||
##aceKeyEvent
|
##aceKeyEvent
|
||||||
Called from: src/static/js/ace2_inner.js
|
Called from: src/static/js/ace2_inner.js
|
||||||
|
|
||||||
Things in context:
|
Things in context:
|
||||||
|
@ -204,7 +204,7 @@ Things in context:
|
||||||
This hook is provided to allow a plugin to handle key events.
|
This hook is provided to allow a plugin to handle key events.
|
||||||
The return value should be true if you have handled the event.
|
The return value should be true if you have handled the event.
|
||||||
|
|
||||||
##collectContentLineText
|
##collectContentLineText
|
||||||
Called from: src/static/js/contentcollector.js
|
Called from: src/static/js/contentcollector.js
|
||||||
|
|
||||||
Things in context:
|
Things in context:
|
||||||
|
@ -217,7 +217,7 @@ Things in context:
|
||||||
This hook allows you to validate/manipulate the text before it's sent to the server side.
|
This hook allows you to validate/manipulate the text before it's sent to the server side.
|
||||||
The return value should be the validated/manipulated text.
|
The return value should be the validated/manipulated text.
|
||||||
|
|
||||||
##collectContentLineBreak
|
##collectContentLineBreak
|
||||||
Called from: src/static/js/contentcollector.js
|
Called from: src/static/js/contentcollector.js
|
||||||
|
|
||||||
Things in context:
|
Things in context:
|
||||||
|
@ -229,7 +229,7 @@ Things in context:
|
||||||
This hook is provided to allow whether the br tag should induce a new magic domline or not.
|
This hook is provided to allow whether the br tag should induce a new magic domline or not.
|
||||||
The return value should be either true(break the line) or false.
|
The return value should be either true(break the line) or false.
|
||||||
|
|
||||||
##disableAuthorColorsForThisLine
|
##disableAuthorColorsForThisLine
|
||||||
Called from: src/static/js/linestylefilter.js
|
Called from: src/static/js/linestylefilter.js
|
||||||
|
|
||||||
Things in context:
|
Things in context:
|
||||||
|
|
|
@ -3,7 +3,7 @@
|
||||||
## What can I do with this API?
|
## What can I do with this API?
|
||||||
The API gives another web application control of the pads. The basic functions are
|
The API gives another web application control of the pads. The basic functions are
|
||||||
|
|
||||||
* create/delete pads
|
* create/delete pads
|
||||||
* grant/forbid access to pads
|
* grant/forbid access to pads
|
||||||
* get/set pad content
|
* get/set pad content
|
||||||
|
|
||||||
|
@ -15,30 +15,30 @@ Take a look at [HTTP API client libraries](https://github.com/Pita/etherpad-lite
|
||||||
|
|
||||||
### Example 1
|
### Example 1
|
||||||
|
|
||||||
A portal (such as WordPress) wants to give a user access to a new pad. Let's assume the user have the internal id 7 and his name is michael.
|
A portal (such as WordPress) wants to give a user access to a new pad. Let's assume the user have the internal id 7 and his name is michael.
|
||||||
|
|
||||||
Portal maps the internal userid to an etherpad author.
|
Portal maps the internal userid to an etherpad author.
|
||||||
|
|
||||||
> Request: `http://pad.domain/api/1/createAuthorIfNotExistsFor?apikey=secret&name=Michael&authorMapper=7`
|
> Request: `http://pad.domain/api/1/createAuthorIfNotExistsFor?apikey=secret&name=Michael&authorMapper=7`
|
||||||
>
|
>
|
||||||
> Response: `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}`
|
> Response: `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}`
|
||||||
|
|
||||||
Portal maps the internal userid to an etherpad group:
|
Portal maps the internal userid to an etherpad group:
|
||||||
|
|
||||||
> Request: `http://pad.domain/api/1/createGroupIfNotExistsFor?apikey=secret&groupMapper=7`
|
> Request: `http://pad.domain/api/1/createGroupIfNotExistsFor?apikey=secret&groupMapper=7`
|
||||||
>
|
>
|
||||||
> Response: `{code: 0, message:"ok", data: {groupID: "g.s8oes9dhwrvt0zif"}}`
|
> Response: `{code: 0, message:"ok", data: {groupID: "g.s8oes9dhwrvt0zif"}}`
|
||||||
|
|
||||||
Portal creates a pad in the userGroup
|
Portal creates a pad in the userGroup
|
||||||
|
|
||||||
> Request: `http://pad.domain/api/1/createGroupPad?apikey=secret&groupID=g.s8oes9dhwrvt0zif&padName=samplePad&text=This is the first sentence in the pad`
|
> Request: `http://pad.domain/api/1/createGroupPad?apikey=secret&groupID=g.s8oes9dhwrvt0zif&padName=samplePad&text=This is the first sentence in the pad`
|
||||||
>
|
>
|
||||||
> Response: `{code: 0, message:"ok", data: null}`
|
> Response: `{code: 0, message:"ok", data: null}`
|
||||||
|
|
||||||
Portal starts the session for the user on the group:
|
Portal starts the session for the user on the group:
|
||||||
|
|
||||||
> Request: `http://pad.domain/api/1/createSession?apikey=secret&groupID=g.s8oes9dhwrvt0zif&authorID=a.s8oes9dhwrvt0zif&validUntil=1312201246`
|
> Request: `http://pad.domain/api/1/createSession?apikey=secret&groupID=g.s8oes9dhwrvt0zif&authorID=a.s8oes9dhwrvt0zif&validUntil=1312201246`
|
||||||
>
|
>
|
||||||
> Response: `{"data":{"sessionID": "s.s8oes9dhwrvt0zif"}}`
|
> Response: `{"data":{"sessionID": "s.s8oes9dhwrvt0zif"}}`
|
||||||
|
|
||||||
Portal places the cookie "sessionID" with the given value on the client and creates an iframe including the pad.
|
Portal places the cookie "sessionID" with the given value on the client and creates an iframe including the pad.
|
||||||
|
@ -50,7 +50,7 @@ A portal (such as WordPress) wants to transform the contents of a pad that multi
|
||||||
Portal retrieves the contents of the pad for entry into the db as a blog post:
|
Portal retrieves the contents of the pad for entry into the db as a blog post:
|
||||||
|
|
||||||
> Request: `http://pad.domain/api/1/getText?apikey=secret&padID=g.s8oes9dhwrvt0zif$123`
|
> Request: `http://pad.domain/api/1/getText?apikey=secret&padID=g.s8oes9dhwrvt0zif$123`
|
||||||
>
|
>
|
||||||
> Response: `{code: 0, message:"ok", data: {text:"Welcome Text"}}`
|
> Response: `{code: 0, message:"ok", data: {text:"Welcome Text"}}`
|
||||||
|
|
||||||
Portal submits content into new blog post
|
Portal submits content into new blog post
|
||||||
|
@ -98,7 +98,7 @@ Responses are valid JSON in the following format:
|
||||||
|
|
||||||
### Authentication
|
### Authentication
|
||||||
|
|
||||||
Authentication works via a token that is sent with each request as a post parameter. There is a single token per Etherpad-Lite deployment. This token will be random string, generated by Etherpad-Lite at the first start. It will be saved in APIKEY.txt in the root folder of Etherpad Lite. Only Etherpad Lite and the requesting application knows this key. Token management will not be exposed through this API.
|
Authentication works via a token that is sent with each request as a post parameter. There is a single token per Etherpad-Lite deployment. This token will be random string, generated by Etherpad-Lite at the first start. It will be saved in APIKEY.txt in the root folder of Etherpad Lite. Only Etherpad Lite and the requesting application knows this key. Token management will not be exposed through this API.
|
||||||
|
|
||||||
### Node Interoperability
|
### Node Interoperability
|
||||||
|
|
||||||
|
@ -118,7 +118,7 @@ Pads can belong to a group. The padID of grouppads is starting with a groupID li
|
||||||
|
|
||||||
#### createGroup()
|
#### createGroup()
|
||||||
* API >= 1
|
* API >= 1
|
||||||
|
|
||||||
creates a new group
|
creates a new group
|
||||||
|
|
||||||
*Example returns:*
|
*Example returns:*
|
||||||
|
@ -127,7 +127,7 @@ creates a new group
|
||||||
#### createGroupIfNotExistsFor(groupMapper)
|
#### createGroupIfNotExistsFor(groupMapper)
|
||||||
* API >= 1
|
* API >= 1
|
||||||
|
|
||||||
this functions helps you to map your application group ids to etherpad lite group ids
|
this functions helps you to map your application group ids to etherpad lite group ids
|
||||||
|
|
||||||
*Example returns:*
|
*Example returns:*
|
||||||
* `{code: 0, message:"ok", data: {groupID: g.s8oes9dhwrvt0zif}}`
|
* `{code: 0, message:"ok", data: {groupID: g.s8oes9dhwrvt0zif}}`
|
||||||
|
@ -170,7 +170,7 @@ lists all existing groups
|
||||||
* `{code: 0, message:"ok", data: {groupIDs: []}}`
|
* `{code: 0, message:"ok", data: {groupIDs: []}}`
|
||||||
|
|
||||||
### Author
|
### Author
|
||||||
These authors are bound to the attributes the users choose (color and name).
|
These authors are bound to the attributes the users choose (color and name).
|
||||||
|
|
||||||
#### createAuthor([name])
|
#### createAuthor([name])
|
||||||
* API >= 1
|
* API >= 1
|
||||||
|
@ -183,7 +183,7 @@ creates a new author
|
||||||
#### createAuthorIfNotExistsFor(authorMapper [, name])
|
#### createAuthorIfNotExistsFor(authorMapper [, name])
|
||||||
* API >= 1
|
* API >= 1
|
||||||
|
|
||||||
this functions helps you to map your application author ids to etherpad lite author ids
|
this functions helps you to map your application author ids to etherpad lite author ids
|
||||||
|
|
||||||
*Example returns:*
|
*Example returns:*
|
||||||
* `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}`
|
* `{code: 0, message:"ok", data: {authorID: "a.s8oes9dhwrvt0zif"}}`
|
||||||
|
@ -290,7 +290,7 @@ returns the text of a pad formatted as HTML
|
||||||
* `{code: 1, message:"padID does not exist", data: null}`
|
* `{code: 1, message:"padID does not exist", data: null}`
|
||||||
|
|
||||||
### Pad
|
### Pad
|
||||||
Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security manager controls access of them and its forbidden for normal pads to include a $ in the name.
|
Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security manager controls access of them and its forbidden for normal pads to include a $ in the name.
|
||||||
|
|
||||||
#### createPad(padID [, text])
|
#### createPad(padID [, text])
|
||||||
* API >= 1
|
* API >= 1
|
||||||
|
@ -398,7 +398,7 @@ returns the timestamp of the last revision of the pad
|
||||||
*Example returns:*
|
*Example returns:*
|
||||||
* `{code: 0, message:"ok", data: {lastEdited: 1340815946602}}`
|
* `{code: 0, message:"ok", data: {lastEdited: 1340815946602}}`
|
||||||
* `{code: 1, message:"padID does not exist", data: null}`
|
* `{code: 1, message:"padID does not exist", data: null}`
|
||||||
|
|
||||||
#### sendClientsMessage(padID, msg)
|
#### sendClientsMessage(padID, msg)
|
||||||
* API >= 1.1
|
* API >= 1.1
|
||||||
|
|
||||||
|
|
|
@ -43,9 +43,9 @@ Information about an author
|
||||||
* **colorID** - the colorID of this author as shown in the pad
|
* **colorID** - the colorID of this author as shown in the pad
|
||||||
|
|
||||||
### mapper2group:$MAPPER
|
### mapper2group:$MAPPER
|
||||||
Maps an external application identifier to an internal group
|
Maps an external application identifier to an internal group
|
||||||
### mapper2author:$MAPPER
|
### mapper2author:$MAPPER
|
||||||
Maps an external application identifier to an internal author
|
Maps an external application identifier to an internal author
|
||||||
### group:$GROUPID
|
### group:$GROUPID
|
||||||
a group of pads
|
a group of pads
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
\documentclass{article}
|
\documentclass{article}
|
||||||
\usepackage{hyperref}
|
\usepackage{hyperref}
|
||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
|
@ -258,7 +258,7 @@ in Section \ref{follows}.
|
||||||
\paragraph{Proof that $\mathbf{AXY=V \Rightarrow A'X'Y'=VD}$.}
|
\paragraph{Proof that $\mathbf{AXY=V \Rightarrow A'X'Y'=VD}$.}
|
||||||
Substituting $A'X'Y'=(AB)(f(B,X))(f(f(X,B),Y))$, we
|
Substituting $A'X'Y'=(AB)(f(B,X))(f(f(X,B),Y))$, we
|
||||||
recall that merges are commutative. So for any two
|
recall that merges are commutative. So for any two
|
||||||
changesets $P$ and $Q$,
|
changesets $P$ and $Q$,
|
||||||
$$m(P,Q)=m(Q,P)=Qf(Q,P)=Pf(P,Q)$$
|
$$m(P,Q)=m(Q,P)=Qf(Q,P)=Pf(P,Q)$$
|
||||||
|
|
||||||
Applying this to the relation above, we see
|
Applying this to the relation above, we see
|
||||||
|
@ -267,7 +267,7 @@ A'X'Y'&=& AB f(B,X) f(f(X,B),Y) \\
|
||||||
&=&AX f(X,B) f(f(X,B),Y) \\
|
&=&AX f(X,B) f(f(X,B),Y) \\
|
||||||
&=&A X Y f(Y, f(X,B)) \\
|
&=&A X Y f(Y, f(X,B)) \\
|
||||||
&=&A X Y D \\
|
&=&A X Y D \\
|
||||||
&=&V D
|
&=&V D
|
||||||
\end{eqnarray*}
|
\end{eqnarray*}
|
||||||
As claimed.
|
As claimed.
|
||||||
|
|
||||||
|
@ -348,7 +348,7 @@ the client's changeset $C$, it does five things:
|
||||||
server's most recent revision number, which we call
|
server's most recent revision number, which we call
|
||||||
$r_H$ ($H$ for HEAD). $C'$ can be computed using
|
$r_H$ ($H$ for HEAD). $C'$ can be computed using
|
||||||
follows (Section \ref{follows}). Remember that the server has a series of
|
follows (Section \ref{follows}). Remember that the server has a series of
|
||||||
changesets,
|
changesets,
|
||||||
$$S_0\rightarrow S_1\rightarrow \ldots S_{r_c}\rightarrow S_{r_c+1} \rightarrow \ldots \rightarrow S_{r_H} $$
|
$$S_0\rightarrow S_1\rightarrow \ldots S_{r_c}\rightarrow S_{r_c+1} \rightarrow \ldots \rightarrow S_{r_H} $$
|
||||||
$C$ is relative to $S_{r_c}$, but we need to compute $C'$ relative to $S_{r_H}$.
|
$C$ is relative to $S_{r_c}$, but we need to compute $C'$ relative to $S_{r_H}$.
|
||||||
We can compute a new $C$ relative to $S_{r_c+1}$ by computing $f(S_{r_c+1},C)$. Similarly we can repeat for
|
We can compute a new $C$ relative to $S_{r_c+1}$ by computing $f(S_{r_c+1},C)$. Similarly we can repeat for
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
\documentclass[12pt]{article}
|
\documentclass[12pt]{article}
|
||||||
|
|
||||||
\usepackage[T1]{fontenc}
|
\usepackage[T1]{fontenc}
|
||||||
\usepackage[USenglish]{babel}
|
\usepackage[USenglish]{babel}
|
||||||
|
|
||||||
|
|
||||||
\begin{document}
|
\begin{document}
|
||||||
|
@ -68,7 +68,7 @@ Here are descriptions of the operations, where capital
|
||||||
letters are variables:
|
letters are variables:
|
||||||
|
|
||||||
\begin{description}
|
\begin{description}
|
||||||
\item{{\bf :N}} \quad \\
|
\item{{\bf :N}} \quad \\
|
||||||
Source text has length $N$ (must be first op)
|
Source text has length $N$ (must be first op)
|
||||||
\item{{\bf >N}} \quad \\
|
\item{{\bf >N}} \quad \\
|
||||||
Final text is $N$ (positive) characters longer than source
|
Final text is $N$ (positive) characters longer than source
|
||||||
|
|
|
@ -72,7 +72,7 @@ Here are descriptions of the operations, where capital letters are variables:
|
||||||
"-N" : Skip over (delete) N characters from the source text, none of them newlines
|
"-N" : Skip over (delete) N characters from the source text, none of them newlines
|
||||||
"=N" : Keep N characters from the source text, none of them newlines
|
"=N" : Keep N characters from the source text, none of them newlines
|
||||||
"|L+N" : Insert N characters from the source text, containing L newlines. The last
|
"|L+N" : Insert N characters from the source text, containing L newlines. The last
|
||||||
character inserted MUST be a newline, but not the (new) document's final newline.
|
character inserted MUST be a newline, but not the (new) document's final newline.
|
||||||
"|L-N" : Delete N characters from the source text, containing L newlines. The last
|
"|L-N" : Delete N characters from the source text, containing L newlines. The last
|
||||||
character inserted MUST be a newline, but not the (old) document's final newline.
|
character inserted MUST be a newline, but not the (old) document's final newline.
|
||||||
"|L=N" : Keep N characters from the source text, containing L newlines. The last character
|
"|L=N" : Keep N characters from the source text, containing L newlines. The last character
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
// favicon default name
|
// favicon default name
|
||||||
// alternatively, set up a fully specified Url to your own favicon
|
// alternatively, set up a fully specified Url to your own favicon
|
||||||
"favicon": "favicon.ico",
|
"favicon": "favicon.ico",
|
||||||
|
|
||||||
//Ip and port which etherpad should bind at
|
//Ip and port which etherpad should bind at
|
||||||
"ip": "0.0.0.0",
|
"ip": "0.0.0.0",
|
||||||
"port" : 9001,
|
"port" : 9001,
|
||||||
|
|
||||||
//The Type of the database. You can choose between dirty, postgres, sqlite and mysql
|
//The Type of the database. You can choose between dirty, postgres, sqlite and mysql
|
||||||
//You shouldn't use "dirty" for for anything else than testing or development
|
//You shouldn't use "dirty" for for anything else than testing or development
|
||||||
"dbType" : "dirty",
|
"dbType" : "dirty",
|
||||||
|
@ -22,38 +22,38 @@
|
||||||
"dbSettings" : {
|
"dbSettings" : {
|
||||||
"filename" : "var/dirty.db"
|
"filename" : "var/dirty.db"
|
||||||
},
|
},
|
||||||
|
|
||||||
/* An Example of MySQL Configuration
|
/* An Example of MySQL Configuration
|
||||||
"dbType" : "mysql",
|
"dbType" : "mysql",
|
||||||
"dbSettings" : {
|
"dbSettings" : {
|
||||||
"user" : "root",
|
"user" : "root",
|
||||||
"host" : "localhost",
|
"host" : "localhost",
|
||||||
"password": "",
|
"password": "",
|
||||||
"database": "store"
|
"database": "store"
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//the default text of a pad
|
//the default text of a pad
|
||||||
"defaultPadText" : "Welcome to Etherpad Lite!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http:\/\/etherpad.org\n",
|
"defaultPadText" : "Welcome to Etherpad Lite!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http:\/\/etherpad.org\n",
|
||||||
|
|
||||||
/* Users must have a session to access pads. This effectively allows only group pads to be accessed. */
|
/* Users must have a session to access pads. This effectively allows only group pads to be accessed. */
|
||||||
"requireSession" : false,
|
"requireSession" : false,
|
||||||
|
|
||||||
/* Users may edit pads but not create new ones. Pad creation is only via the API. This applies both to group pads and regular pads. */
|
/* Users may edit pads but not create new ones. Pad creation is only via the API. This applies both to group pads and regular pads. */
|
||||||
"editOnly" : false,
|
"editOnly" : false,
|
||||||
|
|
||||||
/* if true, all css & js will be minified before sending to the client. This will improve the loading performance massivly,
|
/* if true, all css & js will be minified before sending to the client. This will improve the loading performance massivly,
|
||||||
but makes it impossible to debug the javascript/css */
|
but makes it impossible to debug the javascript/css */
|
||||||
"minify" : true,
|
"minify" : true,
|
||||||
|
|
||||||
/* How long may clients use served javascript code (in seconds)? Without versioning this
|
/* How long may clients use served javascript code (in seconds)? Without versioning this
|
||||||
may cause problems during deployment. Set to 0 to disable caching */
|
may cause problems during deployment. Set to 0 to disable caching */
|
||||||
"maxAge" : 21600, // 60 * 60 * 6 = 6 hours
|
"maxAge" : 21600, // 60 * 60 * 6 = 6 hours
|
||||||
|
|
||||||
/* This is the path to the Abiword executable. Setting it to null, disables abiword.
|
/* This is the path to the Abiword executable. Setting it to null, disables abiword.
|
||||||
Abiword is needed to enable the import/export of pads*/
|
Abiword is needed to enable the import/export of pads*/
|
||||||
"abiword" : null,
|
"abiword" : null,
|
||||||
|
|
||||||
/* This setting is used if you require authentication of all users.
|
/* This setting is used if you require authentication of all users.
|
||||||
Note: /admin always requires authentication. */
|
Note: /admin always requires authentication. */
|
||||||
"requireAuthentication": false,
|
"requireAuthentication": false,
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
{ "name": "admin", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/admin:expressCreateServer" } },
|
{ "name": "admin", "hooks": { "expressCreateServer": "ep_etherpad-lite/node/hooks/express/admin:expressCreateServer" } },
|
||||||
{ "name": "adminplugins", "hooks": {
|
{ "name": "adminplugins", "hooks": {
|
||||||
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminplugins:expressCreateServer",
|
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminplugins:expressCreateServer",
|
||||||
"socketio": "ep_etherpad-lite/node/hooks/express/adminplugins:socketio" }
|
"socketio": "ep_etherpad-lite/node/hooks/express/adminplugins:socketio" }
|
||||||
},
|
},
|
||||||
{ "name": "adminsettings", "hooks": {
|
{ "name": "adminsettings", "hooks": {
|
||||||
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminsettings:expressCreateServer",
|
"expressCreateServer": "ep_etherpad-lite/node/hooks/express/adminsettings:expressCreateServer",
|
||||||
|
|
|
@ -68,7 +68,7 @@ exports.listSessionsOfAuthor = sessionManager.listSessionsOfAuthor;
|
||||||
/************************/
|
/************************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
getText(padID, [rev]) returns the text of a pad
|
getText(padID, [rev]) returns the text of a pad
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ exports.getText = function(padID, rev, callback)
|
||||||
callback = rev;
|
callback = rev;
|
||||||
rev = undefined;
|
rev = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if rev is a number
|
//check if rev is a number
|
||||||
if(rev !== undefined && typeof rev != "number")
|
if(rev !== undefined && typeof rev != "number")
|
||||||
{
|
{
|
||||||
|
@ -98,26 +98,26 @@ exports.getText = function(padID, rev, callback)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ensure this is not a negativ number
|
//ensure this is not a negativ number
|
||||||
if(rev !== undefined && rev < 0)
|
if(rev !== undefined && rev < 0)
|
||||||
{
|
{
|
||||||
callback(new customError("rev is a negativ number","apierror"));
|
callback(new customError("rev is a negativ number","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//ensure this is not a float value
|
//ensure this is not a float value
|
||||||
if(rev !== undefined && !is_int(rev))
|
if(rev !== undefined && !is_int(rev))
|
||||||
{
|
{
|
||||||
callback(new customError("rev is a float value","apierror"));
|
callback(new customError("rev is a float value","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the pad
|
//get the pad
|
||||||
getPadSafe(padID, true, function(err, pad)
|
getPadSafe(padID, true, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//the client asked for a special revision
|
//the client asked for a special revision
|
||||||
if(rev !== undefined)
|
if(rev !== undefined)
|
||||||
{
|
{
|
||||||
|
@ -127,14 +127,14 @@ exports.getText = function(padID, rev, callback)
|
||||||
callback(new customError("rev is higher than the head revision of the pad","apierror"));
|
callback(new customError("rev is higher than the head revision of the pad","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the text of this revision
|
//get the text of this revision
|
||||||
pad.getInternalRevisionAText(rev, function(err, atext)
|
pad.getInternalRevisionAText(rev, function(err, atext)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
data = {text: atext.text};
|
data = {text: atext.text};
|
||||||
|
|
||||||
callback(null, data);
|
callback(null, data);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -147,7 +147,7 @@ exports.getText = function(padID, rev, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
setText(padID, text) sets the text of a pad
|
setText(padID, text) sets the text of a pad
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ Example returns:
|
||||||
{code: 1, message:"text too long", data: null}
|
{code: 1, message:"text too long", data: null}
|
||||||
*/
|
*/
|
||||||
exports.setText = function(padID, text, callback)
|
exports.setText = function(padID, text, callback)
|
||||||
{
|
{
|
||||||
//text is required
|
//text is required
|
||||||
if(typeof text != "string")
|
if(typeof text != "string")
|
||||||
{
|
{
|
||||||
|
@ -168,17 +168,17 @@ exports.setText = function(padID, text, callback)
|
||||||
getPadSafe(padID, true, function(err, pad)
|
getPadSafe(padID, true, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//set the text
|
//set the text
|
||||||
pad.setText(text);
|
pad.setText(text);
|
||||||
|
|
||||||
//update the clients on the pad
|
//update the clients on the pad
|
||||||
padMessageHandler.updatePadClients(pad, callback);
|
padMessageHandler.updatePadClients(pad, callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
getHTML(padID, [rev]) returns the html of a pad
|
getHTML(padID, [rev]) returns the html of a pad
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -190,7 +190,7 @@ exports.getHTML = function(padID, rev, callback)
|
||||||
if(typeof rev == "function")
|
if(typeof rev == "function")
|
||||||
{
|
{
|
||||||
callback = rev;
|
callback = rev;
|
||||||
rev = undefined;
|
rev = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rev !== undefined && typeof rev != "number")
|
if (rev !== undefined && typeof rev != "number")
|
||||||
|
@ -221,7 +221,7 @@ exports.getHTML = function(padID, rev, callback)
|
||||||
getPadSafe(padID, true, function(err, pad)
|
getPadSafe(padID, true, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//the client asked for a special revision
|
//the client asked for a special revision
|
||||||
if(rev !== undefined)
|
if(rev !== undefined)
|
||||||
{
|
{
|
||||||
|
@ -231,8 +231,8 @@ exports.getHTML = function(padID, rev, callback)
|
||||||
callback(new customError("rev is higher than the head revision of the pad","apierror"));
|
callback(new customError("rev is higher than the head revision of the pad","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the html of this revision
|
//get the html of this revision
|
||||||
exportHtml.getPadHTML(pad, rev, function(err, html)
|
exportHtml.getPadHTML(pad, rev, function(err, html)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
@ -246,9 +246,9 @@ exports.getHTML = function(padID, rev, callback)
|
||||||
exportHtml.getPadHTML(pad, undefined, function (err, html)
|
exportHtml.getPadHTML(pad, undefined, function (err, html)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
data = {html: html};
|
data = {html: html};
|
||||||
|
|
||||||
callback(null, data);
|
callback(null, data);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -276,7 +276,7 @@ exports.setHTML = function(padID, html, callback)
|
||||||
/*****************/
|
/*****************/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
getRevisionsCount(padID) returns the number of revisions of this pad
|
getRevisionsCount(padID) returns the number of revisions of this pad
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -289,7 +289,7 @@ exports.getRevisionsCount = function(padID, callback)
|
||||||
getPadSafe(padID, true, function(err, pad)
|
getPadSafe(padID, true, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
callback(null, {revisions: pad.getHeadRevisionNumber()});
|
callback(null, {revisions: pad.getHeadRevisionNumber()});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,7 @@ exports.getLastEdited = function(padID, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
createPad(padName [, text]) creates a new pad in this group
|
createPad(padName [, text]) creates a new pad in this group
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -324,14 +324,14 @@ Example returns:
|
||||||
{code: 1, message:"pad does already exist", data: null}
|
{code: 1, message:"pad does already exist", data: null}
|
||||||
*/
|
*/
|
||||||
exports.createPad = function(padID, text, callback)
|
exports.createPad = function(padID, text, callback)
|
||||||
{
|
{
|
||||||
//ensure there is no $ in the padID
|
//ensure there is no $ in the padID
|
||||||
if(padID && padID.indexOf("$") != -1)
|
if(padID && padID.indexOf("$") != -1)
|
||||||
{
|
{
|
||||||
callback(new customError("createPad can't create group pads","apierror"));
|
callback(new customError("createPad can't create group pads","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//create pad
|
//create pad
|
||||||
getPadSafe(padID, false, text, function(err)
|
getPadSafe(padID, false, text, function(err)
|
||||||
{
|
{
|
||||||
|
@ -341,7 +341,7 @@ exports.createPad = function(padID, text, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
deletePad(padID) deletes a pad
|
deletePad(padID) deletes a pad
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -353,13 +353,13 @@ exports.deletePad = function(padID, callback)
|
||||||
getPadSafe(padID, true, function(err, pad)
|
getPadSafe(padID, true, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
pad.remove(callback);
|
pad.remove(callback);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
getReadOnlyLink(padID) returns the read only link of a pad
|
getReadOnlyLink(padID) returns the read only link of a pad
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -372,7 +372,7 @@ exports.getReadOnlyID = function(padID, callback)
|
||||||
getPadSafe(padID, true, function(err)
|
getPadSafe(padID, true, function(err)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//get the readonlyId
|
//get the readonlyId
|
||||||
readOnlyManager.getReadOnlyId(padID, function(err, readOnlyId)
|
readOnlyManager.getReadOnlyId(padID, function(err, readOnlyId)
|
||||||
{
|
{
|
||||||
|
@ -383,7 +383,7 @@ exports.getReadOnlyID = function(padID, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
setPublicStatus(padID, publicStatus) sets a boolean for the public status of a pad
|
setPublicStatus(padID, publicStatus) sets a boolean for the public status of a pad
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -403,20 +403,20 @@ exports.setPublicStatus = function(padID, publicStatus, callback)
|
||||||
getPadSafe(padID, true, function(err, pad)
|
getPadSafe(padID, true, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//convert string to boolean
|
//convert string to boolean
|
||||||
if(typeof publicStatus == "string")
|
if(typeof publicStatus == "string")
|
||||||
publicStatus = publicStatus == "true" ? true : false;
|
publicStatus = publicStatus == "true" ? true : false;
|
||||||
|
|
||||||
//set the password
|
//set the password
|
||||||
pad.setPublicStatus(publicStatus);
|
pad.setPublicStatus(publicStatus);
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
getPublicStatus(padID) return true of false
|
getPublicStatus(padID) return true of false
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -431,18 +431,18 @@ exports.getPublicStatus = function(padID, callback)
|
||||||
callback(new customError("You can only get/set the publicStatus of pads that belong to a group","apierror"));
|
callback(new customError("You can only get/set the publicStatus of pads that belong to a group","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the pad
|
//get the pad
|
||||||
getPadSafe(padID, true, function(err, pad)
|
getPadSafe(padID, true, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
callback(null, {publicStatus: pad.getPublicStatus()});
|
callback(null, {publicStatus: pad.getPublicStatus()});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
setPassword(padID, password) returns ok or a error message
|
setPassword(padID, password) returns ok or a error message
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -457,21 +457,21 @@ exports.setPassword = function(padID, password, callback)
|
||||||
callback(new customError("You can only get/set the password of pads that belong to a group","apierror"));
|
callback(new customError("You can only get/set the password of pads that belong to a group","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get the pad
|
//get the pad
|
||||||
getPadSafe(padID, true, function(err, pad)
|
getPadSafe(padID, true, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//set the password
|
//set the password
|
||||||
pad.setPassword(password == "" ? null : password);
|
pad.setPassword(password == "" ? null : password);
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
isPasswordProtected(padID) returns true or false
|
isPasswordProtected(padID) returns true or false
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -491,13 +491,13 @@ exports.isPasswordProtected = function(padID, callback)
|
||||||
getPadSafe(padID, true, function(err, pad)
|
getPadSafe(padID, true, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
callback(null, {isPasswordProtected: pad.isPasswordProtected()});
|
callback(null, {isPasswordProtected: pad.isPasswordProtected()});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
listAuthorsOfPad(padID) returns an array of authors who contributed to this pad
|
listAuthorsOfPad(padID) returns an array of authors who contributed to this pad
|
||||||
|
|
||||||
Example returns:
|
Example returns:
|
||||||
|
|
||||||
|
@ -510,7 +510,7 @@ exports.listAuthorsOfPad = function(padID, callback)
|
||||||
getPadSafe(padID, true, function(err, pad)
|
getPadSafe(padID, true, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
callback(null, {authorIDs: pad.getAllAuthors()});
|
callback(null, {authorIDs: pad.getAllAuthors()});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -555,7 +555,7 @@ exports.sendClientsMessage = function (padID, msg, callback) {
|
||||||
|
|
||||||
//checks if a number is an int
|
//checks if a number is an int
|
||||||
function is_int(value)
|
function is_int(value)
|
||||||
{
|
{
|
||||||
return (parseFloat(value) == parseInt(value)) && !isNaN(value)
|
return (parseFloat(value) == parseInt(value)) && !isNaN(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -574,19 +574,19 @@ function getPadSafe(padID, shouldExist, text, callback)
|
||||||
callback(new customError("padID is not a string","apierror"));
|
callback(new customError("padID is not a string","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if the padID maches the requirements
|
//check if the padID maches the requirements
|
||||||
if(!padManager.isValidPadId(padID))
|
if(!padManager.isValidPadId(padID))
|
||||||
{
|
{
|
||||||
callback(new customError("padID did not match requirements","apierror"));
|
callback(new customError("padID did not match requirements","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if the pad exists
|
//check if the pad exists
|
||||||
padManager.doesPadExists(padID, function(err, exists)
|
padManager.doesPadExists(padID, function(err, exists)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//does not exist, but should
|
//does not exist, but should
|
||||||
if(exists == false && shouldExist == true)
|
if(exists == false && shouldExist == true)
|
||||||
{
|
{
|
||||||
|
|
|
@ -38,9 +38,9 @@ exports.doesAuthorExists = function (authorID, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the AuthorID for a token.
|
* Returns the AuthorID for a token.
|
||||||
* @param {String} token The token
|
* @param {String} token The token
|
||||||
* @param {Function} callback callback (err, author)
|
* @param {Function} callback callback (err, author)
|
||||||
*/
|
*/
|
||||||
exports.getAuthor4Token = function (token, callback)
|
exports.getAuthor4Token = function (token, callback)
|
||||||
{
|
{
|
||||||
|
@ -53,21 +53,21 @@ exports.getAuthor4Token = function (token, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the AuthorID for a mapper.
|
* Returns the AuthorID for a mapper.
|
||||||
* @param {String} token The mapper
|
* @param {String} token The mapper
|
||||||
* @param {String} name The name of the author (optional)
|
* @param {String} name The name of the author (optional)
|
||||||
* @param {Function} callback callback (err, author)
|
* @param {Function} callback callback (err, author)
|
||||||
*/
|
*/
|
||||||
exports.createAuthorIfNotExistsFor = function (authorMapper, name, callback)
|
exports.createAuthorIfNotExistsFor = function (authorMapper, name, callback)
|
||||||
{
|
{
|
||||||
mapAuthorWithDBKey("mapper2author", authorMapper, function(err, author)
|
mapAuthorWithDBKey("mapper2author", authorMapper, function(err, author)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//set the name of this author
|
//set the name of this author
|
||||||
if(name)
|
if(name)
|
||||||
exports.setAuthorName(author.authorID, name);
|
exports.setAuthorName(author.authorID, name);
|
||||||
|
|
||||||
//return the authorID
|
//return the authorID
|
||||||
callback(null, author);
|
callback(null, author);
|
||||||
});
|
});
|
||||||
|
@ -76,27 +76,27 @@ exports.createAuthorIfNotExistsFor = function (authorMapper, name, callback)
|
||||||
/**
|
/**
|
||||||
* Returns the AuthorID for a mapper. We can map using a mapperkey,
|
* Returns the AuthorID for a mapper. We can map using a mapperkey,
|
||||||
* so far this is token2author and mapper2author
|
* so far this is token2author and mapper2author
|
||||||
* @param {String} mapperkey The database key name for this mapper
|
* @param {String} mapperkey The database key name for this mapper
|
||||||
* @param {String} mapper The mapper
|
* @param {String} mapper The mapper
|
||||||
* @param {Function} callback callback (err, author)
|
* @param {Function} callback callback (err, author)
|
||||||
*/
|
*/
|
||||||
function mapAuthorWithDBKey (mapperkey, mapper, callback)
|
function mapAuthorWithDBKey (mapperkey, mapper, callback)
|
||||||
{
|
{
|
||||||
//try to map to an author
|
//try to map to an author
|
||||||
db.get(mapperkey + ":" + mapper, function (err, author)
|
db.get(mapperkey + ":" + mapper, function (err, author)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//there is no author with this mapper, so create one
|
//there is no author with this mapper, so create one
|
||||||
if(author == null)
|
if(author == null)
|
||||||
{
|
{
|
||||||
exports.createAuthor(null, function(err, author)
|
exports.createAuthor(null, function(err, author)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//create the token2author relation
|
//create the token2author relation
|
||||||
db.set(mapperkey + ":" + mapper, author.authorID);
|
db.set(mapperkey + ":" + mapper, author.authorID);
|
||||||
|
|
||||||
//return the author
|
//return the author
|
||||||
callback(null, author);
|
callback(null, author);
|
||||||
});
|
});
|
||||||
|
@ -106,7 +106,7 @@ function mapAuthorWithDBKey (mapperkey, mapper, callback)
|
||||||
{
|
{
|
||||||
//update the timestamp of this author
|
//update the timestamp of this author
|
||||||
db.setSub("globalAuthor:" + author, ["timestamp"], new Date().getTime());
|
db.setSub("globalAuthor:" + author, ["timestamp"], new Date().getTime());
|
||||||
|
|
||||||
//return the author
|
//return the author
|
||||||
callback(null, {authorID: author});
|
callback(null, {authorID: author});
|
||||||
}
|
}
|
||||||
|
@ -114,20 +114,20 @@ function mapAuthorWithDBKey (mapperkey, mapper, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal function that creates the database entry for an author
|
* Internal function that creates the database entry for an author
|
||||||
* @param {String} name The name of the author
|
* @param {String} name The name of the author
|
||||||
*/
|
*/
|
||||||
exports.createAuthor = function(name, callback)
|
exports.createAuthor = function(name, callback)
|
||||||
{
|
{
|
||||||
//create the new author name
|
//create the new author name
|
||||||
var author = "a." + randomString(16);
|
var author = "a." + randomString(16);
|
||||||
|
|
||||||
//create the globalAuthors db entry
|
//create the globalAuthors db entry
|
||||||
var authorObj = {"colorId" : Math.floor(Math.random()*32), "name": name, "timestamp": new Date().getTime()};
|
var authorObj = {"colorId" : Math.floor(Math.random()*32), "name": name, "timestamp": new Date().getTime()};
|
||||||
|
|
||||||
//set the global author db entry
|
//set the global author db entry
|
||||||
db.set("globalAuthor:" + author, authorObj);
|
db.set("globalAuthor:" + author, authorObj);
|
||||||
|
|
||||||
callback(null, {authorID: author});
|
callback(null, {authorID: author});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,7 +208,7 @@ exports.listPadsOfAuthor = function (authorID, callback)
|
||||||
}
|
}
|
||||||
//everything is fine, return the pad IDs
|
//everything is fine, return the pad IDs
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var pads = [];
|
var pads = [];
|
||||||
if(author.padIDs != null)
|
if(author.padIDs != null)
|
||||||
{
|
{
|
||||||
|
@ -234,16 +234,16 @@ exports.addPad = function (authorID, padID)
|
||||||
{
|
{
|
||||||
if(ERR(err)) return;
|
if(ERR(err)) return;
|
||||||
if(author == null) return;
|
if(author == null) return;
|
||||||
|
|
||||||
//the entry doesn't exist so far, let's create it
|
//the entry doesn't exist so far, let's create it
|
||||||
if(author.padIDs == null)
|
if(author.padIDs == null)
|
||||||
{
|
{
|
||||||
author.padIDs = {};
|
author.padIDs = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
//add the entry for this pad
|
//add the entry for this pad
|
||||||
author.padIDs[padID] = 1;// anything, because value is not used
|
author.padIDs[padID] = 1;// anything, because value is not used
|
||||||
|
|
||||||
//save the new element back
|
//save the new element back
|
||||||
db.set("globalAuthor:" + authorID, author);
|
db.set("globalAuthor:" + authorID, author);
|
||||||
});
|
});
|
||||||
|
@ -260,11 +260,11 @@ exports.removePad = function (authorID, padID)
|
||||||
{
|
{
|
||||||
if(ERR(err)) return;
|
if(ERR(err)) return;
|
||||||
if(author == null) return;
|
if(author == null) return;
|
||||||
|
|
||||||
if(author.padIDs != null)
|
if(author.padIDs != null)
|
||||||
{
|
{
|
||||||
//remove pad from author
|
//remove pad from author
|
||||||
delete author.padIDs[padID];
|
delete author.padIDs[padID];
|
||||||
db.set("globalAuthor:" + authorID, author);
|
db.set("globalAuthor:" + authorID, author);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* The DB Module provides a database initalized with the settings
|
* The DB Module provides a database initalized with the settings
|
||||||
* provided by the settings module
|
* provided by the settings module
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -33,14 +33,14 @@ exports.db = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initalizes the database with the settings provided by the settings module
|
* Initalizes the database with the settings provided by the settings module
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
exports.init = function(callback)
|
exports.init = function(callback)
|
||||||
{
|
{
|
||||||
//initalize the database async
|
//initalize the database async
|
||||||
db.init(function(err)
|
db.init(function(err)
|
||||||
{
|
{
|
||||||
//there was an error while initializing the database, output it and stop
|
//there was an error while initializing the database, output it and stop
|
||||||
if(err)
|
if(err)
|
||||||
{
|
{
|
||||||
console.error("ERROR: Problem while initalizing the database");
|
console.error("ERROR: Problem while initalizing the database");
|
||||||
|
@ -50,7 +50,7 @@ exports.init = function(callback)
|
||||||
//everything ok
|
//everything ok
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
exports.db = db;
|
exports.db = db;
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
var ERR = require("async-stacktrace");
|
var ERR = require("async-stacktrace");
|
||||||
var customError = require("../utils/customError");
|
var customError = require("../utils/customError");
|
||||||
|
@ -30,13 +30,13 @@ var sessionManager = require("./SessionManager");
|
||||||
exports.listAllGroups = function(callback) {
|
exports.listAllGroups = function(callback) {
|
||||||
db.get("groups", function (err, groups) {
|
db.get("groups", function (err, groups) {
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
// there are no groups
|
// there are no groups
|
||||||
if(groups == null) {
|
if(groups == null) {
|
||||||
callback(null, {groupIDs: []});
|
callback(null, {groupIDs: []});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var groupIDs = [];
|
var groupIDs = [];
|
||||||
for ( var groupID in groups ) {
|
for ( var groupID in groups ) {
|
||||||
groupIDs.push(groupID);
|
groupIDs.push(groupID);
|
||||||
|
@ -44,20 +44,20 @@ exports.listAllGroups = function(callback) {
|
||||||
callback(null, {groupIDs: groupIDs});
|
callback(null, {groupIDs: groupIDs});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.deleteGroup = function(groupID, callback)
|
exports.deleteGroup = function(groupID, callback)
|
||||||
{
|
{
|
||||||
var group;
|
var group;
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
//ensure group exists
|
//ensure group exists
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
//try to get the group entry
|
//try to get the group entry
|
||||||
db.get("group:" + groupID, function (err, _group)
|
db.get("group:" + groupID, function (err, _group)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//group does not exist
|
//group does not exist
|
||||||
if(_group == null)
|
if(_group == null)
|
||||||
{
|
{
|
||||||
|
@ -80,14 +80,14 @@ exports.deleteGroup = function(groupID, callback)
|
||||||
{
|
{
|
||||||
padIDs.push(i);
|
padIDs.push(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//loop trough all pads and delete them
|
//loop trough all pads and delete them
|
||||||
async.forEach(padIDs, function(padID, callback)
|
async.forEach(padIDs, function(padID, callback)
|
||||||
{
|
{
|
||||||
padManager.getPad(padID, function(err, pad)
|
padManager.getPad(padID, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
pad.remove(callback);
|
pad.remove(callback);
|
||||||
});
|
});
|
||||||
}, callback);
|
}, callback);
|
||||||
|
@ -99,18 +99,18 @@ exports.deleteGroup = function(groupID, callback)
|
||||||
db.get("group2sessions:" + groupID, function (err, group2sessions)
|
db.get("group2sessions:" + groupID, function (err, group2sessions)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//skip if there is no group2sessions entry
|
//skip if there is no group2sessions entry
|
||||||
if(group2sessions == null) {callback(); return}
|
if(group2sessions == null) {callback(); return}
|
||||||
|
|
||||||
//collect all sessions in an array, that allows us to use async.forEach
|
//collect all sessions in an array, that allows us to use async.forEach
|
||||||
var sessions = [];
|
var sessions = [];
|
||||||
for(var i in group2sessions.sessionsIDs)
|
for(var i in group2sessions.sessionsIDs)
|
||||||
{
|
{
|
||||||
sessions.push(i);
|
sessions.push(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//loop trough all sessions and delete them
|
//loop trough all sessions and delete them
|
||||||
async.forEach(sessions, function(session, callback)
|
async.forEach(sessions, function(session, callback)
|
||||||
{
|
{
|
||||||
sessionManager.deleteSession(session, callback);
|
sessionManager.deleteSession(session, callback);
|
||||||
|
@ -138,7 +138,7 @@ exports.deleteGroup = function(groupID, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
groups.splice(groups.indexOf(groupID), 1);
|
groups.splice(groups.indexOf(groupID), 1);
|
||||||
|
|
||||||
// store empty groupe list
|
// store empty groupe list
|
||||||
if(groups.length == 0) {
|
if(groups.length == 0) {
|
||||||
db.set("groups", {});
|
db.set("groups", {});
|
||||||
|
@ -163,7 +163,7 @@ exports.deleteGroup = function(groupID, callback)
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.doesGroupExist = function(groupID, callback)
|
exports.doesGroupExist = function(groupID, callback)
|
||||||
{
|
{
|
||||||
//try to get the group entry
|
//try to get the group entry
|
||||||
|
@ -178,17 +178,17 @@ exports.createGroup = function(callback)
|
||||||
{
|
{
|
||||||
//search for non existing groupID
|
//search for non existing groupID
|
||||||
var groupID = "g." + randomString(16);
|
var groupID = "g." + randomString(16);
|
||||||
|
|
||||||
//create the group
|
//create the group
|
||||||
db.set("group:" + groupID, {pads: {}});
|
db.set("group:" + groupID, {pads: {}});
|
||||||
|
|
||||||
//list the group
|
//list the group
|
||||||
exports.listAllGroups(function(err, groups) {
|
exports.listAllGroups(function(err, groups) {
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
groups = groups? groups.groupIDs : [];
|
groups = groups? groups.groupIDs : [];
|
||||||
|
|
||||||
groups.push(groupID);
|
groups.push(groupID);
|
||||||
|
|
||||||
// regenerate group list
|
// regenerate group list
|
||||||
var newGroups = {};
|
var newGroups = {};
|
||||||
async.forEach(groups, function(group, cb) {
|
async.forEach(groups, function(group, cb) {
|
||||||
|
@ -209,22 +209,22 @@ exports.createGroupIfNotExistsFor = function(groupMapper, callback)
|
||||||
callback(new customError("groupMapper is no string","apierror"));
|
callback(new customError("groupMapper is no string","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//try to get a group for this mapper
|
//try to get a group for this mapper
|
||||||
db.get("mapper2group:"+groupMapper, function(err, groupID)
|
db.get("mapper2group:"+groupMapper, function(err, groupID)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//there is no group for this mapper, let's create a group
|
//there is no group for this mapper, let's create a group
|
||||||
if(groupID == null)
|
if(groupID == null)
|
||||||
{
|
{
|
||||||
exports.createGroup(function(err, responseObj)
|
exports.createGroup(function(err, responseObj)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//create the mapper entry for this group
|
//create the mapper entry for this group
|
||||||
db.set("mapper2group:"+groupMapper, responseObj.groupID);
|
db.set("mapper2group:"+groupMapper, responseObj.groupID);
|
||||||
|
|
||||||
callback(null, responseObj);
|
callback(null, responseObj);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -243,13 +243,13 @@ exports.createGroupPad = function(groupID, padName, text, callback)
|
||||||
var padID = groupID + "$" + padName;
|
var padID = groupID + "$" + padName;
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
//ensure group exists
|
//ensure group exists
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
exports.doesGroupExist(groupID, function(err, exists)
|
exports.doesGroupExist(groupID, function(err, exists)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//group does not exist
|
//group does not exist
|
||||||
if(exists == false)
|
if(exists == false)
|
||||||
{
|
{
|
||||||
|
@ -268,7 +268,7 @@ exports.createGroupPad = function(groupID, padName, text, callback)
|
||||||
padManager.doesPadExists(padID, function(err, exists)
|
padManager.doesPadExists(padID, function(err, exists)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//pad exists already
|
//pad exists already
|
||||||
if(exists == true)
|
if(exists == true)
|
||||||
{
|
{
|
||||||
|
@ -308,7 +308,7 @@ exports.listPads = function(groupID, callback)
|
||||||
exports.doesGroupExist(groupID, function(err, exists)
|
exports.doesGroupExist(groupID, function(err, exists)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//group does not exist
|
//group does not exist
|
||||||
if(exists == false)
|
if(exists == false)
|
||||||
{
|
{
|
||||||
|
|
|
@ -83,33 +83,33 @@ Pad.prototype.appendRevision = function appendRevision(aChangeset, author) {
|
||||||
|
|
||||||
db.set("pad:"+this.id+":revs:"+newRev, newRevData);
|
db.set("pad:"+this.id+":revs:"+newRev, newRevData);
|
||||||
this.saveToDatabase();
|
this.saveToDatabase();
|
||||||
|
|
||||||
// set the author to pad
|
// set the author to pad
|
||||||
if(author)
|
if(author)
|
||||||
authorManager.addPad(author, this.id);
|
authorManager.addPad(author, this.id);
|
||||||
|
|
||||||
if (this.head == 0) {
|
if (this.head == 0) {
|
||||||
hooks.callAll("padCreate", {'pad':this});
|
hooks.callAll("padCreate", {'pad':this});
|
||||||
} else {
|
} else {
|
||||||
hooks.callAll("padUpdate", {'pad':this});
|
hooks.callAll("padUpdate", {'pad':this});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//save all attributes to the database
|
//save all attributes to the database
|
||||||
Pad.prototype.saveToDatabase = function saveToDatabase(){
|
Pad.prototype.saveToDatabase = function saveToDatabase(){
|
||||||
var dbObject = {};
|
var dbObject = {};
|
||||||
|
|
||||||
for(var attr in this){
|
for(var attr in this){
|
||||||
if(typeof this[attr] === "function") continue;
|
if(typeof this[attr] === "function") continue;
|
||||||
if(attributeBlackList.indexOf(attr) !== -1) continue;
|
if(attributeBlackList.indexOf(attr) !== -1) continue;
|
||||||
|
|
||||||
dbObject[attr] = this[attr];
|
dbObject[attr] = this[attr];
|
||||||
|
|
||||||
if(jsonableList.indexOf(attr) !== -1){
|
if(jsonableList.indexOf(attr) !== -1){
|
||||||
dbObject[attr] = dbObject[attr].toJsonable();
|
dbObject[attr] = dbObject[attr].toJsonable();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
db.set("pad:"+this.id, dbObject);
|
db.set("pad:"+this.id, dbObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -510,7 +510,7 @@ Pad.prototype.addSavedRevision = function addSavedRevision(revNum, savedById, la
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//build the saved revision object
|
//build the saved revision object
|
||||||
var savedRevision = {};
|
var savedRevision = {};
|
||||||
savedRevision.revNum = revNum;
|
savedRevision.revNum = revNum;
|
||||||
|
@ -518,7 +518,7 @@ Pad.prototype.addSavedRevision = function addSavedRevision(revNum, savedById, la
|
||||||
savedRevision.label = label || "Revision " + revNum;
|
savedRevision.label = label || "Revision " + revNum;
|
||||||
savedRevision.timestamp = new Date().getTime();
|
savedRevision.timestamp = new Date().getTime();
|
||||||
savedRevision.id = randomString(10);
|
savedRevision.id = randomString(10);
|
||||||
|
|
||||||
//save this new saved revision
|
//save this new saved revision
|
||||||
this.savedRevisions.push(savedRevision);
|
this.savedRevisions.push(savedRevision);
|
||||||
this.saveToDatabase();
|
this.saveToDatabase();
|
||||||
|
|
|
@ -23,7 +23,7 @@ var customError = require("../utils/customError");
|
||||||
var Pad = require("../db/Pad").Pad;
|
var Pad = require("../db/Pad").Pad;
|
||||||
var db = require("./DB").db;
|
var db = require("./DB").db;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An Object containing all known Pads. Provides "get" and "set" functions,
|
* An Object containing all known Pads. Provides "get" and "set" functions,
|
||||||
* which should be used instead of indexing with brackets. These prepend a
|
* which should be used instead of indexing with brackets. These prepend a
|
||||||
* colon to the key, to avoid conflicting with built-in Object methods or with
|
* colon to the key, to avoid conflicting with built-in Object methods or with
|
||||||
|
@ -50,24 +50,24 @@ var padIdTransforms = [
|
||||||
/**
|
/**
|
||||||
* Returns a Pad Object with the callback
|
* Returns a Pad Object with the callback
|
||||||
* @param id A String with the id of the pad
|
* @param id A String with the id of the pad
|
||||||
* @param {Function} callback
|
* @param {Function} callback
|
||||||
*/
|
*/
|
||||||
exports.getPad = function(id, text, callback)
|
exports.getPad = function(id, text, callback)
|
||||||
{
|
{
|
||||||
//check if this is a valid padId
|
//check if this is a valid padId
|
||||||
if(!exports.isValidPadId(id))
|
if(!exports.isValidPadId(id))
|
||||||
{
|
{
|
||||||
callback(new customError(id + " is not a valid padId","apierror"));
|
callback(new customError(id + " is not a valid padId","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//make text an optional parameter
|
//make text an optional parameter
|
||||||
if(typeof text == "function")
|
if(typeof text == "function")
|
||||||
{
|
{
|
||||||
callback = text;
|
callback = text;
|
||||||
text = null;
|
text = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if this is a valid text
|
//check if this is a valid text
|
||||||
if(text != null)
|
if(text != null)
|
||||||
{
|
{
|
||||||
|
@ -77,7 +77,7 @@ exports.getPad = function(id, text, callback)
|
||||||
callback(new customError("text is not a string","apierror"));
|
callback(new customError("text is not a string","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if text is less than 100k chars
|
//check if text is less than 100k chars
|
||||||
if(text.length > 100000)
|
if(text.length > 100000)
|
||||||
{
|
{
|
||||||
|
@ -85,9 +85,9 @@ exports.getPad = function(id, text, callback)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var pad = globalPads.get(id);
|
var pad = globalPads.get(id);
|
||||||
|
|
||||||
//return pad if its already loaded
|
//return pad if its already loaded
|
||||||
if(pad != null)
|
if(pad != null)
|
||||||
{
|
{
|
||||||
|
@ -97,12 +97,12 @@ exports.getPad = function(id, text, callback)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pad = new Pad(id);
|
pad = new Pad(id);
|
||||||
|
|
||||||
//initalize the pad
|
//initalize the pad
|
||||||
pad.init(text, function(err)
|
pad.init(text, function(err)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
globalPads.set(id, pad);
|
globalPads.set(id, pad);
|
||||||
callback(null, pad);
|
callback(null, pad);
|
||||||
});
|
});
|
||||||
|
@ -120,7 +120,7 @@ exports.doesPadExists = function(padId, callback)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
callback(null, false);
|
callback(null, false);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||||
* @param {String} padId the id of the pad
|
* @param {String} padId the id of the pad
|
||||||
*/
|
*/
|
||||||
exports.getReadOnlyId = function (padId, callback)
|
exports.getReadOnlyId = function (padId, callback)
|
||||||
{
|
{
|
||||||
var readOnlyId;
|
var readOnlyId;
|
||||||
|
|
||||||
async.waterfall([
|
async.waterfall([
|
||||||
//check if there is a pad2readonly entry
|
//check if there is a pad2readonly entry
|
||||||
function(callback)
|
function(callback)
|
||||||
|
@ -44,7 +44,7 @@ exports.getReadOnlyId = function (padId, callback)
|
||||||
if(dbReadOnlyId == null)
|
if(dbReadOnlyId == null)
|
||||||
{
|
{
|
||||||
readOnlyId = "r." + randomString(16);
|
readOnlyId = "r." + randomString(16);
|
||||||
|
|
||||||
db.set("pad2readonly:" + padId, readOnlyId);
|
db.set("pad2readonly:" + padId, readOnlyId);
|
||||||
db.set("readonly2pad:" + readOnlyId, padId);
|
db.set("readonly2pad:" + readOnlyId, padId);
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ exports.getReadOnlyId = function (padId, callback)
|
||||||
{
|
{
|
||||||
readOnlyId = dbReadOnlyId;
|
readOnlyId = dbReadOnlyId;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
], function(err)
|
], function(err)
|
||||||
|
|
|
@ -33,11 +33,11 @@ var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||||
* @param padID the pad the user wants to access
|
* @param padID the pad the user wants to access
|
||||||
* @param sesssionID the session the user has (set via api)
|
* @param sesssionID the session the user has (set via api)
|
||||||
* @param token the token of the author (randomly generated at client side, used for public pads)
|
* @param token the token of the author (randomly generated at client side, used for public pads)
|
||||||
* @param password the password the user has given to access this pad, can be null
|
* @param password the password the user has given to access this pad, can be null
|
||||||
* @param callback will be called with (err, {accessStatus: grant|deny|wrongPassword|needPassword, authorID: a.xxxxxx})
|
* @param callback will be called with (err, {accessStatus: grant|deny|wrongPassword|needPassword, authorID: a.xxxxxx})
|
||||||
*/
|
*/
|
||||||
exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
||||||
{
|
{
|
||||||
var statusObject;
|
var statusObject;
|
||||||
|
|
||||||
// a valid session is required (api-only mode)
|
// a valid session is required (api-only mode)
|
||||||
|
@ -60,7 +60,7 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
||||||
authorManager.getAuthor4Token(token, function(err, author)
|
authorManager.getAuthor4Token(token, function(err, author)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
// assume user has access
|
// assume user has access
|
||||||
statusObject = {accessStatus: "grant", authorID: author};
|
statusObject = {accessStatus: "grant", authorID: author};
|
||||||
// user can't create pads
|
// user can't create pads
|
||||||
|
@ -70,7 +70,7 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
||||||
padManager.doesPadExists(padID, function(err, exists)
|
padManager.doesPadExists(padID, function(err, exists)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
// pad doesn't exist - user can't have access
|
// pad doesn't exist - user can't have access
|
||||||
if(!exists) statusObject.accessStatus = "deny";
|
if(!exists) statusObject.accessStatus = "deny";
|
||||||
// grant or deny access, with author of token
|
// grant or deny access, with author of token
|
||||||
|
@ -84,12 +84,12 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
||||||
callback(null, statusObject);
|
callback(null, statusObject);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
//don't continue
|
//don't continue
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var groupID = padID.split("$")[0];
|
var groupID = padID.split("$")[0];
|
||||||
var padExists = false;
|
var padExists = false;
|
||||||
var validSession = false;
|
var validSession = false;
|
||||||
|
@ -100,7 +100,7 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
||||||
var passwordStatus = password == null ? "notGiven" : "wrong"; // notGiven, correct, wrong
|
var passwordStatus = password == null ? "notGiven" : "wrong"; // notGiven, correct, wrong
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
//get basic informations from the database
|
//get basic informations from the database
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
async.parallel([
|
async.parallel([
|
||||||
|
@ -121,27 +121,27 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sessionIDs = sessionCookie.split(',');
|
var sessionIDs = sessionCookie.split(',');
|
||||||
async.forEach(sessionIDs, function(sessionID, callback) {
|
async.forEach(sessionIDs, function(sessionID, callback) {
|
||||||
sessionManager.getSessionInfo(sessionID, function(err, sessionInfo) {
|
sessionManager.getSessionInfo(sessionID, function(err, sessionInfo) {
|
||||||
//skip session if it doesn't exist
|
//skip session if it doesn't exist
|
||||||
if(err && err.message == "sessionID does not exist") return;
|
if(err && err.message == "sessionID does not exist") return;
|
||||||
|
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
var now = Math.floor(new Date().getTime()/1000);
|
var now = Math.floor(new Date().getTime()/1000);
|
||||||
|
|
||||||
//is it for this group?
|
//is it for this group?
|
||||||
if(sessionInfo.groupID != groupID) return;
|
if(sessionInfo.groupID != groupID) return;
|
||||||
|
|
||||||
//is validUntil still ok?
|
//is validUntil still ok?
|
||||||
if(sessionInfo.validUntil <= now) return;
|
if(sessionInfo.validUntil <= now) return;
|
||||||
|
|
||||||
// There is a valid session
|
// There is a valid session
|
||||||
validSession = true;
|
validSession = true;
|
||||||
sessionAuthor = sessionInfo.authorID;
|
sessionAuthor = sessionInfo.authorID;
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}, callback);
|
}, callback);
|
||||||
|
@ -163,28 +163,28 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
//skip this if the pad doesn't exists
|
//skip this if the pad doesn't exists
|
||||||
if(padExists == false)
|
if(padExists == false)
|
||||||
{
|
{
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
padManager.getPad(padID, function(err, pad)
|
padManager.getPad(padID, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//is it a public pad?
|
//is it a public pad?
|
||||||
isPublic = pad.getPublicStatus();
|
isPublic = pad.getPublicStatus();
|
||||||
|
|
||||||
//is it password protected?
|
//is it password protected?
|
||||||
isPasswordProtected = pad.isPasswordProtected();
|
isPasswordProtected = pad.isPasswordProtected();
|
||||||
|
|
||||||
//is password correct?
|
//is password correct?
|
||||||
if(isPasswordProtected && password && pad.isCorrectPassword(password))
|
if(isPasswordProtected && password && pad.isCorrectPassword(password))
|
||||||
{
|
{
|
||||||
passwordStatus = "correct";
|
passwordStatus = "correct";
|
||||||
}
|
}
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -221,7 +221,7 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
||||||
{
|
{
|
||||||
throw new Error("Ops, something wrong happend");
|
throw new Error("Ops, something wrong happend");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//- a valid session for this group avaible but pad doesn't exists
|
//- a valid session for this group avaible but pad doesn't exists
|
||||||
else if(validSession && !padExists)
|
else if(validSession && !padExists)
|
||||||
{
|
{
|
||||||
|
@ -245,7 +245,7 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
||||||
//--> grant access, with author of token
|
//--> grant access, with author of token
|
||||||
statusObject = {accessStatus: "grant", authorID: tokenAuthor};
|
statusObject = {accessStatus: "grant", authorID: tokenAuthor};
|
||||||
}
|
}
|
||||||
//- its public and the pad is password protected but wrong password given
|
//- its public and the pad is password protected but wrong password given
|
||||||
else if(isPublic && isPasswordProtected && passwordStatus == "wrong")
|
else if(isPublic && isPasswordProtected && passwordStatus == "wrong")
|
||||||
{
|
{
|
||||||
//--> deny access, ask for new password and tell them that the password is wrong
|
//--> deny access, ask for new password and tell them that the password is wrong
|
||||||
|
@ -267,14 +267,14 @@ exports.checkAccess = function (padID, sessionCookie, token, password, callback)
|
||||||
{
|
{
|
||||||
throw new Error("Ops, something wrong happend");
|
throw new Error("Ops, something wrong happend");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// there is no valid session avaiable AND pad doesn't exists
|
// there is no valid session avaiable AND pad doesn't exists
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//--> deny access
|
//--> deny access
|
||||||
statusObject = {accessStatus: "deny"};
|
statusObject = {accessStatus: "deny"};
|
||||||
}
|
}
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
], function(err)
|
], function(err)
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
var ERR = require("async-stacktrace");
|
var ERR = require("async-stacktrace");
|
||||||
var customError = require("../utils/customError");
|
var customError = require("../utils/customError");
|
||||||
|
@ -26,7 +26,7 @@ var db = require("./DB").db;
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
var groupMangager = require("./GroupManager");
|
var groupMangager = require("./GroupManager");
|
||||||
var authorMangager = require("./AuthorManager");
|
var authorMangager = require("./AuthorManager");
|
||||||
|
|
||||||
exports.doesSessionExist = function(sessionID, callback)
|
exports.doesSessionExist = function(sessionID, callback)
|
||||||
{
|
{
|
||||||
//check if the database entry of this session exists
|
//check if the database entry of this session exists
|
||||||
|
@ -36,7 +36,7 @@ exports.doesSessionExist = function(sessionID, callback)
|
||||||
callback(null, session != null);
|
callback(null, session != null);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new session between an author and a group
|
* Creates a new session between an author and a group
|
||||||
*/
|
*/
|
||||||
|
@ -51,7 +51,7 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
||||||
groupMangager.doesGroupExist(groupID, function(err, exists)
|
groupMangager.doesGroupExist(groupID, function(err, exists)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//group does not exist
|
//group does not exist
|
||||||
if(exists == false)
|
if(exists == false)
|
||||||
{
|
{
|
||||||
|
@ -70,7 +70,7 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
||||||
authorMangager.doesAuthorExists(authorID, function(err, exists)
|
authorMangager.doesAuthorExists(authorID, function(err, exists)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//author does not exist
|
//author does not exist
|
||||||
if(exists == false)
|
if(exists == false)
|
||||||
{
|
{
|
||||||
|
@ -100,34 +100,34 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ensure this is not a negativ number
|
//ensure this is not a negativ number
|
||||||
if(validUntil < 0)
|
if(validUntil < 0)
|
||||||
{
|
{
|
||||||
callback(new customError("validUntil is a negativ number","apierror"));
|
callback(new customError("validUntil is a negativ number","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//ensure this is not a float value
|
//ensure this is not a float value
|
||||||
if(!is_int(validUntil))
|
if(!is_int(validUntil))
|
||||||
{
|
{
|
||||||
callback(new customError("validUntil is a float value","apierror"));
|
callback(new customError("validUntil is a float value","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if validUntil is in the future
|
//check if validUntil is in the future
|
||||||
if(Math.floor(new Date().getTime()/1000) > validUntil)
|
if(Math.floor(new Date().getTime()/1000) > validUntil)
|
||||||
{
|
{
|
||||||
callback(new customError("validUntil is in the past","apierror"));
|
callback(new customError("validUntil is in the past","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//generate sessionID
|
//generate sessionID
|
||||||
sessionID = "s." + randomString(16);
|
sessionID = "s." + randomString(16);
|
||||||
|
|
||||||
//set the session into the database
|
//set the session into the database
|
||||||
db.set("session:" + sessionID, {"groupID": groupID, "authorID": authorID, "validUntil": validUntil});
|
db.set("session:" + sessionID, {"groupID": groupID, "authorID": authorID, "validUntil": validUntil});
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
//set the group2sessions entry
|
//set the group2sessions entry
|
||||||
|
@ -137,19 +137,19 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
||||||
db.get("group2sessions:" + groupID, function(err, group2sessions)
|
db.get("group2sessions:" + groupID, function(err, group2sessions)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//the entry doesn't exist so far, let's create it
|
//the entry doesn't exist so far, let's create it
|
||||||
if(group2sessions == null || group2sessions.sessionIDs == null)
|
if(group2sessions == null || group2sessions.sessionIDs == null)
|
||||||
{
|
{
|
||||||
group2sessions = {sessionIDs : {}};
|
group2sessions = {sessionIDs : {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
//add the entry for this session
|
//add the entry for this session
|
||||||
group2sessions.sessionIDs[sessionID] = 1;
|
group2sessions.sessionIDs[sessionID] = 1;
|
||||||
|
|
||||||
//save the new element back
|
//save the new element back
|
||||||
db.set("group2sessions:" + groupID, group2sessions);
|
db.set("group2sessions:" + groupID, group2sessions);
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -160,26 +160,26 @@ exports.createSession = function(groupID, authorID, validUntil, callback)
|
||||||
db.get("author2sessions:" + authorID, function(err, author2sessions)
|
db.get("author2sessions:" + authorID, function(err, author2sessions)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//the entry doesn't exist so far, let's create it
|
//the entry doesn't exist so far, let's create it
|
||||||
if(author2sessions == null || author2sessions.sessionIDs == null)
|
if(author2sessions == null || author2sessions.sessionIDs == null)
|
||||||
{
|
{
|
||||||
author2sessions = {sessionIDs : {}};
|
author2sessions = {sessionIDs : {}};
|
||||||
}
|
}
|
||||||
|
|
||||||
//add the entry for this session
|
//add the entry for this session
|
||||||
author2sessions.sessionIDs[sessionID] = 1;
|
author2sessions.sessionIDs[sessionID] = 1;
|
||||||
|
|
||||||
//save the new element back
|
//save the new element back
|
||||||
db.set("author2sessions:" + authorID, author2sessions);
|
db.set("author2sessions:" + authorID, author2sessions);
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
], function(err)
|
], function(err)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//return error and sessionID
|
//return error and sessionID
|
||||||
callback(null, {sessionID: sessionID});
|
callback(null, {sessionID: sessionID});
|
||||||
})
|
})
|
||||||
|
@ -191,7 +191,7 @@ exports.getSessionInfo = function(sessionID, callback)
|
||||||
db.get("session:" + sessionID, function (err, session)
|
db.get("session:" + sessionID, function (err, session)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//session does not exists
|
//session does not exists
|
||||||
if(session == null)
|
if(session == null)
|
||||||
{
|
{
|
||||||
|
@ -220,7 +220,7 @@ exports.deleteSession = function(sessionID, callback)
|
||||||
db.get("session:" + sessionID, function (err, session)
|
db.get("session:" + sessionID, function (err, session)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//session does not exists
|
//session does not exists
|
||||||
if(session == null)
|
if(session == null)
|
||||||
{
|
{
|
||||||
|
@ -231,7 +231,7 @@ exports.deleteSession = function(sessionID, callback)
|
||||||
{
|
{
|
||||||
authorID = session.authorID;
|
authorID = session.authorID;
|
||||||
groupID = session.groupID;
|
groupID = session.groupID;
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -261,15 +261,15 @@ exports.deleteSession = function(sessionID, callback)
|
||||||
{
|
{
|
||||||
//remove the session
|
//remove the session
|
||||||
db.remove("session:" + sessionID);
|
db.remove("session:" + sessionID);
|
||||||
|
|
||||||
//remove session from group2sessions
|
//remove session from group2sessions
|
||||||
delete group2sessions.sessionIDs[sessionID];
|
delete group2sessions.sessionIDs[sessionID];
|
||||||
db.set("group2sessions:" + groupID, group2sessions);
|
db.set("group2sessions:" + groupID, group2sessions);
|
||||||
|
|
||||||
//remove session from author2sessions
|
//remove session from author2sessions
|
||||||
delete author2sessions.sessionIDs[sessionID];
|
delete author2sessions.sessionIDs[sessionID];
|
||||||
db.set("author2sessions:" + authorID, author2sessions);
|
db.set("author2sessions:" + authorID, author2sessions);
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
], function(err)
|
], function(err)
|
||||||
|
@ -284,7 +284,7 @@ exports.listSessionsOfGroup = function(groupID, callback)
|
||||||
groupMangager.doesGroupExist(groupID, function(err, exists)
|
groupMangager.doesGroupExist(groupID, function(err, exists)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//group does not exist
|
//group does not exist
|
||||||
if(exists == false)
|
if(exists == false)
|
||||||
{
|
{
|
||||||
|
@ -299,11 +299,11 @@ exports.listSessionsOfGroup = function(groupID, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.listSessionsOfAuthor = function(authorID, callback)
|
exports.listSessionsOfAuthor = function(authorID, callback)
|
||||||
{
|
{
|
||||||
authorMangager.doesAuthorExists(authorID, function(err, exists)
|
authorMangager.doesAuthorExists(authorID, function(err, exists)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//group does not exist
|
//group does not exist
|
||||||
if(exists == false)
|
if(exists == false)
|
||||||
{
|
{
|
||||||
|
@ -334,14 +334,14 @@ function listSessionsWithDBKey (dbkey, callback)
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
//collect all sessionIDs in an arrary
|
//collect all sessionIDs in an arrary
|
||||||
var sessionIDs = [];
|
var sessionIDs = [];
|
||||||
for (var i in sessions)
|
for (var i in sessions)
|
||||||
{
|
{
|
||||||
sessionIDs.push(i);
|
sessionIDs.push(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
//foreach trough the sessions and get the sessioninfos
|
//foreach trough the sessions and get the sessioninfos
|
||||||
async.forEach(sessionIDs, function(sessionID, callback)
|
async.forEach(sessionIDs, function(sessionID, callback)
|
||||||
{
|
{
|
||||||
|
@ -362,6 +362,6 @@ function listSessionsWithDBKey (dbkey, callback)
|
||||||
|
|
||||||
//checks if a number is an int
|
//checks if a number is an int
|
||||||
function is_int(value)
|
function is_int(value)
|
||||||
{
|
{
|
||||||
return (parseFloat(value) == parseInt(value)) && !isNaN(value)
|
return (parseFloat(value) == parseInt(value)) && !isNaN(value)
|
||||||
}
|
}
|
||||||
|
|
|
@ -120,7 +120,7 @@ exports.require = function (name, args, mod) {
|
||||||
args.e = exports;
|
args.e = exports;
|
||||||
args.require = require;
|
args.require = require;
|
||||||
var template = '<% e._init(buf); %>' + fs.readFileSync(ejspath).toString() + '<% e._exit(); %>';
|
var template = '<% e._init(buf); %>' + fs.readFileSync(ejspath).toString() + '<% e._exit(); %>';
|
||||||
|
|
||||||
exports.info.args.push(args);
|
exports.info.args.push(args);
|
||||||
exports.info.file_stack.push({path: ejspath, inherit: []});
|
exports.info.file_stack.push({path: ejspath, inherit: []});
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,7 @@ try
|
||||||
{
|
{
|
||||||
apikey = fs.readFileSync("./APIKEY.txt","utf8");
|
apikey = fs.readFileSync("./APIKEY.txt","utf8");
|
||||||
}
|
}
|
||||||
catch(e)
|
catch(e)
|
||||||
{
|
{
|
||||||
apikey = randomString(32);
|
apikey = randomString(32);
|
||||||
fs.writeFileSync("./APIKEY.txt",apikey,"utf8");
|
fs.writeFileSync("./APIKEY.txt",apikey,"utf8");
|
||||||
|
@ -124,7 +124,7 @@ exports.handle = function(apiVersion, functionName, fields, req, res)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//say goodbye if this is an unkown API version
|
//say goodbye if this is an unkown API version
|
||||||
if(!isKnownApiVersion)
|
if(!isKnownApiVersion)
|
||||||
{
|
{
|
||||||
|
@ -132,7 +132,7 @@ exports.handle = function(apiVersion, functionName, fields, req, res)
|
||||||
res.send({code: 3, message: "no such api version", data: null});
|
res.send({code: 3, message: "no such api version", data: null});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check if this is a valid function name
|
//check if this is a valid function name
|
||||||
var isKnownFunctionname = false;
|
var isKnownFunctionname = false;
|
||||||
for(var knownFunctionname in version[apiVersion])
|
for(var knownFunctionname in version[apiVersion])
|
||||||
|
@ -143,14 +143,14 @@ exports.handle = function(apiVersion, functionName, fields, req, res)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//say goodbye if this is a unkown function
|
//say goodbye if this is a unkown function
|
||||||
if(!isKnownFunctionname)
|
if(!isKnownFunctionname)
|
||||||
{
|
{
|
||||||
res.send({code: 3, message: "no such function", data: null});
|
res.send({code: 3, message: "no such function", data: null});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check the api key!
|
//check the api key!
|
||||||
if(fields["apikey"] != apikey.trim())
|
if(fields["apikey"] != apikey.trim())
|
||||||
{
|
{
|
||||||
|
@ -190,16 +190,16 @@ function callAPI(apiVersion, functionName, fields, req, res)
|
||||||
{
|
{
|
||||||
functionParams.push(fields[ version[apiVersion][functionName][i] ]);
|
functionParams.push(fields[ version[apiVersion][functionName][i] ]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//add a callback function to handle the response
|
//add a callback function to handle the response
|
||||||
functionParams.push(function(err, data)
|
functionParams.push(function(err, data)
|
||||||
{
|
{
|
||||||
// no error happend, everything is fine
|
// no error happend, everything is fine
|
||||||
if(err == null)
|
if(err == null)
|
||||||
{
|
{
|
||||||
if(!data)
|
if(!data)
|
||||||
data = null;
|
data = null;
|
||||||
|
|
||||||
res.send({code: 0, message: "ok", data: data});
|
res.send({code: 0, message: "ok", data: data});
|
||||||
}
|
}
|
||||||
// parameters were wrong and the api stopped execution, pass the error
|
// parameters were wrong and the api stopped execution, pass the error
|
||||||
|
@ -214,7 +214,7 @@ function callAPI(apiVersion, functionName, fields, req, res)
|
||||||
ERR(err);
|
ERR(err);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//call the api function
|
//call the api function
|
||||||
api[functionName](functionParams[0],functionParams[1],functionParams[2],functionParams[3],functionParams[4]);
|
api[functionName](functionParams[0],functionParams[1],functionParams[2],functionParams[3],functionParams[4]);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,15 +33,15 @@ if(settings.abiword != null)
|
||||||
|
|
||||||
var tempDirectory = "/tmp";
|
var tempDirectory = "/tmp";
|
||||||
|
|
||||||
//tempDirectory changes if the operating system is windows
|
//tempDirectory changes if the operating system is windows
|
||||||
if(os.type().indexOf("Windows") > -1)
|
if(os.type().indexOf("Windows") > -1)
|
||||||
{
|
{
|
||||||
tempDirectory = process.env.TEMP;
|
tempDirectory = process.env.TEMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* do a requested export
|
* do a requested export
|
||||||
*/
|
*/
|
||||||
exports.doExport = function(req, res, padId, type)
|
exports.doExport = function(req, res, padId, type)
|
||||||
{
|
{
|
||||||
//tell the browser that this is a downloadable file
|
//tell the browser that this is a downloadable file
|
||||||
|
@ -100,7 +100,7 @@ exports.doExport = function(req, res, padId, type)
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
html = _html;
|
html = _html;
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
//decide what to do with the html export
|
//decide what to do with the html export
|
||||||
function(callback)
|
function(callback)
|
||||||
|
@ -109,13 +109,13 @@ exports.doExport = function(req, res, padId, type)
|
||||||
if(type == "html")
|
if(type == "html")
|
||||||
{
|
{
|
||||||
res.send(html);
|
res.send(html);
|
||||||
callback("stop");
|
callback("stop");
|
||||||
}
|
}
|
||||||
else //write the html export to a file
|
else //write the html export to a file
|
||||||
{
|
{
|
||||||
randNum = Math.floor(Math.random()*0xFFFFFFFF);
|
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);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
//send the convert job to abiword
|
//send the convert job to abiword
|
||||||
|
@ -123,7 +123,7 @@ exports.doExport = function(req, res, padId, type)
|
||||||
{
|
{
|
||||||
//ensure html can be collected by the garbage collector
|
//ensure html can be collected by the garbage collector
|
||||||
html = null;
|
html = null;
|
||||||
|
|
||||||
destFile = tempDirectory + "/eplite_export_" + randNum + "." + type;
|
destFile = tempDirectory + "/eplite_export_" + randNum + "." + type;
|
||||||
abiword.convertFile(srcFile, destFile, type, callback);
|
abiword.convertFile(srcFile, destFile, type, callback);
|
||||||
},
|
},
|
||||||
|
@ -145,7 +145,7 @@ exports.doExport = function(req, res, padId, type)
|
||||||
//100ms delay to accomidate for slow windows fs
|
//100ms delay to accomidate for slow windows fs
|
||||||
if(os.type().indexOf("Windows") > -1)
|
if(os.type().indexOf("Windows") > -1)
|
||||||
{
|
{
|
||||||
setTimeout(function()
|
setTimeout(function()
|
||||||
{
|
{
|
||||||
fs.unlink(destFile, callback);
|
fs.unlink(destFile, callback);
|
||||||
}, 100);
|
}, 100);
|
||||||
|
|
|
@ -38,20 +38,20 @@ if(os.type().indexOf("Windows") > -1)
|
||||||
{
|
{
|
||||||
tempDirectory = process.env.TEMP;
|
tempDirectory = process.env.TEMP;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* do a requested import
|
* do a requested import
|
||||||
*/
|
*/
|
||||||
exports.doImport = function(req, res, padId)
|
exports.doImport = function(req, res, padId)
|
||||||
{
|
{
|
||||||
//pipe to a file
|
//pipe to a file
|
||||||
//convert file to text via abiword
|
//convert file to text via abiword
|
||||||
//set text in the pad
|
//set text in the pad
|
||||||
|
|
||||||
var srcFile, destFile;
|
var srcFile, destFile;
|
||||||
var pad;
|
var pad;
|
||||||
var text;
|
var text;
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
//save the uploaded file to /tmp
|
//save the uploaded file to /tmp
|
||||||
function(callback)
|
function(callback)
|
||||||
|
@ -59,9 +59,9 @@ exports.doImport = function(req, res, padId)
|
||||||
var form = new formidable.IncomingForm();
|
var form = new formidable.IncomingForm();
|
||||||
form.keepExtensions = true;
|
form.keepExtensions = true;
|
||||||
form.uploadDir = tempDirectory;
|
form.uploadDir = tempDirectory;
|
||||||
|
|
||||||
form.parse(req, function(err, fields, files)
|
form.parse(req, function(err, fields, files)
|
||||||
{
|
{
|
||||||
//the upload failed, stop at this point
|
//the upload failed, stop at this point
|
||||||
if(err || files.file === undefined)
|
if(err || files.file === undefined)
|
||||||
{
|
{
|
||||||
|
@ -69,7 +69,7 @@ exports.doImport = function(req, res, padId)
|
||||||
callback("uploadFailed");
|
callback("uploadFailed");
|
||||||
}
|
}
|
||||||
//everything ok, continue
|
//everything ok, continue
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
//save the path of the uploaded file
|
//save the path of the uploaded file
|
||||||
srcFile = files.file.path;
|
srcFile = files.file.path;
|
||||||
|
@ -77,14 +77,14 @@ exports.doImport = function(req, res, padId)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
//ensure this is a file ending we know, else we change the file ending to .txt
|
//ensure this is a file ending we know, else we change the file ending to .txt
|
||||||
//this allows us to accept source code files like .c or .java
|
//this allows us to accept source code files like .c or .java
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var fileEnding = (srcFile.split(".")[1] || "").toLowerCase();
|
var fileEnding = (srcFile.split(".")[1] || "").toLowerCase();
|
||||||
var knownFileEndings = ["txt", "doc", "docx", "pdf", "odt", "html", "htm"];
|
var knownFileEndings = ["txt", "doc", "docx", "pdf", "odt", "html", "htm"];
|
||||||
|
|
||||||
//find out if this is a known file ending
|
//find out if this is a known file ending
|
||||||
var fileEndingKnown = false;
|
var fileEndingKnown = false;
|
||||||
for(var i in knownFileEndings)
|
for(var i in knownFileEndings)
|
||||||
|
@ -94,7 +94,7 @@ exports.doImport = function(req, res, padId)
|
||||||
fileEndingKnown = true;
|
fileEndingKnown = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if the file ending is known, continue as normal
|
//if the file ending is known, continue as normal
|
||||||
if(fileEndingKnown)
|
if(fileEndingKnown)
|
||||||
{
|
{
|
||||||
|
@ -105,11 +105,11 @@ exports.doImport = function(req, res, padId)
|
||||||
{
|
{
|
||||||
var oldSrcFile = srcFile;
|
var oldSrcFile = srcFile;
|
||||||
srcFile = srcFile.split(".")[0] + ".txt";
|
srcFile = srcFile.split(".")[0] + ".txt";
|
||||||
|
|
||||||
fs.rename(oldSrcFile, srcFile, callback);
|
fs.rename(oldSrcFile, srcFile, callback);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
//convert file to text
|
//convert file to text
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
|
@ -125,7 +125,7 @@ exports.doImport = function(req, res, padId)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
//get the pad object
|
//get the pad object
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
|
@ -136,7 +136,7 @@ exports.doImport = function(req, res, padId)
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
//read the text
|
//read the text
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
|
@ -144,8 +144,8 @@ exports.doImport = function(req, res, padId)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
text = _text;
|
text = _text;
|
||||||
|
|
||||||
//node on windows has a delay on releasing of the file lock.
|
//node on windows has a delay on releasing of the file lock.
|
||||||
//We add a 100ms delay to work around this
|
//We add a 100ms delay to work around this
|
||||||
if(os.type().indexOf("Windows") > -1)
|
if(os.type().indexOf("Windows") > -1)
|
||||||
{
|
{
|
||||||
|
@ -160,14 +160,14 @@ exports.doImport = function(req, res, padId)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
//change text of the pad and broadcast the changeset
|
//change text of the pad and broadcast the changeset
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
pad.setText(text);
|
pad.setText(text);
|
||||||
padMessageHandler.updatePadClients(pad, callback);
|
padMessageHandler.updatePadClients(pad, callback);
|
||||||
},
|
},
|
||||||
|
|
||||||
//clean up temporary files
|
//clean up temporary files
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
|
@ -185,7 +185,7 @@ exports.doImport = function(req, res, padId)
|
||||||
], function(err)
|
], function(err)
|
||||||
{
|
{
|
||||||
var status = "ok";
|
var status = "ok";
|
||||||
|
|
||||||
//check for known errors and replace the status
|
//check for known errors and replace the status
|
||||||
if(err == "uploadFailed" || err == "convertFailed")
|
if(err == "uploadFailed" || err == "convertFailed")
|
||||||
{
|
{
|
||||||
|
@ -194,7 +194,7 @@ exports.doImport = function(req, res, padId)
|
||||||
}
|
}
|
||||||
|
|
||||||
ERR(err);
|
ERR(err);
|
||||||
|
|
||||||
//close the connection
|
//close the connection
|
||||||
res.send("<script type='text/javascript' src='/static/js/jquery.js'></script><script> if ( (!$.browser.msie) && (!($.browser.mozilla && $.browser.version.indexOf(\"1.8.\") == 0)) ){document.domain = document.domain;}var impexp = window.top.require('/pad_impexp').padimpexp.handleFrameCall('" + status + "');</script>", 200);
|
res.send("<script type='text/javascript' src='/static/js/jquery.js'></script><script> if ( (!$.browser.msie) && (!($.browser.mozilla && $.browser.version.indexOf(\"1.8.\") == 0)) ){document.domain = document.domain;}var impexp = window.top.require('/pad_impexp').padimpexp.handleFrameCall('" + status + "');</script>", 200);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/**
|
/**
|
||||||
* The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions
|
* The MessageHandler handles all Messages that comes from Socket.IO and controls the sessions
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
* Copyright 2009 Google Inc., 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
||||||
|
@ -71,7 +71,7 @@ exports.setSocketIO = function(socket_io)
|
||||||
* @param client the new client
|
* @param client the new client
|
||||||
*/
|
*/
|
||||||
exports.handleConnect = function(client)
|
exports.handleConnect = function(client)
|
||||||
{
|
{
|
||||||
//Initalize sessioninfos for this new session
|
//Initalize sessioninfos for this new session
|
||||||
sessioninfos[client.id]={};
|
sessioninfos[client.id]={};
|
||||||
}
|
}
|
||||||
|
@ -98,20 +98,20 @@ exports.kickSessionsFromPad = function(padID)
|
||||||
* @param client the client that leaves
|
* @param client the client that leaves
|
||||||
*/
|
*/
|
||||||
exports.handleDisconnect = function(client)
|
exports.handleDisconnect = function(client)
|
||||||
{
|
{
|
||||||
//save the padname of this session
|
//save the padname of this session
|
||||||
var sessionPad=sessioninfos[client.id].padId;
|
var sessionPad=sessioninfos[client.id].padId;
|
||||||
|
|
||||||
//if this connection was already etablished with a handshake, send a disconnect message to the others
|
//if this connection was already etablished with a handshake, send a disconnect message to the others
|
||||||
if(sessioninfos[client.id] && sessioninfos[client.id].author)
|
if(sessioninfos[client.id] && sessioninfos[client.id].author)
|
||||||
{
|
{
|
||||||
var author = sessioninfos[client.id].author;
|
var author = sessioninfos[client.id].author;
|
||||||
|
|
||||||
//get the author color out of the db
|
//get the author color out of the db
|
||||||
authorManager.getAuthorColorId(author, function(err, color)
|
authorManager.getAuthorColorId(author, function(err, color)
|
||||||
{
|
{
|
||||||
ERR(err);
|
ERR(err);
|
||||||
|
|
||||||
//prepare the notification for the other users on the pad, that this user left
|
//prepare the notification for the other users on the pad, that this user left
|
||||||
var messageToTheOtherUsers = {
|
var messageToTheOtherUsers = {
|
||||||
"type": "COLLABROOM",
|
"type": "COLLABROOM",
|
||||||
|
@ -125,7 +125,7 @@ exports.handleDisconnect = function(client)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Go trough all user that are still on the pad, and send them the USER_LEAVE message
|
//Go trough all user that are still on the pad, and send them the USER_LEAVE message
|
||||||
for(i in pad2sessions[sessionPad])
|
for(i in pad2sessions[sessionPad])
|
||||||
{
|
{
|
||||||
|
@ -133,23 +133,23 @@ exports.handleDisconnect = function(client)
|
||||||
if(socket !== undefined){
|
if(socket !== undefined){
|
||||||
socket.json.send(messageToTheOtherUsers);
|
socket.json.send(messageToTheOtherUsers);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Go trough all sessions of this pad, search and destroy the entry of this client
|
//Go trough all sessions of this pad, search and destroy the entry of this client
|
||||||
for(i in pad2sessions[sessionPad])
|
for(i in pad2sessions[sessionPad])
|
||||||
{
|
{
|
||||||
if(pad2sessions[sessionPad][i] == client.id)
|
if(pad2sessions[sessionPad][i] == client.id)
|
||||||
{
|
{
|
||||||
pad2sessions[sessionPad].splice(i, 1);
|
pad2sessions[sessionPad].splice(i, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Delete the sessioninfos entrys of this session
|
//Delete the sessioninfos entrys of this session
|
||||||
delete sessioninfos[client.id];
|
delete sessioninfos[client.id];
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -158,7 +158,7 @@ exports.handleDisconnect = function(client)
|
||||||
* @param message the message from the client
|
* @param message the message from the client
|
||||||
*/
|
*/
|
||||||
exports.handleMessage = function(client, message)
|
exports.handleMessage = function(client, message)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(message == null)
|
if(message == null)
|
||||||
{
|
{
|
||||||
|
@ -173,18 +173,18 @@ exports.handleMessage = function(client, message)
|
||||||
|
|
||||||
var handleMessageHook = function(callback){
|
var handleMessageHook = function(callback){
|
||||||
var dropMessage = false;
|
var dropMessage = false;
|
||||||
|
|
||||||
// Call handleMessage hook. If a plugin returns null, the message will be dropped. Note that for all messages
|
// Call handleMessage hook. If a plugin returns null, the message will be dropped. Note that for all messages
|
||||||
// handleMessage will be called, even if the client is not authorized
|
// handleMessage will be called, even if the client is not authorized
|
||||||
hooks.aCallAll("handleMessage", { client: client, message: message }, function ( err, messages ) {
|
hooks.aCallAll("handleMessage", { client: client, message: message }, function ( err, messages ) {
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
_.each(messages, function(newMessage){
|
_.each(messages, function(newMessage){
|
||||||
if ( newMessage === null ) {
|
if ( newMessage === null ) {
|
||||||
dropMessage = true;
|
dropMessage = true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// If no plugins explicitly told us to drop the message, its ok to proceed
|
// If no plugins explicitly told us to drop the message, its ok to proceed
|
||||||
if(!dropMessage){ callback() };
|
if(!dropMessage){ callback() };
|
||||||
});
|
});
|
||||||
|
@ -224,7 +224,7 @@ exports.handleMessage = function(client, message)
|
||||||
//check permissions
|
//check permissions
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
|
|
||||||
if(!message.padId){
|
if(!message.padId){
|
||||||
// If the message has a padId we assume the client is already known to the server and needs no re-authorization
|
// If the message has a padId we assume the client is already known to the server and needs no re-authorization
|
||||||
callback();
|
callback();
|
||||||
|
@ -265,11 +265,11 @@ exports.handleMessage = function(client, message)
|
||||||
function handleSaveRevisionMessage(client, message){
|
function handleSaveRevisionMessage(client, message){
|
||||||
var padId = sessioninfos[client.id].padId;
|
var padId = sessioninfos[client.id].padId;
|
||||||
var userId = sessioninfos[client.id].author;
|
var userId = sessioninfos[client.id].author;
|
||||||
|
|
||||||
padManager.getPad(padId, function(err, pad)
|
padManager.getPad(padId, function(err, pad)
|
||||||
{
|
{
|
||||||
if(ERR(err)) return;
|
if(ERR(err)) return;
|
||||||
|
|
||||||
pad.addSavedRevision(pad.head, userId);
|
pad.addSavedRevision(pad.head, userId);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -307,10 +307,10 @@ function handleChatMessage(client, message)
|
||||||
var userId = sessioninfos[client.id].author;
|
var userId = sessioninfos[client.id].author;
|
||||||
var text = message.data.text;
|
var text = message.data.text;
|
||||||
var padId = sessioninfos[client.id].padId;
|
var padId = sessioninfos[client.id].padId;
|
||||||
|
|
||||||
var pad;
|
var pad;
|
||||||
var userName;
|
var userName;
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
//get the pad
|
//get the pad
|
||||||
function(callback)
|
function(callback)
|
||||||
|
@ -336,7 +336,7 @@ function handleChatMessage(client, message)
|
||||||
{
|
{
|
||||||
//save the chat message
|
//save the chat message
|
||||||
pad.appendChatMessage(text, userId, time);
|
pad.appendChatMessage(text, userId, time);
|
||||||
|
|
||||||
var msg = {
|
var msg = {
|
||||||
type: "COLLABROOM",
|
type: "COLLABROOM",
|
||||||
data: {
|
data: {
|
||||||
|
@ -347,13 +347,13 @@ function handleChatMessage(client, message)
|
||||||
text: text
|
text: text
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//broadcast the chat message to everyone on the pad
|
//broadcast the chat message to everyone on the pad
|
||||||
for(var i in pad2sessions[padId])
|
for(var i in pad2sessions[padId])
|
||||||
{
|
{
|
||||||
socketio.sockets.sockets[pad2sessions[padId][i]].json.send(msg);
|
socketio.sockets.sockets[pad2sessions[padId][i]].json.send(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
], function(err)
|
], function(err)
|
||||||
|
@ -381,9 +381,9 @@ function handleSuggestUserName(client, message)
|
||||||
messageLogger.warn("Dropped message, suggestUserName Message has no unnamedId!");
|
messageLogger.warn("Dropped message, suggestUserName Message has no unnamedId!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var padId = sessioninfos[client.id].padId;
|
var padId = sessioninfos[client.id].padId;
|
||||||
|
|
||||||
//search the author and send him this message
|
//search the author and send him this message
|
||||||
for(var i in pad2sessions[padId])
|
for(var i in pad2sessions[padId])
|
||||||
{
|
{
|
||||||
|
@ -408,14 +408,14 @@ function handleUserInfoUpdate(client, message)
|
||||||
messageLogger.warn("Dropped message, USERINFO_UPDATE Message has no colorId!");
|
messageLogger.warn("Dropped message, USERINFO_UPDATE Message has no colorId!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Find out the author name of this session
|
//Find out the author name of this session
|
||||||
var author = sessioninfos[client.id].author;
|
var author = sessioninfos[client.id].author;
|
||||||
|
|
||||||
//Tell the authorManager about the new attributes
|
//Tell the authorManager about the new attributes
|
||||||
authorManager.setAuthorColorId(author, message.data.userInfo.colorId);
|
authorManager.setAuthorColorId(author, message.data.userInfo.colorId);
|
||||||
authorManager.setAuthorName(author, message.data.userInfo.name);
|
authorManager.setAuthorName(author, message.data.userInfo.name);
|
||||||
|
|
||||||
var padId = sessioninfos[client.id].padId;
|
var padId = sessioninfos[client.id].padId;
|
||||||
|
|
||||||
var infoMsg = {
|
var infoMsg = {
|
||||||
|
@ -432,13 +432,13 @@ function handleUserInfoUpdate(client, message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//set a null name, when there is no name set. cause the client wants it null
|
//set a null name, when there is no name set. cause the client wants it null
|
||||||
if(infoMsg.data.userInfo.name == null)
|
if(infoMsg.data.userInfo.name == null)
|
||||||
{
|
{
|
||||||
infoMsg.data.userInfo.name = null;
|
infoMsg.data.userInfo.name = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Send the other clients on the pad the update message
|
//Send the other clients on the pad the update message
|
||||||
for(var i in pad2sessions[padId])
|
for(var i in pad2sessions[padId])
|
||||||
{
|
{
|
||||||
|
@ -481,7 +481,7 @@ function handleUserChanges(client, message)
|
||||||
messageLogger.warn("Dropped message, USER_CHANGES Message has no changeset!");
|
messageLogger.warn("Dropped message, USER_CHANGES Message has no changeset!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get all Vars we need
|
//get all Vars we need
|
||||||
var baseRev = message.data.baseRev;
|
var baseRev = message.data.baseRev;
|
||||||
var wireApool = (new AttributePool()).fromJsonable(message.data.apool);
|
var wireApool = (new AttributePool()).fromJsonable(message.data.apool);
|
||||||
|
@ -489,9 +489,9 @@ function handleUserChanges(client, message)
|
||||||
// The client might disconnect between our callbacks. We should still
|
// The client might disconnect between our callbacks. We should still
|
||||||
// finish processing the changeset, so keep a reference to the session.
|
// finish processing the changeset, so keep a reference to the session.
|
||||||
var thisSession = sessioninfos[client.id];
|
var thisSession = sessioninfos[client.id];
|
||||||
|
|
||||||
var r, apool, pad;
|
var r, apool, pad;
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
//get the pad
|
//get the pad
|
||||||
function(callback)
|
function(callback)
|
||||||
|
@ -507,7 +507,7 @@ function handleUserChanges(client, message)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
//ex. _checkChangesetAndPool
|
//ex. _checkChangesetAndPool
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Verify that the changeset has valid syntax and is in canonical form
|
// Verify that the changeset has valid syntax and is in canonical form
|
||||||
|
@ -528,12 +528,12 @@ function handleUserChanges(client, message)
|
||||||
client.json.send({disconnect:"badChangeset"});
|
client.json.send({disconnect:"badChangeset"});
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//ex. adoptChangesetAttribs
|
//ex. adoptChangesetAttribs
|
||||||
|
|
||||||
//Afaik, it copies the new attributes from the changeset, to the global Attribute Pool
|
//Afaik, it copies the new attributes from the changeset, to the global Attribute Pool
|
||||||
changeset = Changeset.moveOpsToNewPool(changeset, wireApool, pad.pool);
|
changeset = Changeset.moveOpsToNewPool(changeset, wireApool, pad.pool);
|
||||||
|
|
||||||
//ex. applyUserChanges
|
//ex. applyUserChanges
|
||||||
apool = pad.pool;
|
apool = pad.pool;
|
||||||
r = baseRev;
|
r = baseRev;
|
||||||
|
@ -547,7 +547,7 @@ function handleUserChanges(client, message)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
r++;
|
r++;
|
||||||
|
|
||||||
pad.getRevisionChangeset(r, function(err, c)
|
pad.getRevisionChangeset(r, function(err, c)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
@ -573,17 +573,17 @@ function handleUserChanges(client, message)
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
var prevText = pad.text();
|
var prevText = pad.text();
|
||||||
|
|
||||||
if (Changeset.oldLen(changeset) != prevText.length)
|
if (Changeset.oldLen(changeset) != prevText.length)
|
||||||
{
|
{
|
||||||
console.warn("Can't apply USER_CHANGES "+changeset+" with oldLen " + Changeset.oldLen(changeset) + " to document of length " + prevText.length);
|
console.warn("Can't apply USER_CHANGES "+changeset+" with oldLen " + Changeset.oldLen(changeset) + " to document of length " + prevText.length);
|
||||||
client.json.send({disconnect:"badChangeset"});
|
client.json.send({disconnect:"badChangeset"});
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
pad.appendRevision(changeset, thisSession.author);
|
pad.appendRevision(changeset, thisSession.author);
|
||||||
|
|
||||||
var correctionChangeset = _correctMarkersInPad(pad.atext, pad.pool);
|
var correctionChangeset = _correctMarkersInPad(pad.atext, pad.pool);
|
||||||
if (correctionChangeset) {
|
if (correctionChangeset) {
|
||||||
pad.appendRevision(correctionChangeset);
|
pad.appendRevision(correctionChangeset);
|
||||||
|
@ -594,7 +594,7 @@ function handleUserChanges(client, message)
|
||||||
var nlChangeset = Changeset.makeSplice(pad.text(), pad.text().length-1, 0, "\n");
|
var nlChangeset = Changeset.makeSplice(pad.text(), pad.text().length-1, 0, "\n");
|
||||||
pad.appendRevision(nlChangeset);
|
pad.appendRevision(nlChangeset);
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.updatePadClients(pad, callback);
|
exports.updatePadClients(pad, callback);
|
||||||
}
|
}
|
||||||
], function(err)
|
], function(err)
|
||||||
|
@ -604,14 +604,14 @@ function handleUserChanges(client, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.updatePadClients = function(pad, callback)
|
exports.updatePadClients = function(pad, callback)
|
||||||
{
|
{
|
||||||
//skip this step if noone is on this pad
|
//skip this step if noone is on this pad
|
||||||
if(!pad2sessions[pad.id])
|
if(!pad2sessions[pad.id])
|
||||||
{
|
{
|
||||||
callback();
|
callback();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
//go trough all sessions on this pad
|
//go trough all sessions on this pad
|
||||||
async.forEach(pad2sessions[pad.id], function(session, callback)
|
async.forEach(pad2sessions[pad.id], function(session, callback)
|
||||||
{
|
{
|
||||||
|
@ -621,10 +621,10 @@ exports.updatePadClients = function(pad, callback)
|
||||||
async.whilst(
|
async.whilst(
|
||||||
function (){ return sessioninfos[session].rev < pad.getHeadRevisionNumber()},
|
function (){ return sessioninfos[session].rev < pad.getHeadRevisionNumber()},
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var author, revChangeset, currentTime;
|
var author, revChangeset, currentTime;
|
||||||
var r = sessioninfos[session].rev + 1;
|
var r = sessioninfos[session].rev + 1;
|
||||||
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
|
@ -677,8 +677,8 @@ exports.updatePadClients = function(pad, callback)
|
||||||
author: author,
|
author: author,
|
||||||
currentTime: currentTime,
|
currentTime: currentTime,
|
||||||
timeDelta: currentTime - sessioninfos[session].time
|
timeDelta: currentTime - sessioninfos[session].time
|
||||||
}};
|
}};
|
||||||
|
|
||||||
socketio.sockets.sockets[session].json.send(wireMsg);
|
socketio.sockets.sockets[session].json.send(wireMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,13 +687,13 @@ exports.updatePadClients = function(pad, callback)
|
||||||
sessioninfos[session].time = currentTime;
|
sessioninfos[session].time = currentTime;
|
||||||
sessioninfos[session].rev = r;
|
sessioninfos[session].rev = r;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null);
|
callback(null);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
);
|
);
|
||||||
},callback);
|
},callback);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -709,11 +709,11 @@ function _correctMarkersInPad(atext, apool) {
|
||||||
var offset = 0;
|
var offset = 0;
|
||||||
while (iter.hasNext()) {
|
while (iter.hasNext()) {
|
||||||
var op = iter.next();
|
var op = iter.next();
|
||||||
|
|
||||||
var hasMarker = _.find(AttributeManager.lineAttributes, function(attribute){
|
var hasMarker = _.find(AttributeManager.lineAttributes, function(attribute){
|
||||||
return Changeset.opAttributeValue(op, attribute, apool);
|
return Changeset.opAttributeValue(op, attribute, apool);
|
||||||
}) !== undefined;
|
}) !== undefined;
|
||||||
|
|
||||||
if (hasMarker) {
|
if (hasMarker) {
|
||||||
for(var i=0;i<op.chars;i++) {
|
for(var i=0;i<op.chars;i++) {
|
||||||
if (offset > 0 && text.charAt(offset-1) != '\n') {
|
if (offset > 0 && text.charAt(offset-1) != '\n') {
|
||||||
|
@ -743,7 +743,7 @@ function _correctMarkersInPad(atext, apool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a CLIENT_READY. A CLIENT_READY is the first message from the client to the server. The Client sends his token
|
* Handles a CLIENT_READY. A CLIENT_READY is the first message from the client to the server. The Client sends his token
|
||||||
* and the pad it wants to enter. The Server answers with the inital values (clientVars) of the pad
|
* and the pad it wants to enter. The Server answers with the inital values (clientVars) of the pad
|
||||||
* @param client the client that send this message
|
* @param client the client that send this message
|
||||||
* @param message the message from the client
|
* @param message the message from the client
|
||||||
|
@ -802,7 +802,7 @@ function handleClientReady(client, message)
|
||||||
securityManager.checkAccess (padIds.padId, message.sessionID, message.token, message.password, function(err, statusObject)
|
securityManager.checkAccess (padIds.padId, message.sessionID, message.token, message.password, function(err, statusObject)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
//access was granted
|
//access was granted
|
||||||
if(statusObject.accessStatus == "grant")
|
if(statusObject.accessStatus == "grant")
|
||||||
{
|
{
|
||||||
|
@ -815,7 +815,7 @@ function handleClientReady(client, message)
|
||||||
client.json.send({accessStatus: statusObject.accessStatus})
|
client.json.send({accessStatus: statusObject.accessStatus})
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
//get all authordata of this new user
|
//get all authordata of this new user
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
|
@ -855,7 +855,7 @@ function handleClientReady(client, message)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var authors = pad.getAllAuthors();
|
var authors = pad.getAllAuthors();
|
||||||
|
|
||||||
async.parallel([
|
async.parallel([
|
||||||
//get timestamp of latest revission needed for timeslider
|
//get timestamp of latest revission needed for timeslider
|
||||||
function(callback)
|
function(callback)
|
||||||
|
@ -892,7 +892,7 @@ function handleClientReady(client, message)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
], callback);
|
], callback);
|
||||||
|
|
||||||
},
|
},
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
|
@ -915,27 +915,27 @@ function handleClientReady(client, message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//Save in sessioninfos that this session belonges to this pad
|
//Save in sessioninfos that this session belonges to this pad
|
||||||
sessioninfos[client.id].padId = padIds.padId;
|
sessioninfos[client.id].padId = padIds.padId;
|
||||||
sessioninfos[client.id].readOnlyPadId = padIds.readOnlyPadId;
|
sessioninfos[client.id].readOnlyPadId = padIds.readOnlyPadId;
|
||||||
sessioninfos[client.id].readonly = padIds.readonly;
|
sessioninfos[client.id].readonly = padIds.readonly;
|
||||||
|
|
||||||
//check if there is already a pad2sessions entry, if not, create one
|
//check if there is already a pad2sessions entry, if not, create one
|
||||||
if(!pad2sessions[padIds.padId])
|
if(!pad2sessions[padIds.padId])
|
||||||
{
|
{
|
||||||
pad2sessions[padIds.padId] = [];
|
pad2sessions[padIds.padId] = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
//Saves in pad2sessions that this session belongs to this pad
|
//Saves in pad2sessions that this session belongs to this pad
|
||||||
pad2sessions[padIds.padId].push(client.id);
|
pad2sessions[padIds.padId].push(client.id);
|
||||||
|
|
||||||
//prepare all values for the wire
|
//prepare all values for the wire
|
||||||
var atext = Changeset.cloneAText(pad.atext);
|
var atext = Changeset.cloneAText(pad.atext);
|
||||||
var attribsForWire = Changeset.prepareForWire(atext.attribs, pad.pool);
|
var attribsForWire = Changeset.prepareForWire(atext.attribs, pad.pool);
|
||||||
var apool = attribsForWire.pool.toJsonable();
|
var apool = attribsForWire.pool.toJsonable();
|
||||||
atext.attribs = attribsForWire.translated;
|
atext.attribs = attribsForWire.translated;
|
||||||
|
|
||||||
// Warning: never ever send padIds.padId to the client. If the
|
// Warning: never ever send padIds.padId to the client. If the
|
||||||
// client is read only you would open a security hole 1 swedish
|
// client is read only you would open a security hole 1 swedish
|
||||||
// mile wide...
|
// mile wide...
|
||||||
|
@ -978,7 +978,7 @@ function handleClientReady(client, message)
|
||||||
"fullWidth": false,
|
"fullWidth": false,
|
||||||
"hideSidebar": false
|
"hideSidebar": false
|
||||||
},
|
},
|
||||||
"abiwordAvailable": settings.abiwordAvailable(),
|
"abiwordAvailable": settings.abiwordAvailable(),
|
||||||
"plugins": {
|
"plugins": {
|
||||||
"plugins": plugins.plugins,
|
"plugins": plugins.plugins,
|
||||||
"parts": plugins.parts,
|
"parts": plugins.parts,
|
||||||
|
@ -992,7 +992,7 @@ function handleClientReady(client, message)
|
||||||
{
|
{
|
||||||
clientVars.userName = authorName;
|
clientVars.userName = authorName;
|
||||||
}
|
}
|
||||||
|
|
||||||
//If this is a reconnect, we don't have to send the client the ClientVars again
|
//If this is a reconnect, we don't have to send the client the ClientVars again
|
||||||
if(message.reconnect == true)
|
if(message.reconnect == true)
|
||||||
{
|
{
|
||||||
|
@ -1007,9 +1007,9 @@ function handleClientReady(client, message)
|
||||||
//Save the current revision in sessioninfos, should be the same as in clientVars
|
//Save the current revision in sessioninfos, should be the same as in clientVars
|
||||||
sessioninfos[client.id].rev = pad.getHeadRevisionNumber();
|
sessioninfos[client.id].rev = pad.getHeadRevisionNumber();
|
||||||
}
|
}
|
||||||
|
|
||||||
sessioninfos[client.id].author = author;
|
sessioninfos[client.id].author = author;
|
||||||
|
|
||||||
//prepare the notification for the other users on the pad, that this user joined
|
//prepare the notification for the other users on the pad, that this user joined
|
||||||
var messageToTheOtherUsers = {
|
var messageToTheOtherUsers = {
|
||||||
"type": "COLLABROOM",
|
"type": "COLLABROOM",
|
||||||
|
@ -1023,19 +1023,19 @@ function handleClientReady(client, message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//Add the authorname of this new User, if avaiable
|
//Add the authorname of this new User, if avaiable
|
||||||
if(authorName != null)
|
if(authorName != null)
|
||||||
{
|
{
|
||||||
messageToTheOtherUsers.data.userInfo.name = authorName;
|
messageToTheOtherUsers.data.userInfo.name = authorName;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Run trough all sessions of this pad
|
//Run trough all sessions of this pad
|
||||||
async.forEach(pad2sessions[padIds.padId], function(sessionID, callback)
|
async.forEach(pad2sessions[padIds.padId], function(sessionID, callback)
|
||||||
{
|
{
|
||||||
var author, socket, sessionAuthorName, sessionAuthorColorId;
|
var author, socket, sessionAuthorName, sessionAuthorColorId;
|
||||||
|
|
||||||
//Since sessioninfos might change while being enumerated, check if the
|
//Since sessioninfos might change while being enumerated, check if the
|
||||||
//sessionID is still assigned to a valid session
|
//sessionID is still assigned to a valid session
|
||||||
if(sessioninfos[sessionID] !== undefined &&
|
if(sessioninfos[sessionID] !== undefined &&
|
||||||
socketio.sockets.sockets[sessionID] !== undefined){
|
socketio.sockets.sockets[sessionID] !== undefined){
|
||||||
|
@ -1070,7 +1070,7 @@ function handleClientReady(client, message)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
],callback);
|
],callback);
|
||||||
},
|
},
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
//Jump over, if this session is the connection session
|
//Jump over, if this session is the connection session
|
||||||
|
@ -1078,7 +1078,7 @@ function handleClientReady(client, message)
|
||||||
{
|
{
|
||||||
//Send this Session the Notification about the new user
|
//Send this Session the Notification about the new user
|
||||||
socket.json.send(messageToTheOtherUsers);
|
socket.json.send(messageToTheOtherUsers);
|
||||||
|
|
||||||
//Send the new User a Notification about this other user
|
//Send the new User a Notification about this other user
|
||||||
var messageToNotifyTheClientAboutTheOthers = {
|
var messageToNotifyTheClientAboutTheOthers = {
|
||||||
"type": "COLLABROOM",
|
"type": "COLLABROOM",
|
||||||
|
@ -1096,7 +1096,7 @@ function handleClientReady(client, message)
|
||||||
client.json.send(messageToNotifyTheClientAboutTheOthers);
|
client.json.send(messageToNotifyTheClientAboutTheOthers);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
], callback);
|
], callback);
|
||||||
}, callback);
|
}, callback);
|
||||||
}
|
}
|
||||||
],function(err)
|
],function(err)
|
||||||
|
@ -1106,7 +1106,7 @@ function handleClientReady(client, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a request for a rough changeset, the timeslider client needs it
|
* Handles a request for a rough changeset, the timeslider client needs it
|
||||||
*/
|
*/
|
||||||
function handleChangesetRequest(client, message)
|
function handleChangesetRequest(client, message)
|
||||||
{
|
{
|
||||||
|
@ -1136,7 +1136,7 @@ function handleChangesetRequest(client, message)
|
||||||
messageLogger.warn("Dropped message, changeset request has no requestID!");
|
messageLogger.warn("Dropped message, changeset request has no requestID!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var granularity = message.data.granularity;
|
var granularity = message.data.granularity;
|
||||||
var start = message.data.start;
|
var start = message.data.start;
|
||||||
var end = start + (100 * granularity);
|
var end = start + (100 * granularity);
|
||||||
|
@ -1180,47 +1180,47 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
|
||||||
var composedChangesets = {};
|
var composedChangesets = {};
|
||||||
var revisionDate = [];
|
var revisionDate = [];
|
||||||
var lines;
|
var lines;
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
//get the pad from the database
|
//get the pad from the database
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
padManager.getPad(padId, function(err, _pad)
|
padManager.getPad(padId, function(err, _pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
pad = _pad;
|
pad = _pad;
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
//calculate the last full endnum
|
//calculate the last full endnum
|
||||||
var lastRev = pad.getHeadRevisionNumber();
|
var lastRev = pad.getHeadRevisionNumber();
|
||||||
if (endNum > lastRev+1) {
|
if (endNum > lastRev+1) {
|
||||||
endNum = lastRev+1;
|
endNum = lastRev+1;
|
||||||
}
|
}
|
||||||
endNum = Math.floor(endNum / granularity)*granularity;
|
endNum = Math.floor(endNum / granularity)*granularity;
|
||||||
|
|
||||||
var compositesChangesetNeeded = [];
|
var compositesChangesetNeeded = [];
|
||||||
var revTimesNeeded = [];
|
var revTimesNeeded = [];
|
||||||
|
|
||||||
//figure out which composite Changeset and revTimes we need, to load them in bulk
|
//figure out which composite Changeset and revTimes we need, to load them in bulk
|
||||||
var compositeStart = startNum;
|
var compositeStart = startNum;
|
||||||
while (compositeStart < endNum)
|
while (compositeStart < endNum)
|
||||||
{
|
{
|
||||||
var compositeEnd = compositeStart + granularity;
|
var compositeEnd = compositeStart + granularity;
|
||||||
|
|
||||||
//add the composite Changeset we needed
|
//add the composite Changeset we needed
|
||||||
compositesChangesetNeeded.push({start: compositeStart, end: compositeEnd});
|
compositesChangesetNeeded.push({start: compositeStart, end: compositeEnd});
|
||||||
|
|
||||||
//add the t1 time we need
|
//add the t1 time we need
|
||||||
revTimesNeeded.push(compositeStart == 0 ? 0 : compositeStart - 1);
|
revTimesNeeded.push(compositeStart == 0 ? 0 : compositeStart - 1);
|
||||||
//add the t2 time we need
|
//add the t2 time we need
|
||||||
revTimesNeeded.push(compositeEnd - 1);
|
revTimesNeeded.push(compositeEnd - 1);
|
||||||
|
|
||||||
compositeStart += granularity;
|
compositeStart += granularity;
|
||||||
}
|
}
|
||||||
|
|
||||||
//get all needed db values parallel
|
//get all needed db values parallel
|
||||||
async.parallel([
|
async.parallel([
|
||||||
function(callback)
|
function(callback)
|
||||||
|
@ -1257,58 +1257,58 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
lines = _lines;
|
lines = _lines;
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
], callback);
|
], callback);
|
||||||
},
|
},
|
||||||
//doesn't know what happens here excatly :/
|
//doesn't know what happens here excatly :/
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var compositeStart = startNum;
|
var compositeStart = startNum;
|
||||||
|
|
||||||
while (compositeStart < endNum)
|
while (compositeStart < endNum)
|
||||||
{
|
{
|
||||||
if (compositeStart + granularity > endNum)
|
if (compositeStart + granularity > endNum)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
var compositeEnd = compositeStart + granularity;
|
var compositeEnd = compositeStart + granularity;
|
||||||
|
|
||||||
var forwards = composedChangesets[compositeStart + "/" + compositeEnd];
|
var forwards = composedChangesets[compositeStart + "/" + compositeEnd];
|
||||||
var backwards = Changeset.inverse(forwards, lines.textlines, lines.alines, pad.apool());
|
var backwards = Changeset.inverse(forwards, lines.textlines, lines.alines, pad.apool());
|
||||||
|
|
||||||
Changeset.mutateAttributionLines(forwards, lines.alines, pad.apool());
|
Changeset.mutateAttributionLines(forwards, lines.alines, pad.apool());
|
||||||
Changeset.mutateTextLines(forwards, lines.textlines);
|
Changeset.mutateTextLines(forwards, lines.textlines);
|
||||||
|
|
||||||
var forwards2 = Changeset.moveOpsToNewPool(forwards, pad.apool(), apool);
|
var forwards2 = Changeset.moveOpsToNewPool(forwards, pad.apool(), apool);
|
||||||
var backwards2 = Changeset.moveOpsToNewPool(backwards, pad.apool(), apool);
|
var backwards2 = Changeset.moveOpsToNewPool(backwards, pad.apool(), apool);
|
||||||
|
|
||||||
var t1, t2;
|
var t1, t2;
|
||||||
if (compositeStart == 0)
|
if (compositeStart == 0)
|
||||||
{
|
{
|
||||||
t1 = revisionDate[0];
|
t1 = revisionDate[0];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
t1 = revisionDate[compositeStart - 1];
|
t1 = revisionDate[compositeStart - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
t2 = revisionDate[compositeEnd - 1];
|
t2 = revisionDate[compositeEnd - 1];
|
||||||
|
|
||||||
timeDeltas.push(t2 - t1);
|
timeDeltas.push(t2 - t1);
|
||||||
forwardsChangesets.push(forwards2);
|
forwardsChangesets.push(forwards2);
|
||||||
backwardsChangesets.push(backwards2);
|
backwardsChangesets.push(backwards2);
|
||||||
|
|
||||||
compositeStart += granularity;
|
compositeStart += granularity;
|
||||||
}
|
}
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
], function(err)
|
], function(err)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
callback(null, {forwardsChangesets: forwardsChangesets,
|
callback(null, {forwardsChangesets: forwardsChangesets,
|
||||||
backwardsChangesets: backwardsChangesets,
|
backwardsChangesets: backwardsChangesets,
|
||||||
apool: apool.toJsonable(),
|
apool: apool.toJsonable(),
|
||||||
|
@ -1323,7 +1323,7 @@ function getChangesetInfo(padId, startNum, endNum, granularity, callback)
|
||||||
* Tries to rebuild the getPadLines function of the original Etherpad
|
* Tries to rebuild the getPadLines function of the original Etherpad
|
||||||
* https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L263
|
* https://github.com/ether/pad/blob/master/etherpad/src/etherpad/control/pad/pad_changeset_control.js#L263
|
||||||
*/
|
*/
|
||||||
function getPadLines(padId, revNum, callback)
|
function getPadLines(padId, revNum, callback)
|
||||||
{
|
{
|
||||||
var atext;
|
var atext;
|
||||||
var result = {};
|
var result = {};
|
||||||
|
@ -1334,7 +1334,7 @@ function getPadLines(padId, revNum, callback)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
padManager.getPad(padId, function(err, _pad)
|
padManager.getPad(padId, function(err, _pad)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
pad = _pad;
|
pad = _pad;
|
||||||
callback();
|
callback();
|
||||||
|
@ -1396,14 +1396,14 @@ function composePadChangesets(padId, startNum, endNum, callback)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var changesetsNeeded=[];
|
var changesetsNeeded=[];
|
||||||
|
|
||||||
//create a array for all changesets, we will
|
//create a array for all changesets, we will
|
||||||
//replace the values with the changeset later
|
//replace the values with the changeset later
|
||||||
for(var r=startNum;r<endNum;r++)
|
for(var r=startNum;r<endNum;r++)
|
||||||
{
|
{
|
||||||
changesetsNeeded.push(r);
|
changesetsNeeded.push(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
//get all changesets
|
//get all changesets
|
||||||
async.forEach(changesetsNeeded, function(revNum,callback)
|
async.forEach(changesetsNeeded, function(revNum,callback)
|
||||||
{
|
{
|
||||||
|
@ -1420,13 +1420,13 @@ function composePadChangesets(padId, startNum, endNum, callback)
|
||||||
{
|
{
|
||||||
changeset = changesets[startNum];
|
changeset = changesets[startNum];
|
||||||
var pool = pad.apool();
|
var pool = pad.apool();
|
||||||
|
|
||||||
for(var r=startNum+1;r<endNum;r++)
|
for(var r=startNum+1;r<endNum;r++)
|
||||||
{
|
{
|
||||||
var cs = changesets[r];
|
var cs = changesets[r];
|
||||||
changeset = Changeset.compose(changeset, cs, pool);
|
changeset = Changeset.compose(changeset, cs, pool);
|
||||||
}
|
}
|
||||||
|
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This is the Socket.IO Router. It routes the Messages between the
|
* This is the Socket.IO Router. It routes the Messages between the
|
||||||
* components of the Server. The components are at the moment: pad and timeslider
|
* components of the Server. The components are at the moment: pad and timeslider
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -28,11 +28,11 @@ var securityManager = require("../db/SecurityManager");
|
||||||
* Saves all components
|
* Saves all components
|
||||||
* key is the component name
|
* key is the component name
|
||||||
* value is the component module
|
* value is the component module
|
||||||
*/
|
*/
|
||||||
var components = {};
|
var components = {};
|
||||||
|
|
||||||
var socket;
|
var socket;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* adds a component
|
* adds a component
|
||||||
*/
|
*/
|
||||||
|
@ -40,7 +40,7 @@ exports.addComponent = function(moduleName, module)
|
||||||
{
|
{
|
||||||
//save the component
|
//save the component
|
||||||
components[moduleName] = module;
|
components[moduleName] = module;
|
||||||
|
|
||||||
//give the module the socket
|
//give the module the socket
|
||||||
module.setSocketIO(socket);
|
module.setSocketIO(socket);
|
||||||
}
|
}
|
||||||
|
@ -52,11 +52,11 @@ exports.setSocketIO = function(_socket)
|
||||||
{
|
{
|
||||||
//save this socket internaly
|
//save this socket internaly
|
||||||
socket = _socket;
|
socket = _socket;
|
||||||
|
|
||||||
socket.sockets.on('connection', function(client)
|
socket.sockets.on('connection', function(client)
|
||||||
{
|
{
|
||||||
var clientAuthorized = false;
|
var clientAuthorized = false;
|
||||||
|
|
||||||
//wrap the original send function to log the messages
|
//wrap the original send function to log the messages
|
||||||
client._send = client.send;
|
client._send = client.send;
|
||||||
client.send = function(message)
|
client.send = function(message)
|
||||||
|
@ -64,19 +64,19 @@ exports.setSocketIO = function(_socket)
|
||||||
messageLogger.info("to " + client.id + ": " + stringifyWithoutPassword(message));
|
messageLogger.info("to " + client.id + ": " + stringifyWithoutPassword(message));
|
||||||
client._send(message);
|
client._send(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
//tell all components about this connect
|
//tell all components about this connect
|
||||||
for(var i in components)
|
for(var i in components)
|
||||||
{
|
{
|
||||||
components[i].handleConnect(client);
|
components[i].handleConnect(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
//try to handle the message of this client
|
//try to handle the message of this client
|
||||||
function handleMessage(message)
|
function handleMessage(message)
|
||||||
{
|
{
|
||||||
if(message.component && components[message.component])
|
if(message.component && components[message.component])
|
||||||
{
|
{
|
||||||
//check if component is registered in the components array
|
//check if component is registered in the components array
|
||||||
if(components[message.component])
|
if(components[message.component])
|
||||||
{
|
{
|
||||||
messageLogger.info("from " + client.id + ": " + stringifyWithoutPassword(message));
|
messageLogger.info("from " + client.id + ": " + stringifyWithoutPassword(message));
|
||||||
|
@ -87,8 +87,8 @@ exports.setSocketIO = function(_socket)
|
||||||
{
|
{
|
||||||
messageLogger.error("Can't route the message:" + stringifyWithoutPassword(message));
|
messageLogger.error("Can't route the message:" + stringifyWithoutPassword(message));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
client.on('message', function(message)
|
client.on('message', function(message)
|
||||||
{
|
{
|
||||||
if(message.protocolVersion && message.protocolVersion != 2)
|
if(message.protocolVersion && message.protocolVersion != 2)
|
||||||
|
@ -111,7 +111,7 @@ exports.setSocketIO = function(_socket)
|
||||||
securityManager.checkAccess (message.padId, message.sessionID, message.token, message.password, function(err, statusObject)
|
securityManager.checkAccess (message.padId, message.sessionID, message.token, message.password, function(err, statusObject)
|
||||||
{
|
{
|
||||||
ERR(err);
|
ERR(err);
|
||||||
|
|
||||||
//access was granted, mark the client as authorized and handle the message
|
//access was granted, mark the client as authorized and handle the message
|
||||||
if(statusObject.accessStatus == "grant")
|
if(statusObject.accessStatus == "grant")
|
||||||
{
|
{
|
||||||
|
@ -150,7 +150,7 @@ exports.setSocketIO = function(_socket)
|
||||||
function stringifyWithoutPassword(message)
|
function stringifyWithoutPassword(message)
|
||||||
{
|
{
|
||||||
var newMessage = {};
|
var newMessage = {};
|
||||||
|
|
||||||
for(var i in message)
|
for(var i in message)
|
||||||
{
|
{
|
||||||
if(i == "password" && message[i] != null)
|
if(i == "password" && message[i] != null)
|
||||||
|
@ -158,6 +158,6 @@ function stringifyWithoutPassword(message)
|
||||||
else
|
else
|
||||||
newMessage[i]=message[i];
|
newMessage[i]=message[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.stringify(newMessage);
|
return JSON.stringify(newMessage);
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ exports.createServer = function () {
|
||||||
version = version.substring(0, 7);
|
version = version.substring(0, 7);
|
||||||
console.log("Your Etherpad Lite git version is " + version);
|
console.log("Your Etherpad Lite git version is " + version);
|
||||||
}
|
}
|
||||||
catch(e)
|
catch(e)
|
||||||
{
|
{
|
||||||
console.warn("Can't get git version for server header\n" + e.message)
|
console.warn("Can't get git version for server header\n" + e.message)
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
|
|
||||||
//The Etherpad client side sends information about how a disconnect happen
|
//The Etherpad client side sends information about how a disconnect happen
|
||||||
args.app.post('/ep/pad/connection-diagnostic-info', function(req, res) {
|
args.app.post('/ep/pad/connection-diagnostic-info', function(req, res) {
|
||||||
new formidable.IncomingForm().parse(req, function(err, fields, files) {
|
new formidable.IncomingForm().parse(req, function(err, fields, files) {
|
||||||
console.log("DIAGNOSTIC-INFO: " + fields.diagnosticInfo);
|
console.log("DIAGNOSTIC-INFO: " + fields.diagnosticInfo);
|
||||||
res.end("OK");
|
res.end("OK");
|
||||||
});
|
});
|
||||||
|
@ -52,7 +52,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
|
|
||||||
//The Etherpad client side sends information about client side javscript errors
|
//The Etherpad client side sends information about client side javscript errors
|
||||||
args.app.post('/jserror', function(req, res) {
|
args.app.post('/jserror', function(req, res) {
|
||||||
new formidable.IncomingForm().parse(req, function(err, fields, files) {
|
new formidable.IncomingForm().parse(req, function(err, fields, files) {
|
||||||
console.error("CLIENT SIDE JAVASCRIPT ERROR: " + fields.errorInfo);
|
console.error("CLIENT SIDE JAVASCRIPT ERROR: " + fields.errorInfo);
|
||||||
res.end("OK");
|
res.end("OK");
|
||||||
});
|
});
|
||||||
|
|
|
@ -31,7 +31,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
//if abiword is disabled, skip handling this request
|
//if abiword is disabled, skip handling this request
|
||||||
if(settings.abiword == null) {
|
if(settings.abiword == null) {
|
||||||
next();
|
next();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
hasPadAccess(req, res, function() {
|
hasPadAccess(req, res, function() {
|
||||||
|
|
|
@ -7,7 +7,7 @@ var exporthtml = require("../../utils/ExportHtml");
|
||||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
//serve read only pad
|
//serve read only pad
|
||||||
args.app.get('/ro/:id', function(req, res)
|
args.app.get('/ro/:id', function(req, res)
|
||||||
{
|
{
|
||||||
var html;
|
var html;
|
||||||
var padId;
|
var padId;
|
||||||
var pad;
|
var pad;
|
||||||
|
@ -22,8 +22,8 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
|
|
||||||
padId = _padId;
|
padId = _padId;
|
||||||
|
|
||||||
//we need that to tell hasPadAcess about the pad
|
//we need that to tell hasPadAcess about the pad
|
||||||
req.params.pad = padId;
|
req.params.pad = padId;
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
|
|
|
@ -8,7 +8,7 @@ var webaccess = require("ep_etherpad-lite/node/hooks/express/webaccess");
|
||||||
var padMessageHandler = require("../../handler/PadMessageHandler");
|
var padMessageHandler = require("../../handler/PadMessageHandler");
|
||||||
|
|
||||||
var connect = require('connect');
|
var connect = require('connect');
|
||||||
|
|
||||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
//init socket.io and redirect all requests to the MessageHandler
|
//init socket.io and redirect all requests to the MessageHandler
|
||||||
var io = socketio.listen(args.server);
|
var io = socketio.listen(args.server);
|
||||||
|
@ -36,7 +36,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// the following has been successfully tested with the following browsers
|
// the following has been successfully tested with the following browsers
|
||||||
// works also behind reverse proxy
|
// works also behind reverse proxy
|
||||||
// Firefox 14.0.1
|
// Firefox 14.0.1
|
||||||
// IE8 with Native XMLHTTP support
|
// IE8 with Native XMLHTTP support
|
||||||
|
@ -49,7 +49,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
debug: function (str)
|
debug: function (str)
|
||||||
{
|
{
|
||||||
socketIOLogger.debug.apply(socketIOLogger, arguments);
|
socketIOLogger.debug.apply(socketIOLogger, arguments);
|
||||||
},
|
},
|
||||||
info: function (str)
|
info: function (str)
|
||||||
{
|
{
|
||||||
socketIOLogger.info.apply(socketIOLogger, arguments);
|
socketIOLogger.info.apply(socketIOLogger, arguments);
|
||||||
|
|
|
@ -26,7 +26,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
|
|
||||||
//serve pad.html under /p
|
//serve pad.html under /p
|
||||||
args.app.get('/p/:pad', function(req, res, next)
|
args.app.get('/p/:pad', function(req, res, next)
|
||||||
{
|
{
|
||||||
res.send(eejs.require("ep_etherpad-lite/templates/pad.html", {req: req}));
|
res.send(eejs.require("ep_etherpad-lite/templates/pad.html", {req: req}));
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -41,9 +41,9 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
|
|
||||||
var clientParts = _(plugins.parts)
|
var clientParts = _(plugins.parts)
|
||||||
.filter(function(part){ return _(part).has('client_hooks') });
|
.filter(function(part){ return _(part).has('client_hooks') });
|
||||||
|
|
||||||
var clientPlugins = {};
|
var clientPlugins = {};
|
||||||
|
|
||||||
_(clientParts).chain()
|
_(clientParts).chain()
|
||||||
.map(function(part){ return part.plugin })
|
.map(function(part){ return part.plugin })
|
||||||
.uniq()
|
.uniq()
|
||||||
|
@ -51,7 +51,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
clientPlugins[name] = _(plugins.plugins[name]).clone();
|
clientPlugins[name] = _(plugins.plugins[name]).clone();
|
||||||
delete clientPlugins[name]['package'];
|
delete clientPlugins[name]['package'];
|
||||||
});
|
});
|
||||||
|
|
||||||
res.header("Content-Type","application/json; charset=utf-8");
|
res.header("Content-Type","application/json; charset=utf-8");
|
||||||
res.write(JSON.stringify({"plugins": clientPlugins, "parts": clientParts}));
|
res.write(JSON.stringify({"plugins": clientPlugins, "parts": clientParts}));
|
||||||
res.end();
|
res.end();
|
||||||
|
|
|
@ -75,7 +75,7 @@ exports.basicAuth = function (req, res, next) {
|
||||||
Note that the process could stop already in step 3 with a redirect to login page.
|
Note that the process could stop already in step 3 with a redirect to login page.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
authorize(function (ok) {
|
authorize(function (ok) {
|
||||||
if (ok) return next();
|
if (ok) return next();
|
||||||
authenticate(function (ok) {
|
authenticate(function (ok) {
|
||||||
|
@ -105,7 +105,7 @@ exports.expressConfigure = function (hook_name, args, cb) {
|
||||||
exports.sessionStore = new express.session.MemoryStore();
|
exports.sessionStore = new express.session.MemoryStore();
|
||||||
exports.secret = randomString(32);
|
exports.secret = randomString(32);
|
||||||
}
|
}
|
||||||
|
|
||||||
args.app.use(express.cookieParser(exports.secret));
|
args.app.use(express.cookieParser(exports.secret));
|
||||||
|
|
||||||
args.app.sessionStore = exports.sessionStore;
|
args.app.sessionStore = exports.sessionStore;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
/**
|
/**
|
||||||
* This module is started with bin/run.sh. It sets up a Express HTTP and a Socket.IO Server.
|
* This module is started with bin/run.sh. It sets up a Express HTTP and a Socket.IO Server.
|
||||||
* Static file Requests are answered directly from this module, Socket.IO messages are passed
|
* Static file Requests are answered directly from this module, Socket.IO messages are passed
|
||||||
* to MessageHandler and minfied requests are passed to minified.
|
* to MessageHandler and minfied requests are passed to minified.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ async.waterfall([
|
||||||
callback(er)
|
callback(er)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
// load everything
|
// load everything
|
||||||
function(callback) {
|
function(callback) {
|
||||||
settings = require('./utils/Settings');
|
settings = require('./utils/Settings');
|
||||||
|
@ -54,7 +54,7 @@ async.waterfall([
|
||||||
log4js.setGlobalLogLevel(settings.loglevel);
|
log4js.setGlobalLogLevel(settings.loglevel);
|
||||||
callback();
|
callback();
|
||||||
},
|
},
|
||||||
|
|
||||||
//initalize the database
|
//initalize the database
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
|
@ -80,6 +80,6 @@ async.waterfall([
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
hooks.callAll("createServer", {});
|
hooks.callAll("createServer", {});
|
||||||
callback(null);
|
callback(null);
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var util = require('util');
|
var util = require('util');
|
||||||
var spawn = require('child_process').spawn;
|
var spawn = require('child_process').spawn;
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
|
@ -35,7 +35,7 @@ if(os.type().indexOf("Windows") > -1)
|
||||||
{
|
{
|
||||||
//span an abiword process to perform the conversion
|
//span an abiword process to perform the conversion
|
||||||
var abiword = spawn(settings.abiword, ["--to=" + task.destFile, task.srcFile]);
|
var abiword = spawn(settings.abiword, ["--to=" + task.destFile, task.srcFile]);
|
||||||
|
|
||||||
//delegate the processing of stdout to another function
|
//delegate the processing of stdout to another function
|
||||||
abiword.stdout.on('data', function (data)
|
abiword.stdout.on('data', function (data)
|
||||||
{
|
{
|
||||||
|
@ -44,7 +44,7 @@ if(os.type().indexOf("Windows") > -1)
|
||||||
});
|
});
|
||||||
|
|
||||||
//append error messages to the buffer
|
//append error messages to the buffer
|
||||||
abiword.stderr.on('data', function (data)
|
abiword.stderr.on('data', function (data)
|
||||||
{
|
{
|
||||||
stdoutBuffer += data.toString();
|
stdoutBuffer += data.toString();
|
||||||
});
|
});
|
||||||
|
@ -64,7 +64,7 @@ if(os.type().indexOf("Windows") > -1)
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.convertFile = function(srcFile, destFile, type, callback)
|
exports.convertFile = function(srcFile, destFile, type, callback)
|
||||||
{
|
{
|
||||||
doConvertTask({"srcFile": srcFile, "destFile": destFile, "type": type}, callback);
|
doConvertTask({"srcFile": srcFile, "destFile": destFile, "type": type}, callback);
|
||||||
|
@ -80,16 +80,16 @@ else
|
||||||
var spawnAbiword = function (){
|
var spawnAbiword = function (){
|
||||||
abiword = spawn(settings.abiword, ["--plugin", "AbiCommand"]);
|
abiword = spawn(settings.abiword, ["--plugin", "AbiCommand"]);
|
||||||
var stdoutBuffer = "";
|
var stdoutBuffer = "";
|
||||||
var firstPrompt = true;
|
var firstPrompt = true;
|
||||||
|
|
||||||
//append error messages to the buffer
|
//append error messages to the buffer
|
||||||
abiword.stderr.on('data', function (data)
|
abiword.stderr.on('data', function (data)
|
||||||
{
|
{
|
||||||
stdoutBuffer += data.toString();
|
stdoutBuffer += data.toString();
|
||||||
});
|
});
|
||||||
|
|
||||||
//abiword died, let's restart abiword and return an error with the callback
|
//abiword died, let's restart abiword and return an error with the callback
|
||||||
abiword.on('exit', function (code)
|
abiword.on('exit', function (code)
|
||||||
{
|
{
|
||||||
spawnAbiword();
|
spawnAbiword();
|
||||||
stdoutCallback("Abiword died with exit code " + code);
|
stdoutCallback("Abiword died with exit code " + code);
|
||||||
|
@ -100,16 +100,16 @@ else
|
||||||
{
|
{
|
||||||
//add data to buffer
|
//add data to buffer
|
||||||
stdoutBuffer+=data.toString();
|
stdoutBuffer+=data.toString();
|
||||||
|
|
||||||
//we're searching for the prompt, cause this means everything we need is in the buffer
|
//we're searching for the prompt, cause this means everything we need is in the buffer
|
||||||
if(stdoutBuffer.search("AbiWord:>") != -1)
|
if(stdoutBuffer.search("AbiWord:>") != -1)
|
||||||
{
|
{
|
||||||
//filter the feedback message
|
//filter the feedback message
|
||||||
var err = stdoutBuffer.search("OK") != -1 ? null : stdoutBuffer;
|
var err = stdoutBuffer.search("OK") != -1 ? null : stdoutBuffer;
|
||||||
|
|
||||||
//reset the buffer
|
//reset the buffer
|
||||||
stdoutBuffer = "";
|
stdoutBuffer = "";
|
||||||
|
|
||||||
//call the callback with the error message
|
//call the callback with the error message
|
||||||
//skip the first prompt
|
//skip the first prompt
|
||||||
if(stdoutCallback != null && !firstPrompt)
|
if(stdoutCallback != null && !firstPrompt)
|
||||||
|
@ -117,7 +117,7 @@ else
|
||||||
stdoutCallback(err);
|
stdoutCallback(err);
|
||||||
stdoutCallback = null;
|
stdoutCallback = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
firstPrompt = false;
|
firstPrompt = false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -127,7 +127,7 @@ else
|
||||||
doConvertTask = function(task, callback)
|
doConvertTask = function(task, callback)
|
||||||
{
|
{
|
||||||
abiword.stdin.write("convert " + task.srcFile + " " + task.destFile + " " + task.type + "\n");
|
abiword.stdin.write("convert " + task.srcFile + " " + task.destFile + " " + task.type + "\n");
|
||||||
|
|
||||||
//create a callback that calls the task callback and the caller callback
|
//create a callback that calls the task callback and the caller callback
|
||||||
stdoutCallback = function (err)
|
stdoutCallback = function (err)
|
||||||
{
|
{
|
||||||
|
@ -136,12 +136,12 @@ else
|
||||||
task.callback(err);
|
task.callback(err);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
//Queue with the converts we have to do
|
//Queue with the converts we have to do
|
||||||
var queue = async.queue(doConvertTask, 1);
|
var queue = async.queue(doConvertTask, 1);
|
||||||
|
|
||||||
exports.convertFile = function(srcFile, destFile, type, callback)
|
exports.convertFile = function(srcFile, destFile, type, callback)
|
||||||
{
|
{
|
||||||
queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback});
|
queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback});
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2011 Adrian Lang
|
* Copyright 2011 Adrian Lang
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS-IS" BASIS,
|
* distributed under the License is distributed on an "AS-IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
/**
|
/**
|
||||||
* Copyright 2009 Google Inc.
|
* Copyright 2009 Google Inc.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS-IS" BASIS,
|
* distributed under the License is distributed on an "AS-IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
@ -142,7 +142,7 @@ function getHTMLFromAtext(pad, atext)
|
||||||
assem.append(tags[i]);
|
assem.append(tags[i]);
|
||||||
assem.append('>');
|
assem.append('>');
|
||||||
}
|
}
|
||||||
|
|
||||||
function orderdCloseTags(tags2close)
|
function orderdCloseTags(tags2close)
|
||||||
{
|
{
|
||||||
for(var i=0;i<openTags.length;i++)
|
for(var i=0;i<openTags.length;i++)
|
||||||
|
@ -246,9 +246,9 @@ function getHTMLFromAtext(pad, atext)
|
||||||
tags2close.push(i);
|
tags2close.push(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
orderdCloseTags(tags2close);
|
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)
|
||||||
|
@ -264,16 +264,16 @@ 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
|
//removes the characters with the code 12. Don't know where they come
|
||||||
//from but they break the abiword parser and are completly useless
|
//from but they break the abiword parser and are completly useless
|
||||||
s = s.replace(String.fromCharCode(12), "");
|
s = s.replace(String.fromCharCode(12), "");
|
||||||
|
|
||||||
assem.append(_encodeWhitespace(Security.escapeHTML(s)));
|
assem.append(_encodeWhitespace(Security.escapeHTML(s)));
|
||||||
} // end iteration over spans in line
|
} // end iteration over spans in line
|
||||||
|
|
||||||
var tags2close = [];
|
var tags2close = [];
|
||||||
for (var i = propVals.length - 1; i >= 0; i--)
|
for (var i = propVals.length - 1; i >= 0; i--)
|
||||||
{
|
{
|
||||||
|
@ -283,7 +283,7 @@ function getHTMLFromAtext(pad, atext)
|
||||||
propVals[i] = false;
|
propVals[i] = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
orderdCloseTags(tags2close);
|
orderdCloseTags(tags2close);
|
||||||
} // end processNextChars
|
} // end processNextChars
|
||||||
if (urls)
|
if (urls)
|
||||||
|
@ -317,7 +317,7 @@ function getHTMLFromAtext(pad, atext)
|
||||||
{
|
{
|
||||||
var line = _analyzeLine(textLines[i], attribLines[i], apool);
|
var line = _analyzeLine(textLines[i], attribLines[i], apool);
|
||||||
var lineContent = getLineHTML(line.text, line.aline);
|
var lineContent = getLineHTML(line.text, line.aline);
|
||||||
|
|
||||||
if (line.listLevel)//If we are inside a list
|
if (line.listLevel)//If we are inside a list
|
||||||
{
|
{
|
||||||
// do list stuff
|
// do list stuff
|
||||||
|
@ -401,8 +401,8 @@ function getHTMLFromAtext(pad, atext)
|
||||||
pieces.push('</li></ul>');
|
pieces.push('</li></ul>');
|
||||||
}
|
}
|
||||||
lists.length--;
|
lists.length--;
|
||||||
}
|
}
|
||||||
var lineContentFromHook = hooks.callAllStr("getLineHTMLForExport",
|
var lineContentFromHook = hooks.callAllStr("getLineHTMLForExport",
|
||||||
{
|
{
|
||||||
line: line,
|
line: line,
|
||||||
apool: apool,
|
apool: apool,
|
||||||
|
@ -412,14 +412,14 @@ function getHTMLFromAtext(pad, atext)
|
||||||
if (lineContentFromHook)
|
if (lineContentFromHook)
|
||||||
{
|
{
|
||||||
pieces.push(lineContentFromHook, '');
|
pieces.push(lineContentFromHook, '');
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
pieces.push(lineContent, '<br>');
|
pieces.push(lineContent, '<br>');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (var k = lists.length - 1; k >= 0; k--)
|
for (var k = lists.length - 1; k >= 0; k--)
|
||||||
{
|
{
|
||||||
if(lists[k][1] == "number")
|
if(lists[k][1] == "number")
|
||||||
|
@ -480,14 +480,14 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
var head =
|
var head =
|
||||||
(noDocType ? '' : '<!doctype html>\n') +
|
(noDocType ? '' : '<!doctype html>\n') +
|
||||||
'<html lang="en">\n' + (noDocType ? '' : '<head>\n' +
|
'<html lang="en">\n' + (noDocType ? '' : '<head>\n' +
|
||||||
'<title>' + Security.escapeHTML(padId) + '</title>\n' +
|
'<title>' + Security.escapeHTML(padId) + '</title>\n' +
|
||||||
'<meta charset="utf-8">\n' +
|
'<meta charset="utf-8">\n' +
|
||||||
'<style> * { font-family: arial, sans-serif;\n' +
|
'<style> * { font-family: arial, sans-serif;\n' +
|
||||||
'font-size: 13px;\n' +
|
'font-size: 13px;\n' +
|
||||||
'line-height: 17px; }' +
|
'line-height: 17px; }' +
|
||||||
'ul.indent { list-style-type: none; }' +
|
'ul.indent { list-style-type: none; }' +
|
||||||
'ol { list-style-type: decimal; }' +
|
'ol { list-style-type: decimal; }' +
|
||||||
'ol ol { list-style-type: lower-latin; }' +
|
'ol ol { list-style-type: lower-latin; }' +
|
||||||
|
@ -497,7 +497,7 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
|
||||||
'ol ol ol ol ol ol{ list-style-type: lower-roman; }' +
|
'ol ol ol ol ol ol{ list-style-type: lower-roman; }' +
|
||||||
'ol ol ol ol ol ol ol { list-style-type: decimal; }' +
|
'ol ol ol ol ol ol ol { list-style-type: decimal; }' +
|
||||||
'ol ol ol ol ol ol ol ol{ list-style-type: lower-latin; }' +
|
'ol ol ol ol ol ol ol ol{ list-style-type: lower-latin; }' +
|
||||||
'</style>\n' + '</head>\n') +
|
'</style>\n' + '</head>\n') +
|
||||||
'<body>';
|
'<body>';
|
||||||
|
|
||||||
var foot = '</body>\n</html>\n';
|
var foot = '</body>\n</html>\n';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* This Module manages all /minified/* requests. It controls the
|
* This Module manages all /minified/* requests. It controls the
|
||||||
* minification && compression of Javascript and CSS.
|
* minification && compression of Javascript and CSS.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
||||||
|
@ -149,7 +149,7 @@ function minify(req, res, next)
|
||||||
} else {
|
} else {
|
||||||
res.writeHead(404, {});
|
res.writeHead(404, {});
|
||||||
res.end();
|
res.end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle static files for plugins/libraries:
|
/* Handle static files for plugins/libraries:
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* The Settings Modul reads the settings out of settings.json and provides
|
* The Settings Modul reads the settings out of settings.json and provides
|
||||||
* this information to the other modules
|
* this information to the other modules
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -43,7 +43,7 @@ exports.favicon = "favicon.ico";
|
||||||
* The IP ep-lite should listen to
|
* The IP ep-lite should listen to
|
||||||
*/
|
*/
|
||||||
exports.ip = "0.0.0.0";
|
exports.ip = "0.0.0.0";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The Port ep-lite should listen to
|
* The Port ep-lite should listen to
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -5,11 +5,11 @@ function customError(message, errorName)
|
||||||
{
|
{
|
||||||
this.name = errorName || "Error";
|
this.name = errorName || "Error";
|
||||||
this.message = message;
|
this.message = message;
|
||||||
|
|
||||||
var stackParts = new Error().stack.split("\n");
|
var stackParts = new Error().stack.split("\n");
|
||||||
stackParts.splice(0,2);
|
stackParts.splice(0,2);
|
||||||
stackParts.unshift(this.name + ": " + message);
|
stackParts.unshift(this.name + ": " + message);
|
||||||
|
|
||||||
this.stack = stackParts.join("\n");
|
this.stack = stackParts.join("\n");
|
||||||
}
|
}
|
||||||
customError.prototype = Error.prototype;
|
customError.prototype = Error.prototype;
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"keywords" : ["etherpad", "realtime", "collaborative", "editor"],
|
"keywords" : ["etherpad", "realtime", "collaborative", "editor"],
|
||||||
"author" : "Peter 'Pita' Martischka <petermartischka@googlemail.com> - Primary Technology Ltd",
|
"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" },
|
||||||
{ "name": "Marcel Klehr" }
|
{ "name": "Marcel Klehr" }
|
||||||
|
@ -43,6 +43,6 @@
|
||||||
},
|
},
|
||||||
"engines" : { "node" : ">=0.6.0",
|
"engines" : { "node" : ">=0.6.0",
|
||||||
"npm" : ">=1.0"
|
"npm" : ">=1.0"
|
||||||
},
|
},
|
||||||
"version" : "1.1.4"
|
"version" : "1.1.4"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,130 +1,130 @@
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: #333;
|
color: #333;
|
||||||
font: 14px helvetica, sans-serif;
|
font: 14px helvetica, sans-serif;
|
||||||
background: #ddd;
|
background: #ddd;
|
||||||
background: -webkit-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
background: -webkit-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
||||||
background: -moz-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
background: -moz-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
||||||
background: -ms-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
background: -ms-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
||||||
background: -o-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
background: -o-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
||||||
border-top: 8px solid rgba(51,51,51,.8);
|
border-top: 8px solid rgba(51,51,51,.8);
|
||||||
}
|
}
|
||||||
#wrapper {
|
#wrapper {
|
||||||
margin-top: 160px;
|
margin-top: 160px;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
opacity: .9;
|
opacity: .9;
|
||||||
box-shadow: 0px 1px 8px rgba(0,0,0,0.3);
|
box-shadow: 0px 1px 8px rgba(0,0,0,0.3);
|
||||||
max-width: 700px;
|
max-width: 700px;
|
||||||
margin: auto;
|
margin: auto;
|
||||||
border-radius: 0 0 7px 7px;
|
border-radius: 0 0 7px 7px;
|
||||||
}
|
}
|
||||||
h1 {
|
h1 {
|
||||||
font-size: 29px;
|
font-size: 29px;
|
||||||
}
|
}
|
||||||
h2 {
|
h2 {
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
}
|
}
|
||||||
.separator {
|
.separator {
|
||||||
margin: 10px 0;
|
margin: 10px 0;
|
||||||
height: 1px;
|
height: 1px;
|
||||||
background: #aaa;
|
background: #aaa;
|
||||||
background: -webkit-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
|
background: -webkit-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
|
||||||
background: -moz-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
|
background: -moz-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
|
||||||
background: -ms-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
|
background: -ms-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
|
||||||
background: -o-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
|
background: -o-linear-gradient(left, #fff, #aaa 20%, #aaa 80%, #fff);
|
||||||
}
|
}
|
||||||
form {
|
form {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0;
|
||||||
}
|
}
|
||||||
#inner {
|
#inner {
|
||||||
width: 300px;
|
width: 300px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
input {
|
input {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
input[type="button"] {
|
input[type="button"] {
|
||||||
padding: 4px 6px;
|
padding: 4px 6px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
input[type="button"].do-install, input[type="button"].do-uninstall {
|
input[type="button"].do-install, input[type="button"].do-uninstall {
|
||||||
float: right;
|
float: right;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
input[type="button"]#do-search {
|
input[type="button"]#do-search {
|
||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
input[type="text"] {
|
input[type="text"] {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
*padding: 0; /* IE7 hack */
|
*padding: 0; /* IE7 hack */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
outline: none;
|
outline: none;
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
margin: 0 0 5px 0;
|
margin: 0 0 5px 0;
|
||||||
max-width: 500px;
|
max-width: 500px;
|
||||||
}
|
}
|
||||||
table {
|
table {
|
||||||
border: 1px solid #ddd;
|
border: 1px solid #ddd;
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 20px 0;
|
margin: 20px 0;
|
||||||
}
|
}
|
||||||
table thead tr {
|
table thead tr {
|
||||||
background: #eee;
|
background: #eee;
|
||||||
}
|
}
|
||||||
td, th {
|
td, th {
|
||||||
padding: 5px;
|
padding: 5px;
|
||||||
}
|
}
|
||||||
.template {
|
.template {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
.dialog {
|
.dialog {
|
||||||
display: none;
|
display: none;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 50%;
|
left: 50%;
|
||||||
top: 50%;
|
top: 50%;
|
||||||
width: 700px;
|
width: 700px;
|
||||||
height: 500px;
|
height: 500px;
|
||||||
margin-left: -350px;
|
margin-left: -350px;
|
||||||
margin-top: -250px;
|
margin-top: -250px;
|
||||||
border: 3px solid #999;
|
border: 3px solid #999;
|
||||||
background: #eee;
|
background: #eee;
|
||||||
}
|
}
|
||||||
.dialog .title {
|
.dialog .title {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
border-bottom: 3px solid #999;
|
border-bottom: 3px solid #999;
|
||||||
font-size: 24px;
|
font-size: 24px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
.dialog .title .close {
|
.dialog .title .close {
|
||||||
float: right;
|
float: right;
|
||||||
padding: 1px 10px;
|
padding: 1px 10px;
|
||||||
}
|
}
|
||||||
.dialog .history {
|
.dialog .history {
|
||||||
background: #222;
|
background: #222;
|
||||||
color: #eee;
|
color: #eee;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 41px;
|
top: 41px;
|
||||||
bottom: 10px;
|
bottom: 10px;
|
||||||
left: 10px;
|
left: 10px;
|
||||||
right: 10px;
|
right: 10px;
|
||||||
padding: 2px;
|
padding: 2px;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
}
|
}
|
||||||
.settings {
|
.settings {
|
||||||
margin-top:10px;
|
margin-top:10px;
|
||||||
width:100%;
|
width:100%;
|
||||||
min-height:600px;
|
min-height:600px;
|
||||||
}
|
}
|
||||||
#response{
|
#response{
|
||||||
display:inline;
|
display:inline;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ ul.list-indent8 { list-style-type: none; }
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
#outerdocbody {
|
#outerdocbody {
|
||||||
background-color: #fff;
|
background-color: #fff;
|
||||||
|
|
|
@ -775,7 +775,7 @@ input[type=checkbox] {
|
||||||
border-left: 1px solid #ccc !important;
|
border-left: 1px solid #ccc !important;
|
||||||
width: 185px !important;
|
width: 185px !important;
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 600px) {
|
@media screen and (max-width: 600px) {
|
||||||
.toolbar ul li.separator {
|
.toolbar ul li.separator {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -784,13 +784,13 @@ input[type=checkbox] {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media screen and (max-width: 400px){
|
@media screen and (max-width: 400px){
|
||||||
#editorcontainer {
|
#editorcontainer {
|
||||||
top: 68px;
|
top: 68px;
|
||||||
}
|
}
|
||||||
#editbar {
|
#editbar {
|
||||||
height: 62px;
|
height: 62px;
|
||||||
}
|
}
|
||||||
.toolbar ul.menu_right {
|
.toolbar ul.menu_right {
|
||||||
float: left;
|
float: left;
|
||||||
margin-top:2px;
|
margin-top:2px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,23 +4,23 @@ var _ = require('./underscore');
|
||||||
|
|
||||||
var lineMarkerAttribute = 'lmkr';
|
var lineMarkerAttribute = 'lmkr';
|
||||||
|
|
||||||
// If one of these attributes are set to the first character of a
|
// If one of these attributes are set to the first character of a
|
||||||
// line it is considered as a line attribute marker i.e. attributes
|
// line it is considered as a line attribute marker i.e. attributes
|
||||||
// set on this marker are applied to the whole line.
|
// set on this marker are applied to the whole line.
|
||||||
// The list attribute is only maintained for compatibility reasons
|
// The list attribute is only maintained for compatibility reasons
|
||||||
var lineAttributes = [lineMarkerAttribute,'list'];
|
var lineAttributes = [lineMarkerAttribute,'list'];
|
||||||
|
|
||||||
/*
|
/*
|
||||||
The Attribute manager builds changesets based on a document
|
The Attribute manager builds changesets based on a document
|
||||||
representation for setting and removing range or line-based attributes.
|
representation for setting and removing range or line-based attributes.
|
||||||
|
|
||||||
@param rep the document representation to be used
|
@param rep the document representation to be used
|
||||||
@param applyChangesetCallback this callback will be called
|
@param applyChangesetCallback this callback will be called
|
||||||
once a changeset has been built.
|
once a changeset has been built.
|
||||||
|
|
||||||
|
|
||||||
A document representation contains
|
A document representation contains
|
||||||
- an array `alines` containing 1 attributes string for each line
|
- an array `alines` containing 1 attributes string for each line
|
||||||
- an Attribute pool `apool`
|
- an Attribute pool `apool`
|
||||||
- a SkipList `lines` containing the text lines of the document.
|
- a SkipList `lines` containing the text lines of the document.
|
||||||
*/
|
*/
|
||||||
|
@ -30,7 +30,7 @@ var AttributeManager = function(rep, applyChangesetCallback)
|
||||||
this.rep = rep;
|
this.rep = rep;
|
||||||
this.applyChangesetCallback = applyChangesetCallback;
|
this.applyChangesetCallback = applyChangesetCallback;
|
||||||
this.author = '';
|
this.author = '';
|
||||||
|
|
||||||
// If the first char in a line has one of the following attributes
|
// If the first char in a line has one of the following attributes
|
||||||
// it will be considered as a line marker
|
// it will be considered as a line marker
|
||||||
};
|
};
|
||||||
|
@ -38,19 +38,19 @@ var AttributeManager = function(rep, applyChangesetCallback)
|
||||||
AttributeManager.lineAttributes = lineAttributes;
|
AttributeManager.lineAttributes = lineAttributes;
|
||||||
|
|
||||||
AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
||||||
|
|
||||||
applyChangeset: function(changeset){
|
applyChangeset: function(changeset){
|
||||||
if(!this.applyChangesetCallback) return changeset;
|
if(!this.applyChangesetCallback) return changeset;
|
||||||
|
|
||||||
var cs = changeset.toString();
|
var cs = changeset.toString();
|
||||||
if (!Changeset.isIdentity(cs))
|
if (!Changeset.isIdentity(cs))
|
||||||
{
|
{
|
||||||
this.applyChangesetCallback(cs);
|
this.applyChangesetCallback(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
return changeset;
|
return changeset;
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sets attributes on a range
|
Sets attributes on a range
|
||||||
@param start [row, col] tuple pointing to the start of the range
|
@param start [row, col] tuple pointing to the start of the range
|
||||||
|
@ -65,22 +65,22 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
||||||
return this.applyChangeset(builder);
|
return this.applyChangeset(builder);
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Returns if the line already has a line marker
|
Returns if the line already has a line marker
|
||||||
@param lineNum: the number of the line
|
@param lineNum: the number of the line
|
||||||
*/
|
*/
|
||||||
lineHasMarker: function(lineNum){
|
lineHasMarker: function(lineNum){
|
||||||
var that = this;
|
var that = this;
|
||||||
|
|
||||||
return _.find(lineAttributes, function(attribute){
|
return _.find(lineAttributes, function(attribute){
|
||||||
return that.getAttributeOnLine(lineNum, attribute) != '';
|
return that.getAttributeOnLine(lineNum, attribute) != '';
|
||||||
}) !== undefined;
|
}) !== undefined;
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Gets a specified attribute on a line
|
Gets a specified attribute on a line
|
||||||
@param lineNum: the number of the line to set the attribute for
|
@param lineNum: the number of the line to set the attribute for
|
||||||
@param attributeKey: the name of the attribute to get, e.g. list
|
@param attributeKey: the name of the attribute to get, e.g. list
|
||||||
*/
|
*/
|
||||||
getAttributeOnLine: function(lineNum, attributeName){
|
getAttributeOnLine: function(lineNum, attributeName){
|
||||||
// get `attributeName` attribute of first char of line
|
// get `attributeName` attribute of first char of line
|
||||||
|
@ -95,26 +95,26 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
||||||
}
|
}
|
||||||
return '';
|
return '';
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sets a specified attribute on a line
|
Sets a specified attribute on a line
|
||||||
@param lineNum: the number of the line to set the attribute for
|
@param lineNum: the number of the line to set the attribute for
|
||||||
@param attributeKey: the name of the attribute to set, e.g. list
|
@param attributeKey: the name of the attribute to set, e.g. list
|
||||||
@param attributeValue: an optional parameter to pass to the attribute (e.g. indention level)
|
@param attributeValue: an optional parameter to pass to the attribute (e.g. indention level)
|
||||||
|
|
||||||
*/
|
*/
|
||||||
setAttributeOnLine: function(lineNum, attributeName, attributeValue){
|
setAttributeOnLine: function(lineNum, attributeName, attributeValue){
|
||||||
var loc = [0,0];
|
var loc = [0,0];
|
||||||
var builder = Changeset.builder(this.rep.lines.totalWidth());
|
var builder = Changeset.builder(this.rep.lines.totalWidth());
|
||||||
var hasMarker = this.lineHasMarker(lineNum);
|
var hasMarker = this.lineHasMarker(lineNum);
|
||||||
|
|
||||||
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
|
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
|
||||||
|
|
||||||
if(hasMarker){
|
if(hasMarker){
|
||||||
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 1]), [
|
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 1]), [
|
||||||
[attributeName, attributeValue]
|
[attributeName, attributeValue]
|
||||||
], this.rep.apool);
|
], this.rep.apool);
|
||||||
}else{
|
}else{
|
||||||
// add a line marker
|
// add a line marker
|
||||||
builder.insert('*', [
|
builder.insert('*', [
|
||||||
['author', this.author],
|
['author', this.author],
|
||||||
|
@ -123,10 +123,10 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
||||||
[attributeName, attributeValue]
|
[attributeName, attributeValue]
|
||||||
], this.rep.apool);
|
], this.rep.apool);
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.applyChangeset(builder);
|
return this.applyChangeset(builder);
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Removes a specified attribute on a line
|
Removes a specified attribute on a line
|
||||||
@param lineNum: the number of the affected line
|
@param lineNum: the number of the affected line
|
||||||
|
@ -134,19 +134,19 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
||||||
|
|
||||||
*/
|
*/
|
||||||
removeAttributeOnLine: function(lineNum, attributeName, attributeValue){
|
removeAttributeOnLine: function(lineNum, attributeName, attributeValue){
|
||||||
|
|
||||||
var loc = [0,0];
|
var loc = [0,0];
|
||||||
var builder = Changeset.builder(this.rep.lines.totalWidth());
|
var builder = Changeset.builder(this.rep.lines.totalWidth());
|
||||||
var hasMarker = this.lineHasMarker(lineNum);
|
var hasMarker = this.lineHasMarker(lineNum);
|
||||||
|
|
||||||
if(hasMarker){
|
if(hasMarker){
|
||||||
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
|
ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0]));
|
||||||
ChangesetUtils.buildRemoveRange(this.rep, builder, loc, (loc = [lineNum, 1]));
|
ChangesetUtils.buildRemoveRange(this.rep, builder, loc, (loc = [lineNum, 1]));
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.applyChangeset(builder);
|
return this.applyChangeset(builder);
|
||||||
},
|
},
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Sets a specified attribute on a line
|
Sets a specified attribute on a line
|
||||||
@param lineNum: the number of the line to set the attribute for
|
@param lineNum: the number of the line to set the attribute for
|
||||||
|
@ -157,7 +157,7 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({
|
||||||
return this.getAttributeOnLine(attributeName) ?
|
return this.getAttributeOnLine(attributeName) ?
|
||||||
this.removeAttributeOnLine(lineNum, attributeName) :
|
this.removeAttributeOnLine(lineNum, attributeName) :
|
||||||
this.setAttributeOnLine(lineNum, attributeName, attributeValue);
|
this.setAttributeOnLine(lineNum, attributeName, attributeValue);
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -91,6 +91,6 @@ AttributePool.prototype.fromJsonable = function (obj) {
|
||||||
}
|
}
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
module.exports = AttributePool;
|
module.exports = AttributePool;
|
|
@ -42,7 +42,7 @@ exports.error = function error(msg) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is user for assertions with Messages
|
* This method is user for assertions with Messages
|
||||||
* if assert fails, the error function called.
|
* if assert fails, the error function called.
|
||||||
* @param b {boolean} assertion condition
|
* @param b {boolean} assertion condition
|
||||||
* @param msgParts {string} error to be passed if it fails
|
* @param msgParts {string} error to be passed if it fails
|
||||||
|
@ -76,7 +76,7 @@ exports.numToString = function (num) {
|
||||||
* Converts stuff before $ to base 10
|
* Converts stuff before $ to base 10
|
||||||
* @obsolete not really used anywhere??
|
* @obsolete not really used anywhere??
|
||||||
* @param cs {string} the string
|
* @param cs {string} the string
|
||||||
* @return integer
|
* @return integer
|
||||||
*/
|
*/
|
||||||
exports.toBaseTen = function (cs) {
|
exports.toBaseTen = function (cs) {
|
||||||
var dollarIndex = cs.indexOf('$');
|
var dollarIndex = cs.indexOf('$');
|
||||||
|
@ -93,10 +93,10 @@ exports.toBaseTen = function (cs) {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns the required length of the text before changeset
|
* returns the required length of the text before changeset
|
||||||
* can be applied
|
* can be applied
|
||||||
* @param cs {string} String representation of the Changeset
|
* @param cs {string} String representation of the Changeset
|
||||||
*/
|
*/
|
||||||
exports.oldLen = function (cs) {
|
exports.oldLen = function (cs) {
|
||||||
return exports.unpack(cs).oldLen;
|
return exports.unpack(cs).oldLen;
|
||||||
};
|
};
|
||||||
|
@ -104,16 +104,16 @@ exports.oldLen = function (cs) {
|
||||||
/**
|
/**
|
||||||
* returns the length of the text after changeset is applied
|
* returns the length of the text after changeset is applied
|
||||||
* @param cs {string} String representation of the Changeset
|
* @param cs {string} String representation of the Changeset
|
||||||
*/
|
*/
|
||||||
exports.newLen = function (cs) {
|
exports.newLen = function (cs) {
|
||||||
return exports.unpack(cs).newLen;
|
return exports.unpack(cs).newLen;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this function creates an iterator which decodes string changeset operations
|
* this function creates an iterator which decodes string changeset operations
|
||||||
* @param opsStr {string} String encoding of the change operations to be performed
|
* @param opsStr {string} String encoding of the change operations to be performed
|
||||||
* @param optStartIndex {int} from where in the string should the iterator start
|
* @param optStartIndex {int} from where in the string should the iterator start
|
||||||
* @return {Op} type object iterator
|
* @return {Op} type object iterator
|
||||||
*/
|
*/
|
||||||
exports.opIterator = function (opsStr, optStartIndex) {
|
exports.opIterator = function (opsStr, optStartIndex) {
|
||||||
//print(opsStr);
|
//print(opsStr);
|
||||||
|
@ -131,7 +131,7 @@ exports.opIterator = function (opsStr, optStartIndex) {
|
||||||
if (result[0] == '?') {
|
if (result[0] == '?') {
|
||||||
exports.error("Hit error opcode in op stream");
|
exports.error("Hit error opcode in op stream");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
var regexResult = nextRegexMatch();
|
var regexResult = nextRegexMatch();
|
||||||
|
@ -504,7 +504,7 @@ exports.opAssembler = function () {
|
||||||
/**
|
/**
|
||||||
* A custom made String Iterator
|
* A custom made String Iterator
|
||||||
* @param str {string} String to be iterated over
|
* @param str {string} String to be iterated over
|
||||||
*/
|
*/
|
||||||
exports.stringIterator = function (str) {
|
exports.stringIterator = function (str) {
|
||||||
var curIndex = 0;
|
var curIndex = 0;
|
||||||
|
|
||||||
|
@ -542,7 +542,7 @@ exports.stringIterator = function (str) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A custom made StringBuffer
|
* A custom made StringBuffer
|
||||||
*/
|
*/
|
||||||
exports.stringAssembler = function () {
|
exports.stringAssembler = function () {
|
||||||
var pieces = [];
|
var pieces = [];
|
||||||
|
@ -820,12 +820,12 @@ exports.textLinesMutator = function (lines) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function allowing iterating over two Op strings.
|
* Function allowing iterating over two Op strings.
|
||||||
* @params in1 {string} first Op string
|
* @params in1 {string} first Op string
|
||||||
* @params idx1 {int} integer where 1st iterator should start
|
* @params idx1 {int} integer where 1st iterator should start
|
||||||
* @params in2 {string} second Op string
|
* @params in2 {string} second Op string
|
||||||
* @params idx2 {int} integer where 2nd iterator should start
|
* @params idx2 {int} integer where 2nd iterator should start
|
||||||
* @params func {function} which decides how 1st or 2nd iterator
|
* @params func {function} which decides how 1st or 2nd iterator
|
||||||
* advances. When opX.opcode = 0, iterator X advances to
|
* advances. When opX.opcode = 0, iterator X advances to
|
||||||
* next element
|
* next element
|
||||||
* func has signature f(op1, op2, opOut)
|
* func has signature f(op1, op2, opOut)
|
||||||
|
@ -882,7 +882,7 @@ exports.unpack = function (cs) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Packs Changeset object into a string
|
* Packs Changeset object into a string
|
||||||
* @params oldLen {int} Old length of the Changeset
|
* @params oldLen {int} Old length of the Changeset
|
||||||
* @params newLen {int] New length of the Changeset
|
* @params newLen {int] New length of the Changeset
|
||||||
* @params opsStr {string} String encoding of the changes to be made
|
* @params opsStr {string} String encoding of the changes to be made
|
||||||
|
@ -958,8 +958,8 @@ exports.mutateTextLines = function (cs, lines) {
|
||||||
* Composes two attribute strings (see below) into one.
|
* Composes two attribute strings (see below) into one.
|
||||||
* @param att1 {string} first attribute string
|
* @param att1 {string} first attribute string
|
||||||
* @param att2 {string} second attribue string
|
* @param att2 {string} second attribue string
|
||||||
* @param resultIsMutaton {boolean}
|
* @param resultIsMutaton {boolean}
|
||||||
* @param pool {AttribPool} attribute pool
|
* @param pool {AttribPool} attribute pool
|
||||||
*/
|
*/
|
||||||
exports.composeAttributes = function (att1, att2, resultIsMutation, pool) {
|
exports.composeAttributes = function (att1, att2, resultIsMutation, pool) {
|
||||||
// att1 and att2 are strings like "*3*f*1c", asMutation is a boolean.
|
// att1 and att2 are strings like "*3*f*1c", asMutation is a boolean.
|
||||||
|
@ -1019,8 +1019,8 @@ exports.composeAttributes = function (att1, att2, resultIsMutation, pool) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function used as parameter for applyZip to apply a Changeset to an
|
* Function used as parameter for applyZip to apply a Changeset to an
|
||||||
* attribute
|
* attribute
|
||||||
*/
|
*/
|
||||||
exports._slicerZipperFunc = function (attOp, csOp, opOut, pool) {
|
exports._slicerZipperFunc = function (attOp, csOp, opOut, pool) {
|
||||||
// attOp is the op from the sequence that is being operated on, either an
|
// attOp is the op from the sequence that is being operated on, either an
|
||||||
|
@ -1337,7 +1337,7 @@ exports.compose = function (cs1, cs2, pool) {
|
||||||
* returns a function that tests if a string of attributes
|
* returns a function that tests if a string of attributes
|
||||||
* (e.g. *3*4) contains a given attribute key,value that
|
* (e.g. *3*4) contains a given attribute key,value that
|
||||||
* is already present in the pool.
|
* is already present in the pool.
|
||||||
* @param attribPair array [key,value] of the attribute
|
* @param attribPair array [key,value] of the attribute
|
||||||
* @param pool {AttribPool} Attribute pool
|
* @param pool {AttribPool} Attribute pool
|
||||||
*/
|
*/
|
||||||
exports.attributeTester = function (attribPair, pool) {
|
exports.attributeTester = function (attribPair, pool) {
|
||||||
|
@ -1369,9 +1369,9 @@ exports.identity = function (N) {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates a Changeset which works on oldFullText and removes text
|
* creates a Changeset which works on oldFullText and removes text
|
||||||
* from spliceStart to spliceStart+numRemoved and inserts newText
|
* from spliceStart to spliceStart+numRemoved and inserts newText
|
||||||
* instead. Also gives possibility to add attributes optNewTextAPairs
|
* instead. Also gives possibility to add attributes optNewTextAPairs
|
||||||
* for the new text.
|
* for the new text.
|
||||||
* @param oldFullText {string} old text
|
* @param oldFullText {string} old text
|
||||||
* @param spliecStart {int} where splicing starts
|
* @param spliecStart {int} where splicing starts
|
||||||
|
@ -1407,7 +1407,7 @@ exports.makeSplice = function (oldFullText, spliceStart, numRemoved, newText, op
|
||||||
* @param cs Changeset
|
* @param cs Changeset
|
||||||
*/
|
*/
|
||||||
exports.toSplices = function (cs) {
|
exports.toSplices = function (cs) {
|
||||||
//
|
//
|
||||||
var unpacked = exports.unpack(cs);
|
var unpacked = exports.unpack(cs);
|
||||||
var splices = [];
|
var splices = [];
|
||||||
|
|
||||||
|
@ -1438,7 +1438,7 @@ exports.toSplices = function (cs) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
exports.characterRangeFollow = function (cs, startChar, endChar, insertionsAfter) {
|
exports.characterRangeFollow = function (cs, startChar, endChar, insertionsAfter) {
|
||||||
var newStartChar = startChar;
|
var newStartChar = startChar;
|
||||||
|
@ -1524,7 +1524,7 @@ exports.makeAttribution = function (text) {
|
||||||
* and runs function func on them
|
* and runs function func on them
|
||||||
* @param cs {Changeset} changeset
|
* @param cs {Changeset} changeset
|
||||||
* @param func {function} function to be called
|
* @param func {function} function to be called
|
||||||
*/
|
*/
|
||||||
exports.eachAttribNumber = function (cs, func) {
|
exports.eachAttribNumber = function (cs, func) {
|
||||||
var dollarPos = cs.indexOf('$');
|
var dollarPos = cs.indexOf('$');
|
||||||
if (dollarPos < 0) {
|
if (dollarPos < 0) {
|
||||||
|
@ -1543,16 +1543,16 @@ exports.eachAttribNumber = function (cs, func) {
|
||||||
* callable on a exports, attribution string, or attribs property of an op,
|
* callable on a exports, attribution string, or attribs property of an op,
|
||||||
* though it may easily create adjacent ops that can be merged.
|
* though it may easily create adjacent ops that can be merged.
|
||||||
* @param cs {Changeset} changeset to be filtered
|
* @param cs {Changeset} changeset to be filtered
|
||||||
* @param filter {function} fnc which returns true if an
|
* @param filter {function} fnc which returns true if an
|
||||||
* attribute X (int) should be kept in the Changeset
|
* attribute X (int) should be kept in the Changeset
|
||||||
*/
|
*/
|
||||||
exports.filterAttribNumbers = function (cs, filter) {
|
exports.filterAttribNumbers = function (cs, filter) {
|
||||||
return exports.mapAttribNumbers(cs, filter);
|
return exports.mapAttribNumbers(cs, filter);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* does exactly the same as exports.filterAttribNumbers
|
* does exactly the same as exports.filterAttribNumbers
|
||||||
*/
|
*/
|
||||||
exports.mapAttribNumbers = function (cs, func) {
|
exports.mapAttribNumbers = function (cs, func) {
|
||||||
var dollarPos = cs.indexOf('$');
|
var dollarPos = cs.indexOf('$');
|
||||||
if (dollarPos < 0) {
|
if (dollarPos < 0) {
|
||||||
|
@ -1577,7 +1577,7 @@ exports.mapAttribNumbers = function (cs, func) {
|
||||||
/**
|
/**
|
||||||
* Create a Changeset going from Identity to a certain state
|
* Create a Changeset going from Identity to a certain state
|
||||||
* @params text {string} text of the final change
|
* @params text {string} text of the final change
|
||||||
* @attribs attribs {string} optional, operations which insert
|
* @attribs attribs {string} optional, operations which insert
|
||||||
* the text and also puts the right attributes
|
* the text and also puts the right attributes
|
||||||
*/
|
*/
|
||||||
exports.makeAText = function (text, attribs) {
|
exports.makeAText = function (text, attribs) {
|
||||||
|
@ -1588,9 +1588,9 @@ exports.makeAText = function (text, attribs) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply a Changeset to a AText
|
* Apply a Changeset to a AText
|
||||||
* @param cs {Changeset} Changeset to be applied
|
* @param cs {Changeset} Changeset to be applied
|
||||||
* @param atext {AText}
|
* @param atext {AText}
|
||||||
* @param pool {AttribPool} Attribute Pool to add to
|
* @param pool {AttribPool} Attribute Pool to add to
|
||||||
*/
|
*/
|
||||||
exports.applyToAText = function (cs, atext, pool) {
|
exports.applyToAText = function (cs, atext, pool) {
|
||||||
|
@ -1602,7 +1602,7 @@ exports.applyToAText = function (cs, atext, pool) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clones a AText structure
|
* Clones a AText structure
|
||||||
* @param atext {AText}
|
* @param atext {AText}
|
||||||
*/
|
*/
|
||||||
exports.cloneAText = function (atext) {
|
exports.cloneAText = function (atext) {
|
||||||
return {
|
return {
|
||||||
|
@ -1613,7 +1613,7 @@ exports.cloneAText = function (atext) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Copies a AText structure from atext1 to atext2
|
* Copies a AText structure from atext1 to atext2
|
||||||
* @param atext {AText}
|
* @param atext {AText}
|
||||||
*/
|
*/
|
||||||
exports.copyAText = function (atext1, atext2) {
|
exports.copyAText = function (atext1, atext2) {
|
||||||
atext2.text = atext1.text;
|
atext2.text = atext1.text;
|
||||||
|
@ -1622,7 +1622,7 @@ exports.copyAText = function (atext1, atext2) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append the set of operations from atext to an assembler
|
* Append the set of operations from atext to an assembler
|
||||||
* @param atext {AText}
|
* @param atext {AText}
|
||||||
* @param assem Assembler like smartOpAssembler
|
* @param assem Assembler like smartOpAssembler
|
||||||
*/
|
*/
|
||||||
exports.appendATextToAssembler = function (atext, assem) {
|
exports.appendATextToAssembler = function (atext, assem) {
|
||||||
|
@ -1660,7 +1660,7 @@ exports.appendATextToAssembler = function (atext, assem) {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a clone of a Changeset and it's APool
|
* Creates a clone of a Changeset and it's APool
|
||||||
* @param cs {Changeset}
|
* @param cs {Changeset}
|
||||||
* @param pool {AtributePool}
|
* @param pool {AtributePool}
|
||||||
*/
|
*/
|
||||||
exports.prepareForWire = function (cs, pool) {
|
exports.prepareForWire = function (cs, pool) {
|
||||||
|
@ -1681,8 +1681,8 @@ exports.isIdentity = function (cs) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns all the values of attributes with a certain key
|
* returns all the values of attributes with a certain key
|
||||||
* in an Op attribs string
|
* in an Op attribs string
|
||||||
* @param attribs {string} Attribute string of a Op
|
* @param attribs {string} Attribute string of a Op
|
||||||
* @param key {string} string to be seached for
|
* @param key {string} string to be seached for
|
||||||
* @param pool {AttribPool} attribute pool
|
* @param pool {AttribPool} attribute pool
|
||||||
|
@ -1692,8 +1692,8 @@ exports.opAttributeValue = function (op, key, pool) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* returns all the values of attributes with a certain key
|
* returns all the values of attributes with a certain key
|
||||||
* in an attribs string
|
* in an attribs string
|
||||||
* @param attribs {string} Attribute string
|
* @param attribs {string} Attribute string
|
||||||
* @param key {string} string to be seached for
|
* @param key {string} string to be seached for
|
||||||
* @param pool {AttribPool} attribute pool
|
* @param pool {AttribPool} attribute pool
|
||||||
|
@ -1711,7 +1711,7 @@ exports.attribsAttributeValue = function (attribs, key, pool) {
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a Changeset builder for a string with initial
|
* Creates a Changeset builder for a string with initial
|
||||||
* length oldLen. Allows to add/remove parts of it
|
* length oldLen. Allows to add/remove parts of it
|
||||||
* @param oldLen {int} Old length
|
* @param oldLen {int} Old length
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -86,7 +86,7 @@ function Ace2Editor()
|
||||||
});
|
});
|
||||||
actionsPendingInit = [];
|
actionsPendingInit = [];
|
||||||
}
|
}
|
||||||
|
|
||||||
ace2.registry[info.id] = info;
|
ace2.registry[info.id] = info;
|
||||||
|
|
||||||
// The following functions (prefixed by 'ace_') are exposed by editor, but
|
// The following functions (prefixed by 'ace_') are exposed by editor, but
|
||||||
|
@ -97,7 +97,7 @@ function Ace2Editor()
|
||||||
'applyChangesToBase', 'applyPreparedChangesetToBase',
|
'applyChangesToBase', 'applyPreparedChangesetToBase',
|
||||||
'setUserChangeNotificationCallback', 'setAuthorInfo',
|
'setUserChangeNotificationCallback', 'setAuthorInfo',
|
||||||
'setAuthorSelectionRange', 'callWithAce', 'execCommand', 'replaceRange'];
|
'setAuthorSelectionRange', 'callWithAce', 'execCommand', 'replaceRange'];
|
||||||
|
|
||||||
_.each(aceFunctionsPendingInit, function(fnName,i){
|
_.each(aceFunctionsPendingInit, function(fnName,i){
|
||||||
var prefix = 'ace_';
|
var prefix = 'ace_';
|
||||||
var name = prefix + fnName;
|
var name = prefix + fnName;
|
||||||
|
@ -105,18 +105,18 @@ function Ace2Editor()
|
||||||
info[prefix + fnName].apply(this, arguments);
|
info[prefix + fnName].apply(this, arguments);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
editor.exportText = function()
|
editor.exportText = function()
|
||||||
{
|
{
|
||||||
if (!loaded) return "(awaiting init)\n";
|
if (!loaded) return "(awaiting init)\n";
|
||||||
return info.ace_exportText();
|
return info.ace_exportText();
|
||||||
};
|
};
|
||||||
|
|
||||||
editor.getFrame = function()
|
editor.getFrame = function()
|
||||||
{
|
{
|
||||||
return info.frame || null;
|
return info.frame || null;
|
||||||
};
|
};
|
||||||
|
|
||||||
editor.getDebugProperty = function(prop)
|
editor.getDebugProperty = function(prop)
|
||||||
{
|
{
|
||||||
return info.ace_getDebugProperty(prop);
|
return info.ace_getDebugProperty(prop);
|
||||||
|
@ -221,16 +221,16 @@ function Ace2Editor()
|
||||||
// calls to these functions ($$INCLUDE_...) are replaced when this file is processed
|
// calls to these functions ($$INCLUDE_...) are replaced when this file is processed
|
||||||
// and compressed, putting the compressed code from the named file directly into the
|
// and compressed, putting the compressed code from the named file directly into the
|
||||||
// source here.
|
// source here.
|
||||||
// these lines must conform to a specific format because they are passed by the build script:
|
// these lines must conform to a specific format because they are passed by the build script:
|
||||||
var includedCSS = [];
|
var includedCSS = [];
|
||||||
var $$INCLUDE_CSS = function(filename) {includedCSS.push(filename)};
|
var $$INCLUDE_CSS = function(filename) {includedCSS.push(filename)};
|
||||||
$$INCLUDE_CSS("../static/css/iframe_editor.css");
|
$$INCLUDE_CSS("../static/css/iframe_editor.css");
|
||||||
$$INCLUDE_CSS("../static/css/pad.css");
|
$$INCLUDE_CSS("../static/css/pad.css");
|
||||||
$$INCLUDE_CSS("../static/custom/pad.css");
|
$$INCLUDE_CSS("../static/custom/pad.css");
|
||||||
|
|
||||||
var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path });
|
var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path });
|
||||||
includedCSS = includedCSS.concat(additionalCSS);
|
includedCSS = includedCSS.concat(additionalCSS);
|
||||||
|
|
||||||
pushStyleTagsFor(iframeHTML, includedCSS);
|
pushStyleTagsFor(iframeHTML, includedCSS);
|
||||||
|
|
||||||
if (!Ace2Editor.EMBEDED && Ace2Editor.EMBEDED[KERNEL_SOURCE]) {
|
if (!Ace2Editor.EMBEDED && Ace2Editor.EMBEDED[KERNEL_SOURCE]) {
|
||||||
|
@ -304,11 +304,11 @@ window.onload = function () {\n\
|
||||||
$$INCLUDE_CSS("../static/css/iframe_editor.css");
|
$$INCLUDE_CSS("../static/css/iframe_editor.css");
|
||||||
$$INCLUDE_CSS("../static/css/pad.css");
|
$$INCLUDE_CSS("../static/css/pad.css");
|
||||||
$$INCLUDE_CSS("../static/custom/pad.css");
|
$$INCLUDE_CSS("../static/custom/pad.css");
|
||||||
|
|
||||||
|
|
||||||
var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path });
|
var additionalCSS = _(hooks.callAll("aceEditorCSS")).map(function(path){ return '../static/plugins/' + path });
|
||||||
includedCSS = includedCSS.concat(additionalCSS);
|
includedCSS = includedCSS.concat(additionalCSS);
|
||||||
|
|
||||||
pushStyleTagsFor(outerHTML, includedCSS);
|
pushStyleTagsFor(outerHTML, includedCSS);
|
||||||
|
|
||||||
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly
|
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -36,10 +36,10 @@ var isNodeText = Ace2Common.isNodeText,
|
||||||
htmlPrettyEscape = Ace2Common.htmlPrettyEscape,
|
htmlPrettyEscape = Ace2Common.htmlPrettyEscape,
|
||||||
noop = Ace2Common.noop;
|
noop = Ace2Common.noop;
|
||||||
var hooks = require('./pluginfw/hooks');
|
var hooks = require('./pluginfw/hooks');
|
||||||
|
|
||||||
|
|
||||||
function Ace2Inner(){
|
function Ace2Inner(){
|
||||||
|
|
||||||
var makeChangesetTracker = require('./changesettracker').makeChangesetTracker;
|
var makeChangesetTracker = require('./changesettracker').makeChangesetTracker;
|
||||||
var colorutils = require('./colorutils').colorutils;
|
var colorutils = require('./colorutils').colorutils;
|
||||||
var makeContentCollector = require('./contentcollector').makeContentCollector;
|
var makeContentCollector = require('./contentcollector').makeContentCollector;
|
||||||
|
@ -53,9 +53,9 @@ function Ace2Inner(){
|
||||||
var undoModule = require('./undomodule').undoModule;
|
var undoModule = require('./undomodule').undoModule;
|
||||||
var makeVirtualLineView = require('./virtual_lines').makeVirtualLineView;
|
var makeVirtualLineView = require('./virtual_lines').makeVirtualLineView;
|
||||||
var AttributeManager = require('./AttributeManager');
|
var AttributeManager = require('./AttributeManager');
|
||||||
|
|
||||||
var DEBUG = false; //$$ build script replaces the string "var DEBUG=true;//$$" with "var DEBUG=false;"
|
var DEBUG = false; //$$ build script replaces the string "var DEBUG=true;//$$" with "var DEBUG=false;"
|
||||||
// changed to false
|
// changed to false
|
||||||
var isSetUp = false;
|
var isSetUp = false;
|
||||||
|
|
||||||
var THE_TAB = ' '; //4
|
var THE_TAB = ' '; //4
|
||||||
|
@ -83,9 +83,9 @@ function Ace2Inner(){
|
||||||
initLineNumbers();
|
initLineNumbers();
|
||||||
|
|
||||||
var outsideKeyDown = noop;
|
var outsideKeyDown = noop;
|
||||||
|
|
||||||
var outsideKeyPress = function(){return true;};
|
var outsideKeyPress = function(){return true;};
|
||||||
|
|
||||||
var outsideNotifyDirty = noop;
|
var outsideNotifyDirty = noop;
|
||||||
|
|
||||||
// selFocusAtStart -- determines whether the selection extends "backwards", so that the focus
|
// selFocusAtStart -- determines whether the selection extends "backwards", so that the focus
|
||||||
|
@ -101,7 +101,7 @@ function Ace2Inner(){
|
||||||
alines: [],
|
alines: [],
|
||||||
apool: new AttribPool()
|
apool: new AttribPool()
|
||||||
};
|
};
|
||||||
|
|
||||||
// lines, alltext, alines, and DOM are set up in setup()
|
// lines, alltext, alines, and DOM are set up in setup()
|
||||||
if (undoModule.enabled)
|
if (undoModule.enabled)
|
||||||
{
|
{
|
||||||
|
@ -113,7 +113,7 @@ function Ace2Inner(){
|
||||||
var doesWrap = true;
|
var doesWrap = true;
|
||||||
var hasLineNumbers = true;
|
var hasLineNumbers = true;
|
||||||
var isStyled = true;
|
var isStyled = true;
|
||||||
|
|
||||||
// space around the innermost iframe element
|
// space around the innermost iframe element
|
||||||
var iframePadLeft = MIN_LINEDIV_WIDTH + LINE_NUMBER_PADDING_RIGHT + EDIT_BODY_PADDING_LEFT;
|
var iframePadLeft = MIN_LINEDIV_WIDTH + LINE_NUMBER_PADDING_RIGHT + EDIT_BODY_PADDING_LEFT;
|
||||||
var iframePadTop = EDIT_BODY_PADDING_TOP;
|
var iframePadTop = EDIT_BODY_PADDING_TOP;
|
||||||
|
@ -122,7 +122,7 @@ function Ace2Inner(){
|
||||||
|
|
||||||
var console = (DEBUG && window.console);
|
var console = (DEBUG && window.console);
|
||||||
var documentAttributeManager;
|
var documentAttributeManager;
|
||||||
|
|
||||||
if (!window.console)
|
if (!window.console)
|
||||||
{
|
{
|
||||||
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
|
var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
|
||||||
|
@ -158,7 +158,7 @@ function Ace2Inner(){
|
||||||
|
|
||||||
var textFace = 'monospace';
|
var textFace = 'monospace';
|
||||||
var textSize = 12;
|
var textSize = 12;
|
||||||
|
|
||||||
|
|
||||||
function textLineHeight()
|
function textLineHeight()
|
||||||
{
|
{
|
||||||
|
@ -231,15 +231,15 @@ function Ace2Inner(){
|
||||||
{
|
{
|
||||||
bgcolor = fadeColor(bgcolor, info.fade);
|
bgcolor = fadeColor(bgcolor, info.fade);
|
||||||
}
|
}
|
||||||
|
|
||||||
var authorStyle = dynamicCSS.selectorStyle(getAuthorColorClassSelector(
|
var authorStyle = dynamicCSS.selectorStyle(getAuthorColorClassSelector(
|
||||||
getAuthorClassName(author)));
|
getAuthorClassName(author)));
|
||||||
var anchorStyle = dynamicCSS.selectorStyle(getAuthorColorClassSelector(
|
var anchorStyle = dynamicCSS.selectorStyle(getAuthorColorClassSelector(
|
||||||
getAuthorClassName(author))+' > a')
|
getAuthorClassName(author))+' > a')
|
||||||
|
|
||||||
// author color
|
// author color
|
||||||
authorStyle.backgroundColor = bgcolor;
|
authorStyle.backgroundColor = bgcolor;
|
||||||
|
|
||||||
// text contrast
|
// text contrast
|
||||||
if(colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.5)
|
if(colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.5)
|
||||||
{
|
{
|
||||||
|
@ -247,7 +247,7 @@ function Ace2Inner(){
|
||||||
}else{
|
}else{
|
||||||
authorStyle.color = null;
|
authorStyle.color = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// anchor text contrast
|
// anchor text contrast
|
||||||
if(colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.55)
|
if(colorutils.luminosity(colorutils.css2triple(bgcolor)) < 0.55)
|
||||||
{
|
{
|
||||||
|
@ -540,8 +540,8 @@ function Ace2Inner(){
|
||||||
{
|
{
|
||||||
return rep.lines.atOffset(charOffset).key;
|
return rep.lines.atOffset(charOffset).key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function dispose()
|
function dispose()
|
||||||
{
|
{
|
||||||
disposed = true;
|
disposed = true;
|
||||||
|
@ -896,14 +896,14 @@ function Ace2Inner(){
|
||||||
editorInfo.ace_doReturnKey = doReturnKey;
|
editorInfo.ace_doReturnKey = doReturnKey;
|
||||||
editorInfo.ace_isBlockElement = isBlockElement;
|
editorInfo.ace_isBlockElement = isBlockElement;
|
||||||
editorInfo.ace_getLineListType = getLineListType;
|
editorInfo.ace_getLineListType = getLineListType;
|
||||||
|
|
||||||
editorInfo.ace_callWithAce = function(fn, callStack, normalize)
|
editorInfo.ace_callWithAce = function(fn, callStack, normalize)
|
||||||
{
|
{
|
||||||
var wrapper = function()
|
var wrapper = function()
|
||||||
{
|
{
|
||||||
return fn(editorInfo);
|
return fn(editorInfo);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (normalize !== undefined)
|
if (normalize !== undefined)
|
||||||
{
|
{
|
||||||
var wrapper1 = wrapper;
|
var wrapper1 = wrapper;
|
||||||
|
@ -929,14 +929,14 @@ function Ace2Inner(){
|
||||||
// @param value the value to set to
|
// @param value the value to set to
|
||||||
editorInfo.ace_setProperty = function(key, value)
|
editorInfo.ace_setProperty = function(key, value)
|
||||||
{
|
{
|
||||||
|
|
||||||
// Convinience function returning a setter for a class on an element
|
// Convinience function returning a setter for a class on an element
|
||||||
var setClassPresenceNamed = function(element, cls){
|
var setClassPresenceNamed = function(element, cls){
|
||||||
return function(value){
|
return function(value){
|
||||||
setClassPresence(element, cls, !! value)
|
setClassPresence(element, cls, !! value)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// These properties are exposed
|
// These properties are exposed
|
||||||
var setters = {
|
var setters = {
|
||||||
wraps: setWraps,
|
wraps: setWraps,
|
||||||
|
@ -951,7 +951,7 @@ function Ace2Inner(){
|
||||||
},
|
},
|
||||||
grayedout: setClassPresenceNamed(outerWin.document.body, "grayedout"),
|
grayedout: setClassPresenceNamed(outerWin.document.body, "grayedout"),
|
||||||
dmesg: function(){ dmesg = window.dmesg = value; },
|
dmesg: function(){ dmesg = window.dmesg = value; },
|
||||||
userauthor: function(value){
|
userauthor: function(value){
|
||||||
thisAuthor = String(value);
|
thisAuthor = String(value);
|
||||||
documentAttributeManager.author = thisAuthor;
|
documentAttributeManager.author = thisAuthor;
|
||||||
},
|
},
|
||||||
|
@ -960,10 +960,10 @@ function Ace2Inner(){
|
||||||
textsize: setTextSize,
|
textsize: setTextSize,
|
||||||
rtlistrue: setClassPresenceNamed(root, "rtl")
|
rtlistrue: setClassPresenceNamed(root, "rtl")
|
||||||
};
|
};
|
||||||
|
|
||||||
var setter = setters[key.toLowerCase()];
|
var setter = setters[key.toLowerCase()];
|
||||||
|
|
||||||
// check if setter is present
|
// check if setter is present
|
||||||
if(setter !== undefined){
|
if(setter !== undefined){
|
||||||
setter(value)
|
setter(value)
|
||||||
}
|
}
|
||||||
|
@ -1067,7 +1067,7 @@ function Ace2Inner(){
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
isTimeUp.elapsed = function()
|
isTimeUp.elapsed = function()
|
||||||
{
|
{
|
||||||
return now() - startTime;
|
return now() - startTime;
|
||||||
|
@ -1448,7 +1448,7 @@ function Ace2Inner(){
|
||||||
var p = PROFILER("getSelection", false);
|
var p = PROFILER("getSelection", false);
|
||||||
var selection = getSelection();
|
var selection = getSelection();
|
||||||
p.end();
|
p.end();
|
||||||
|
|
||||||
function topLevel(n)
|
function topLevel(n)
|
||||||
{
|
{
|
||||||
if ((!n) || n == root) return null;
|
if ((!n) || n == root) return null;
|
||||||
|
@ -1458,7 +1458,7 @@ function Ace2Inner(){
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (selection)
|
if (selection)
|
||||||
{
|
{
|
||||||
var node1 = topLevel(selection.startPoint.node);
|
var node1 = topLevel(selection.startPoint.node);
|
||||||
|
@ -1704,7 +1704,7 @@ function Ace2Inner(){
|
||||||
root:root,
|
root:root,
|
||||||
point:selection.startPoint,
|
point:selection.startPoint,
|
||||||
documentAttributeManager: documentAttributeManager
|
documentAttributeManager: documentAttributeManager
|
||||||
});
|
});
|
||||||
selStart = (selStartFromHook==null||selStartFromHook.length==0)?getLineAndCharForPoint(selection.startPoint):selStartFromHook;
|
selStart = (selStartFromHook==null||selStartFromHook.length==0)?getLineAndCharForPoint(selection.startPoint):selStartFromHook;
|
||||||
}
|
}
|
||||||
if (selection && !selEnd)
|
if (selection && !selEnd)
|
||||||
|
@ -1717,7 +1717,7 @@ function Ace2Inner(){
|
||||||
point:selection.endPoint,
|
point:selection.endPoint,
|
||||||
documentAttributeManager: documentAttributeManager
|
documentAttributeManager: documentAttributeManager
|
||||||
});
|
});
|
||||||
selEnd = (selEndFromHook==null||selEndFromHook.length==0)?getLineAndCharForPoint(selection.endPoint):selEndFromHook;
|
selEnd = (selEndFromHook==null||selEndFromHook.length==0)?getLineAndCharForPoint(selection.endPoint):selEndFromHook;
|
||||||
}
|
}
|
||||||
|
|
||||||
// selection from content collection can, in various ways, extend past final
|
// selection from content collection can, in various ways, extend past final
|
||||||
|
@ -1738,7 +1738,7 @@ function Ace2Inner(){
|
||||||
// update rep if we have a new selection
|
// update rep if we have a new selection
|
||||||
// NOTE: IE loses the selection when you click stuff in e.g. the
|
// NOTE: IE loses the selection when you click stuff in e.g. the
|
||||||
// editbar, so removing the selection when it's lost is not a good
|
// editbar, so removing the selection when it's lost is not a good
|
||||||
// idea.
|
// idea.
|
||||||
if (selection) repSelectionChange(selStart, selEnd, selection && selection.focusAtStart);
|
if (selection) repSelectionChange(selStart, selEnd, selection && selection.focusAtStart);
|
||||||
// update browser selection
|
// update browser selection
|
||||||
p.mark("browsel");
|
p.mark("browsel");
|
||||||
|
@ -1873,19 +1873,19 @@ function Ace2Inner(){
|
||||||
return rep.selStart[0];
|
return rep.selStart[0];
|
||||||
}
|
}
|
||||||
editorInfo.ace_caretLine = caretLine;
|
editorInfo.ace_caretLine = caretLine;
|
||||||
|
|
||||||
function caretColumn()
|
function caretColumn()
|
||||||
{
|
{
|
||||||
return rep.selStart[1];
|
return rep.selStart[1];
|
||||||
}
|
}
|
||||||
editorInfo.ace_caretColumn = caretColumn;
|
editorInfo.ace_caretColumn = caretColumn;
|
||||||
|
|
||||||
function caretDocChar()
|
function caretDocChar()
|
||||||
{
|
{
|
||||||
return rep.lines.offsetOfIndex(caretLine()) + caretColumn();
|
return rep.lines.offsetOfIndex(caretLine()) + caretColumn();
|
||||||
}
|
}
|
||||||
editorInfo.ace_caretDocChar = caretDocChar;
|
editorInfo.ace_caretDocChar = caretDocChar;
|
||||||
|
|
||||||
function handleReturnIndentation()
|
function handleReturnIndentation()
|
||||||
{
|
{
|
||||||
// on return, indent to level of previous line
|
// on return, indent to level of previous line
|
||||||
|
@ -2314,8 +2314,8 @@ function Ace2Inner(){
|
||||||
documentAttributeManager.setAttributesOnRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs);
|
documentAttributeManager.setAttributesOnRange(lineAndColumnFromChar(start), lineAndColumnFromChar(end), attribs);
|
||||||
}
|
}
|
||||||
editorInfo.ace_performDocumentApplyAttributesToCharRange = performDocumentApplyAttributesToCharRange;
|
editorInfo.ace_performDocumentApplyAttributesToCharRange = performDocumentApplyAttributesToCharRange;
|
||||||
|
|
||||||
|
|
||||||
function setAttributeOnSelection(attributeName, attributeValue)
|
function setAttributeOnSelection(attributeName, attributeValue)
|
||||||
{
|
{
|
||||||
if (!(rep.selStart && rep.selEnd)) return;
|
if (!(rep.selStart && rep.selEnd)) return;
|
||||||
|
@ -2879,7 +2879,7 @@ function Ace2Inner(){
|
||||||
{
|
{
|
||||||
if (lineClass !== null) lineElem.className = lineClass;
|
if (lineClass !== null) lineElem.className = lineClass;
|
||||||
};
|
};
|
||||||
|
|
||||||
result.prepareForAdd = writeClass;
|
result.prepareForAdd = writeClass;
|
||||||
result.finishUpdate = writeClass;
|
result.finishUpdate = writeClass;
|
||||||
result.getInnerHTML = function()
|
result.getInnerHTML = function()
|
||||||
|
@ -3241,7 +3241,7 @@ function Ace2Inner(){
|
||||||
{
|
{
|
||||||
return (n.tagName || '').toLowerCase() == "a" && n.href;
|
return (n.tagName || '').toLowerCase() == "a" && n.href;
|
||||||
}
|
}
|
||||||
|
|
||||||
// only want to catch left-click
|
// only want to catch left-click
|
||||||
if ((!evt.ctrlKey) && (evt.button != 2) && (evt.button != 3))
|
if ((!evt.ctrlKey) && (evt.button != 2) && (evt.button != 3))
|
||||||
{
|
{
|
||||||
|
@ -3277,7 +3277,7 @@ function Ace2Inner(){
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var lineNum = rep.selStart[0];
|
var lineNum = rep.selStart[0];
|
||||||
var listType = getLineListType(lineNum);
|
var listType = getLineListType(lineNum);
|
||||||
|
|
||||||
|
@ -3287,7 +3287,7 @@ function Ace2Inner(){
|
||||||
listType = /([a-z]+)([12345678])/.exec(listType);
|
listType = /([a-z]+)([12345678])/.exec(listType);
|
||||||
var type = listType[1];
|
var type = listType[1];
|
||||||
var level = Number(listType[2]);
|
var level = Number(listType[2]);
|
||||||
|
|
||||||
//detect empty list item; exclude indentation
|
//detect empty list item; exclude indentation
|
||||||
if(text === '*' && type !== "indent")
|
if(text === '*' && type !== "indent")
|
||||||
{
|
{
|
||||||
|
@ -3401,9 +3401,9 @@ function Ace2Inner(){
|
||||||
var thisLineListType = getLineListType(theLine);
|
var thisLineListType = getLineListType(theLine);
|
||||||
var prevLineEntry = (theLine > 0 && rep.lines.atIndex(theLine - 1));
|
var prevLineEntry = (theLine > 0 && rep.lines.atIndex(theLine - 1));
|
||||||
var prevLineBlank = (prevLineEntry && prevLineEntry.text.length == prevLineEntry.lineMarker);
|
var prevLineBlank = (prevLineEntry && prevLineEntry.text.length == prevLineEntry.lineMarker);
|
||||||
|
|
||||||
var thisLineHasMarker = documentAttributeManager.lineHasMarker(theLine);
|
var thisLineHasMarker = documentAttributeManager.lineHasMarker(theLine);
|
||||||
|
|
||||||
if (thisLineListType)
|
if (thisLineListType)
|
||||||
{
|
{
|
||||||
// this line is a list
|
// this line is a list
|
||||||
|
@ -3478,7 +3478,7 @@ function Ace2Inner(){
|
||||||
return !!REGEX_WORDCHAR.exec(c);
|
return !!REGEX_WORDCHAR.exec(c);
|
||||||
}
|
}
|
||||||
editorInfo.ace_isWordChar = isWordChar;
|
editorInfo.ace_isWordChar = isWordChar;
|
||||||
|
|
||||||
function isSpaceChar(c)
|
function isSpaceChar(c)
|
||||||
{
|
{
|
||||||
return !!REGEX_SPACE.exec(c);
|
return !!REGEX_SPACE.exec(c);
|
||||||
|
@ -4011,7 +4011,7 @@ function Ace2Inner(){
|
||||||
maxIndex: tn.nodeValue.length
|
maxIndex: tn.nodeValue.length
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
var selection = {};
|
var selection = {};
|
||||||
if (origSelectionRange.compareEndPoints("StartToEnd", origSelectionRange) === 0)
|
if (origSelectionRange.compareEndPoints("StartToEnd", origSelectionRange) === 0)
|
||||||
{
|
{
|
||||||
|
@ -4875,9 +4875,9 @@ function Ace2Inner(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var listAttributeName = 'list';
|
var listAttributeName = 'list';
|
||||||
|
|
||||||
function getLineListType(lineNum)
|
function getLineListType(lineNum)
|
||||||
{
|
{
|
||||||
return documentAttributeManager.getAttributeOnLine(lineNum, listAttributeName)
|
return documentAttributeManager.getAttributeOnLine(lineNum, listAttributeName)
|
||||||
|
@ -4890,7 +4890,7 @@ function Ace2Inner(){
|
||||||
}else{
|
}else{
|
||||||
documentAttributeManager.setAttributeOnLine(lineNum, listAttributeName, listType);
|
documentAttributeManager.setAttributeOnLine(lineNum, listAttributeName, listType);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if the list has been removed, it is necessary to renumber
|
//if the list has been removed, it is necessary to renumber
|
||||||
//starting from the *next* line because the list may have been
|
//starting from the *next* line because the list may have been
|
||||||
//separated. If it returns null, it means that the list was not cut, try
|
//separated. If it returns null, it means that the list was not cut, try
|
||||||
|
@ -4900,7 +4900,7 @@ function Ace2Inner(){
|
||||||
renumberList(lineNum);
|
renumberList(lineNum);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function renumberList(lineNum){
|
function renumberList(lineNum){
|
||||||
//1-check we are in a list
|
//1-check we are in a list
|
||||||
var type = getLineListType(lineNum);
|
var type = getLineListType(lineNum);
|
||||||
|
@ -4913,7 +4913,7 @@ function Ace2Inner(){
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
//2-find the first line of the list
|
//2-find the first line of the list
|
||||||
while(lineNum-1 >= 0 && (type=getLineListType(lineNum-1)))
|
while(lineNum-1 >= 0 && (type=getLineListType(lineNum-1)))
|
||||||
{
|
{
|
||||||
|
@ -4922,7 +4922,7 @@ function Ace2Inner(){
|
||||||
break;
|
break;
|
||||||
lineNum--;
|
lineNum--;
|
||||||
}
|
}
|
||||||
|
|
||||||
//3-renumber every list item of the same level from the beginning, level 1
|
//3-renumber every list item of the same level from the beginning, level 1
|
||||||
//IMPORTANT: never skip a level because there imbrication may be arbitrary
|
//IMPORTANT: never skip a level because there imbrication may be arbitrary
|
||||||
var builder = Changeset.builder(rep.lines.totalWidth());
|
var builder = Changeset.builder(rep.lines.totalWidth());
|
||||||
|
@ -4949,7 +4949,7 @@ function Ace2Inner(){
|
||||||
ChangesetUtils.buildKeepRange(rep, builder, loc, (loc = [line, 1]), [
|
ChangesetUtils.buildKeepRange(rep, builder, loc, (loc = [line, 1]), [
|
||||||
['start', position]
|
['start', position]
|
||||||
], rep.apool);
|
], rep.apool);
|
||||||
|
|
||||||
position++;
|
position++;
|
||||||
line++;
|
line++;
|
||||||
}
|
}
|
||||||
|
@ -4964,19 +4964,19 @@ function Ace2Inner(){
|
||||||
}
|
}
|
||||||
return line;
|
return line;
|
||||||
}
|
}
|
||||||
|
|
||||||
applyNumberList(lineNum, 1);
|
applyNumberList(lineNum, 1);
|
||||||
var cs = builder.toString();
|
var cs = builder.toString();
|
||||||
if (!Changeset.isIdentity(cs))
|
if (!Changeset.isIdentity(cs))
|
||||||
{
|
{
|
||||||
performDocumentApplyChangeset(cs);
|
performDocumentApplyChangeset(cs);
|
||||||
}
|
}
|
||||||
|
|
||||||
//4-apply the modifications
|
//4-apply the modifications
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function doInsertList(type)
|
function doInsertList(type)
|
||||||
{
|
{
|
||||||
|
@ -5014,12 +5014,12 @@ function Ace2Inner(){
|
||||||
var t = getLineListType(n);
|
var t = getLineListType(n);
|
||||||
mods.push([n, allLinesAreList ? 'indent' + level : (t ? type + level : type + '1')]);
|
mods.push([n, allLinesAreList ? 'indent' + level : (t ? type + level : type + '1')]);
|
||||||
}
|
}
|
||||||
|
|
||||||
_.each(mods, function(mod){
|
_.each(mods, function(mod){
|
||||||
setLineListType(mod[0], mod[1]);
|
setLineListType(mod[0], mod[1]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function doInsertUnorderedList(){
|
function doInsertUnorderedList(){
|
||||||
doInsertList('bullet');
|
doInsertList('bullet');
|
||||||
}
|
}
|
||||||
|
@ -5353,7 +5353,7 @@ function Ace2Inner(){
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})());
|
})());
|
||||||
|
|
||||||
var lineNumbersShown;
|
var lineNumbersShown;
|
||||||
var sideDivInner;
|
var sideDivInner;
|
||||||
|
|
||||||
|
@ -5369,11 +5369,11 @@ function Ace2Inner(){
|
||||||
var newNumLines = rep.lines.length();
|
var newNumLines = rep.lines.length();
|
||||||
if (newNumLines < 1) newNumLines = 1;
|
if (newNumLines < 1) newNumLines = 1;
|
||||||
//update height of all current line numbers
|
//update height of all current line numbers
|
||||||
|
|
||||||
var a = sideDivInner.firstChild;
|
var a = sideDivInner.firstChild;
|
||||||
var b = doc.body.firstChild;
|
var b = doc.body.firstChild;
|
||||||
var n = 0;
|
var n = 0;
|
||||||
|
|
||||||
if (currentCallStack && currentCallStack.domClean)
|
if (currentCallStack && currentCallStack.domClean)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -5403,8 +5403,8 @@ function Ace2Inner(){
|
||||||
b = b.nextSibling;
|
b = b.nextSibling;
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (newNumLines != lineNumbersShown)
|
if (newNumLines != lineNumbersShown)
|
||||||
{
|
{
|
||||||
var container = sideDivInner;
|
var container = sideDivInner;
|
||||||
|
@ -5414,21 +5414,21 @@ function Ace2Inner(){
|
||||||
{
|
{
|
||||||
lineNumbersShown++;
|
lineNumbersShown++;
|
||||||
var n = lineNumbersShown;
|
var n = lineNumbersShown;
|
||||||
var div = odoc.createElement("DIV");
|
var div = odoc.createElement("DIV");
|
||||||
//calculate height for new line number
|
//calculate height for new line number
|
||||||
var h = (b.clientHeight || b.offsetHeight);
|
var h = (b.clientHeight || b.offsetHeight);
|
||||||
|
|
||||||
if (b.nextSibling)
|
if (b.nextSibling)
|
||||||
h = b.nextSibling.offsetTop - b.offsetTop;
|
h = b.nextSibling.offsetTop - b.offsetTop;
|
||||||
|
|
||||||
if(h) // apply style to div
|
if(h) // apply style to div
|
||||||
div.style.height = h +"px";
|
div.style.height = h +"px";
|
||||||
|
|
||||||
div.appendChild(odoc.createTextNode(String(n)));
|
div.appendChild(odoc.createTextNode(String(n)));
|
||||||
fragment.appendChild(div);
|
fragment.appendChild(div);
|
||||||
b = b.nextSibling;
|
b = b.nextSibling;
|
||||||
}
|
}
|
||||||
|
|
||||||
container.appendChild(fragment);
|
container.appendChild(fragment);
|
||||||
while (lineNumbersShown > newNumLines)
|
while (lineNumbersShown > newNumLines)
|
||||||
{
|
{
|
||||||
|
@ -5437,8 +5437,8 @@ function Ace2Inner(){
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Init documentAttributeManager
|
// Init documentAttributeManager
|
||||||
documentAttributeManager = new AttributeManager(rep, performDocumentApplyChangeset);
|
documentAttributeManager = new AttributeManager(rep, performDocumentApplyChangeset);
|
||||||
editorInfo.ace_performDocumentApplyAttributesToRange = function () {
|
editorInfo.ace_performDocumentApplyAttributesToRange = function () {
|
||||||
|
@ -5484,13 +5484,13 @@ function Ace2Inner(){
|
||||||
bindTheEventHandlers();
|
bindTheEventHandlers();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
hooks.callAll('aceInitialized', {
|
hooks.callAll('aceInitialized', {
|
||||||
editorInfo: editorInfo,
|
editorInfo: editorInfo,
|
||||||
rep: rep,
|
rep: rep,
|
||||||
documentAttributeManager: documentAttributeManager
|
documentAttributeManager: documentAttributeManager
|
||||||
});
|
});
|
||||||
|
|
||||||
scheduler.setTimeout(function()
|
scheduler.setTimeout(function()
|
||||||
{
|
{
|
||||||
parent.readyFunc(); // defined in code that sets up the inner iframe
|
parent.readyFunc(); // defined in code that sets up the inner iframe
|
||||||
|
|
|
@ -1,180 +1,180 @@
|
||||||
// Autosize 1.13 - jQuery plugin for textareas
|
// Autosize 1.13 - jQuery plugin for textareas
|
||||||
// (c) 2012 Jack Moore - jacklmoore.com
|
// (c) 2012 Jack Moore - jacklmoore.com
|
||||||
// license: www.opensource.org/licenses/mit-license.php
|
// license: www.opensource.org/licenses/mit-license.php
|
||||||
|
|
||||||
(function ($) {
|
(function ($) {
|
||||||
var
|
var
|
||||||
defaults = {
|
defaults = {
|
||||||
className: 'autosizejs',
|
className: 'autosizejs',
|
||||||
append: "",
|
append: "",
|
||||||
callback: false
|
callback: false
|
||||||
},
|
},
|
||||||
hidden = 'hidden',
|
hidden = 'hidden',
|
||||||
borderBox = 'border-box',
|
borderBox = 'border-box',
|
||||||
lineHeight = 'lineHeight',
|
lineHeight = 'lineHeight',
|
||||||
copy = '<textarea tabindex="-1" style="position:absolute; top:-9999px; left:-9999px; right:auto; bottom:auto; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden;"/>',
|
copy = '<textarea tabindex="-1" style="position:absolute; top:-9999px; left:-9999px; right:auto; bottom:auto; -moz-box-sizing:content-box; -webkit-box-sizing:content-box; box-sizing:content-box; word-wrap:break-word; height:0 !important; min-height:0 !important; overflow:hidden;"/>',
|
||||||
// line-height is omitted because IE7/IE8 doesn't return the correct value.
|
// line-height is omitted because IE7/IE8 doesn't return the correct value.
|
||||||
copyStyle = [
|
copyStyle = [
|
||||||
'fontFamily',
|
'fontFamily',
|
||||||
'fontSize',
|
'fontSize',
|
||||||
'fontWeight',
|
'fontWeight',
|
||||||
'fontStyle',
|
'fontStyle',
|
||||||
'letterSpacing',
|
'letterSpacing',
|
||||||
'textTransform',
|
'textTransform',
|
||||||
'wordSpacing',
|
'wordSpacing',
|
||||||
'textIndent'
|
'textIndent'
|
||||||
],
|
],
|
||||||
oninput = 'oninput',
|
oninput = 'oninput',
|
||||||
onpropertychange = 'onpropertychange',
|
onpropertychange = 'onpropertychange',
|
||||||
test = $(copy)[0];
|
test = $(copy)[0];
|
||||||
|
|
||||||
// For testing support in old FireFox
|
// For testing support in old FireFox
|
||||||
test.setAttribute(oninput, "return");
|
test.setAttribute(oninput, "return");
|
||||||
|
|
||||||
if ($.isFunction(test[oninput]) || onpropertychange in test) {
|
if ($.isFunction(test[oninput]) || onpropertychange in test) {
|
||||||
|
|
||||||
// test that line-height can be accurately copied to avoid
|
// test that line-height can be accurately copied to avoid
|
||||||
// incorrect value reporting in old IE and old Opera
|
// incorrect value reporting in old IE and old Opera
|
||||||
$(test).css(lineHeight, '99px');
|
$(test).css(lineHeight, '99px');
|
||||||
if ($(test).css(lineHeight) === '99px') {
|
if ($(test).css(lineHeight) === '99px') {
|
||||||
copyStyle.push(lineHeight);
|
copyStyle.push(lineHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
$.fn.autosize = function (options) {
|
$.fn.autosize = function (options) {
|
||||||
options = $.extend({}, defaults, options || {});
|
options = $.extend({}, defaults, options || {});
|
||||||
|
|
||||||
return this.each(function () {
|
return this.each(function () {
|
||||||
var
|
var
|
||||||
ta = this,
|
ta = this,
|
||||||
$ta = $(ta),
|
$ta = $(ta),
|
||||||
mirror,
|
mirror,
|
||||||
minHeight = $ta.height(),
|
minHeight = $ta.height(),
|
||||||
maxHeight = parseInt($ta.css('maxHeight'), 10),
|
maxHeight = parseInt($ta.css('maxHeight'), 10),
|
||||||
active,
|
active,
|
||||||
i = copyStyle.length,
|
i = copyStyle.length,
|
||||||
resize,
|
resize,
|
||||||
boxOffset = 0,
|
boxOffset = 0,
|
||||||
value = ta.value,
|
value = ta.value,
|
||||||
callback = $.isFunction(options.callback);
|
callback = $.isFunction(options.callback);
|
||||||
|
|
||||||
if ($ta.css('box-sizing') === borderBox || $ta.css('-moz-box-sizing') === borderBox || $ta.css('-webkit-box-sizing') === borderBox){
|
if ($ta.css('box-sizing') === borderBox || $ta.css('-moz-box-sizing') === borderBox || $ta.css('-webkit-box-sizing') === borderBox){
|
||||||
boxOffset = $ta.outerHeight() - $ta.height();
|
boxOffset = $ta.outerHeight() - $ta.height();
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($ta.data('mirror') || $ta.data('ismirror')) {
|
if ($ta.data('mirror') || $ta.data('ismirror')) {
|
||||||
// if autosize has already been applied, exit.
|
// if autosize has already been applied, exit.
|
||||||
// if autosize is being applied to a mirror element, exit.
|
// if autosize is being applied to a mirror element, exit.
|
||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
mirror = $(copy).data('ismirror', true).addClass(options.className)[0];
|
mirror = $(copy).data('ismirror', true).addClass(options.className)[0];
|
||||||
|
|
||||||
resize = $ta.css('resize') === 'none' ? 'none' : 'horizontal';
|
resize = $ta.css('resize') === 'none' ? 'none' : 'horizontal';
|
||||||
|
|
||||||
$ta.data('mirror', $(mirror)).css({
|
$ta.data('mirror', $(mirror)).css({
|
||||||
overflow: hidden,
|
overflow: hidden,
|
||||||
overflowY: hidden,
|
overflowY: hidden,
|
||||||
wordWrap: 'break-word',
|
wordWrap: 'break-word',
|
||||||
resize: resize
|
resize: resize
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// Opera returns '-1px' when max-height is set to 'none'.
|
// Opera returns '-1px' when max-height is set to 'none'.
|
||||||
maxHeight = maxHeight && maxHeight > 0 ? maxHeight : 9e4;
|
maxHeight = maxHeight && maxHeight > 0 ? maxHeight : 9e4;
|
||||||
|
|
||||||
// Using mainly bare JS in this function because it is going
|
// Using mainly bare JS in this function because it is going
|
||||||
// to fire very often while typing, and needs to very efficient.
|
// to fire very often while typing, and needs to very efficient.
|
||||||
function adjust() {
|
function adjust() {
|
||||||
var height, overflow, original;
|
var height, overflow, original;
|
||||||
|
|
||||||
// the active flag keeps IE from tripping all over itself. Otherwise
|
// the active flag keeps IE from tripping all over itself. Otherwise
|
||||||
// actions in the adjust function will cause IE to call adjust again.
|
// actions in the adjust function will cause IE to call adjust again.
|
||||||
if (!active) {
|
if (!active) {
|
||||||
active = true;
|
active = true;
|
||||||
mirror.value = ta.value + options.append;
|
mirror.value = ta.value + options.append;
|
||||||
mirror.style.overflowY = ta.style.overflowY;
|
mirror.style.overflowY = ta.style.overflowY;
|
||||||
original = parseInt(ta.style.height,10);
|
original = parseInt(ta.style.height,10);
|
||||||
|
|
||||||
// Update the width in case the original textarea width has changed
|
// Update the width in case the original textarea width has changed
|
||||||
mirror.style.width = $ta.css('width');
|
mirror.style.width = $ta.css('width');
|
||||||
|
|
||||||
// Needed for IE to reliably return the correct scrollHeight
|
// Needed for IE to reliably return the correct scrollHeight
|
||||||
mirror.scrollTop = 0;
|
mirror.scrollTop = 0;
|
||||||
|
|
||||||
// Set a very high value for scrollTop to be sure the
|
// Set a very high value for scrollTop to be sure the
|
||||||
// mirror is scrolled all the way to the bottom.
|
// mirror is scrolled all the way to the bottom.
|
||||||
mirror.scrollTop = 9e4;
|
mirror.scrollTop = 9e4;
|
||||||
|
|
||||||
height = mirror.scrollTop;
|
height = mirror.scrollTop;
|
||||||
overflow = hidden;
|
overflow = hidden;
|
||||||
if (height > maxHeight) {
|
if (height > maxHeight) {
|
||||||
height = maxHeight;
|
height = maxHeight;
|
||||||
overflow = 'scroll';
|
overflow = 'scroll';
|
||||||
} else if (height < minHeight) {
|
} else if (height < minHeight) {
|
||||||
height = minHeight;
|
height = minHeight;
|
||||||
}
|
}
|
||||||
height += boxOffset;
|
height += boxOffset;
|
||||||
ta.style.overflowY = overflow;
|
ta.style.overflowY = overflow;
|
||||||
|
|
||||||
if (original !== height) {
|
if (original !== height) {
|
||||||
ta.style.height = height + 'px';
|
ta.style.height = height + 'px';
|
||||||
if (callback) {
|
if (callback) {
|
||||||
options.callback.call(ta);
|
options.callback.call(ta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This small timeout gives IE a chance to draw it's scrollbar
|
// This small timeout gives IE a chance to draw it's scrollbar
|
||||||
// before adjust can be run again (prevents an infinite loop).
|
// before adjust can be run again (prevents an infinite loop).
|
||||||
setTimeout(function () {
|
setTimeout(function () {
|
||||||
active = false;
|
active = false;
|
||||||
}, 1);
|
}, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// mirror is a duplicate textarea located off-screen that
|
// mirror is a duplicate textarea located off-screen that
|
||||||
// is automatically updated to contain the same text as the
|
// is automatically updated to contain the same text as the
|
||||||
// original textarea. mirror always has a height of 0.
|
// original textarea. mirror always has a height of 0.
|
||||||
// This gives a cross-browser supported way getting the actual
|
// This gives a cross-browser supported way getting the actual
|
||||||
// height of the text, through the scrollTop property.
|
// height of the text, through the scrollTop property.
|
||||||
while (i--) {
|
while (i--) {
|
||||||
mirror.style[copyStyle[i]] = $ta.css(copyStyle[i]);
|
mirror.style[copyStyle[i]] = $ta.css(copyStyle[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
$('body').append(mirror);
|
$('body').append(mirror);
|
||||||
|
|
||||||
if (onpropertychange in ta) {
|
if (onpropertychange in ta) {
|
||||||
if (oninput in ta) {
|
if (oninput in ta) {
|
||||||
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
|
// Detects IE9. IE9 does not fire onpropertychange or oninput for deletions,
|
||||||
// so binding to onkeyup to catch most of those occassions. There is no way that I
|
// so binding to onkeyup to catch most of those occassions. There is no way that I
|
||||||
// know of to detect something like 'cut' in IE9.
|
// know of to detect something like 'cut' in IE9.
|
||||||
ta[oninput] = ta.onkeyup = adjust;
|
ta[oninput] = ta.onkeyup = adjust;
|
||||||
} else {
|
} else {
|
||||||
// IE7 / IE8
|
// IE7 / IE8
|
||||||
ta[onpropertychange] = adjust;
|
ta[onpropertychange] = adjust;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Modern Browsers
|
// Modern Browsers
|
||||||
ta[oninput] = adjust;
|
ta[oninput] = adjust;
|
||||||
|
|
||||||
// The textarea overflow is now hidden. But Chrome doesn't reflow the text after the scrollbars are removed.
|
// The textarea overflow is now hidden. But Chrome doesn't reflow the text after the scrollbars are removed.
|
||||||
// This is a hack to get Chrome to reflow it's text.
|
// This is a hack to get Chrome to reflow it's text.
|
||||||
ta.value = '';
|
ta.value = '';
|
||||||
ta.value = value;
|
ta.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
$(window).resize(adjust);
|
$(window).resize(adjust);
|
||||||
|
|
||||||
// Allow for manual triggering if needed.
|
// Allow for manual triggering if needed.
|
||||||
$ta.bind('autosize', adjust);
|
$ta.bind('autosize', adjust);
|
||||||
|
|
||||||
// Call adjust in case the textarea already contains text.
|
// Call adjust in case the textarea already contains text.
|
||||||
adjust();
|
adjust();
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
// Makes no changes for older browsers (FireFox3- and Safari4-)
|
// Makes no changes for older browsers (FireFox3- and Safari4-)
|
||||||
$.fn.autosize = function (callback) {
|
$.fn.autosize = function (callback) {
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
}(jQuery));
|
}(jQuery));
|
|
@ -7,18 +7,18 @@
|
||||||
if (typeof global.JSON == "undefined" || !global.JSON) {
|
if (typeof global.JSON == "undefined" || !global.JSON) {
|
||||||
global.JSON = {};
|
global.JSON = {};
|
||||||
}
|
}
|
||||||
|
|
||||||
global.JSON.minify = function(json) {
|
global.JSON.minify = function(json) {
|
||||||
|
|
||||||
var tokenizer = /"|(\/\*)|(\*\/)|(\/\/)|\n|\r/g,
|
var tokenizer = /"|(\/\*)|(\*\/)|(\/\/)|\n|\r/g,
|
||||||
in_string = false,
|
in_string = false,
|
||||||
in_multiline_comment = false,
|
in_multiline_comment = false,
|
||||||
in_singleline_comment = false,
|
in_singleline_comment = false,
|
||||||
tmp, tmp2, new_str = [], ns = 0, from = 0, lc, rc
|
tmp, tmp2, new_str = [], ns = 0, from = 0, lc, rc
|
||||||
;
|
;
|
||||||
|
|
||||||
tokenizer.lastIndex = 0;
|
tokenizer.lastIndex = 0;
|
||||||
|
|
||||||
while (tmp = tokenizer.exec(json)) {
|
while (tmp = tokenizer.exec(json)) {
|
||||||
lc = RegExp.leftContext;
|
lc = RegExp.leftContext;
|
||||||
rc = RegExp.rightContext;
|
rc = RegExp.rightContext;
|
||||||
|
@ -30,7 +30,7 @@
|
||||||
new_str[ns++] = tmp2;
|
new_str[ns++] = tmp2;
|
||||||
}
|
}
|
||||||
from = tokenizer.lastIndex;
|
from = tokenizer.lastIndex;
|
||||||
|
|
||||||
if (tmp[0] == "\"" && !in_multiline_comment && !in_singleline_comment) {
|
if (tmp[0] == "\"" && !in_multiline_comment && !in_singleline_comment) {
|
||||||
tmp2 = lc.match(/(\\)*$/);
|
tmp2 = lc.match(/(\\)*$/);
|
||||||
if (!in_string || !tmp2 || (tmp2[0].length % 2) == 0) { // start of string with ", or unescaped " character found to end string
|
if (!in_string || !tmp2 || (tmp2[0].length % 2) == 0) { // start of string with ", or unescaped " character found to end string
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
var socket,
|
var socket,
|
||||||
loc = document.location,
|
loc = document.location,
|
||||||
port = loc.port == "" ? (loc.protocol == "https:" ? 443 : 80) : loc.port,
|
port = loc.port == "" ? (loc.protocol == "https:" ? 443 : 80) : loc.port,
|
||||||
|
@ -81,7 +81,7 @@ $(document).ready(function () {
|
||||||
message = "<span class='status'>" + data.message.toString() + "</span>";
|
message = "<span class='status'>" + data.message.toString() + "</span>";
|
||||||
}
|
}
|
||||||
if (data.error) {
|
if (data.error) {
|
||||||
message = "<span class='error'>" + data.error.toString() + "<span>";
|
message = "<span class='error'>" + data.error.toString() + "<span>";
|
||||||
}
|
}
|
||||||
$("#progress.dialog .message").html(message);
|
$("#progress.dialog .message").html(message);
|
||||||
$("#progress.dialog .history").append("<div>" + message + "</div>");
|
$("#progress.dialog .history").append("<div>" + message + "</div>");
|
||||||
|
|
|
@ -18,11 +18,11 @@ $(document).ready(function () {
|
||||||
{
|
{
|
||||||
$('.settings').append(settings.results);
|
$('.settings').append(settings.results);
|
||||||
$('.settings').focus();
|
$('.settings').focus();
|
||||||
$('.settings').autosize();
|
$('.settings').autosize();
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
alert("YOUR JSON IS BAD AND YOU SHOULD FEEL BAD");
|
alert("YOUR JSON IS BAD AND YOU SHOULD FEEL BAD");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
/* When the admin clicks save Settings check the JSON then send the JSON back to the server */
|
/* When the admin clicks save Settings check the JSON then send the JSON back to the server */
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -274,12 +274,12 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
||||||
padContents.currentTime += timeDelta;
|
padContents.currentTime += timeDelta;
|
||||||
debugLog('Time Delta: ', timeDelta)
|
debugLog('Time Delta: ', timeDelta)
|
||||||
updateTimer();
|
updateTimer();
|
||||||
|
|
||||||
var authors = _.map(padContents.getActiveAuthors(), function(name)
|
var authors = _.map(padContents.getActiveAuthors(), function(name)
|
||||||
{
|
{
|
||||||
return authorData[name];
|
return authorData[name];
|
||||||
});
|
});
|
||||||
|
|
||||||
BroadcastSlider.setAuthors(authors);
|
BroadcastSlider.setAuthors(authors);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -292,9 +292,9 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
||||||
str = '0' + str;
|
str = '0' + str;
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var date = new Date(padContents.currentTime);
|
var date = new Date(padContents.currentTime);
|
||||||
var dateFormat = function()
|
var dateFormat = function()
|
||||||
{
|
{
|
||||||
|
@ -306,18 +306,18 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
||||||
var seconds = zpad(date.getSeconds(), 2);
|
var seconds = zpad(date.getSeconds(), 2);
|
||||||
return ([month, '/', day, '/', year, ' ', hours, ':', minutes, ':', seconds].join(""));
|
return ([month, '/', day, '/', year, ' ', hours, ':', minutes, ':', seconds].join(""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
$('#timer').html(dateFormat());
|
$('#timer').html(dateFormat());
|
||||||
|
|
||||||
var revisionDate = ["Saved", ["Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"][date.getMonth()], date.getDate() + ",", date.getFullYear()].join(" ")
|
var revisionDate = ["Saved", ["Jan", "Feb", "March", "April", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"][date.getMonth()], date.getDate() + ",", date.getFullYear()].join(" ")
|
||||||
$('#revision_date').html(revisionDate)
|
$('#revision_date').html(revisionDate)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateTimer();
|
updateTimer();
|
||||||
|
|
||||||
function goToRevision(newRevision)
|
function goToRevision(newRevision)
|
||||||
|
@ -380,7 +380,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
||||||
|
|
||||||
changesetLoader.queueUp(start, 1, update);
|
changesetLoader.queueUp(start, 1, update);
|
||||||
}
|
}
|
||||||
|
|
||||||
var authors = _.map(padContents.getActiveAuthors(), function(name){
|
var authors = _.map(padContents.getActiveAuthors(), function(name){
|
||||||
return authorData[name];
|
return authorData[name];
|
||||||
});
|
});
|
||||||
|
@ -549,7 +549,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro
|
||||||
goToRevision.apply(goToRevision, arguments);
|
goToRevision.apply(goToRevision, arguments);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BroadcastSlider.onSlider(goToRevisionIfEnabled);
|
BroadcastSlider.onSlider(goToRevisionIfEnabled);
|
||||||
|
|
||||||
var dynamicCSS = makeCSSManager('dynamicsyntax');
|
var dynamicCSS = makeCSSManager('dynamicsyntax');
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -56,7 +56,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
slidercallbacks[i](newval);
|
slidercallbacks[i](newval);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var updateSliderElements = function()
|
var updateSliderElements = function()
|
||||||
{
|
{
|
||||||
for (var i = 0; i < savedRevisions.length; i++)
|
for (var i = 0; i < savedRevisions.length; i++)
|
||||||
|
@ -65,7 +65,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
savedRevisions[i].css('left', (position * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0)) - 1);
|
savedRevisions[i].css('left', (position * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0)) - 1);
|
||||||
}
|
}
|
||||||
$("#ui-slider-handle").css('left', sliderPos * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0));
|
$("#ui-slider-handle").css('left', sliderPos * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
var addSavedRevision = function(position, info)
|
var addSavedRevision = function(position, info)
|
||||||
{
|
{
|
||||||
|
@ -162,7 +162,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
var height = $('#timeslider-top').height();
|
var height = $('#timeslider-top').height();
|
||||||
$('#editorcontainerbox').css({marginTop: height});
|
$('#editorcontainerbox').css({marginTop: height});
|
||||||
}, 600);
|
}, 600);
|
||||||
|
|
||||||
function setAuthors(authors)
|
function setAuthors(authors)
|
||||||
{
|
{
|
||||||
var authorsList = $("#authorsList");
|
var authorsList = $("#authorsList");
|
||||||
|
@ -176,7 +176,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
if (author.name)
|
if (author.name)
|
||||||
{
|
{
|
||||||
if (numNamed !== 0) authorsList.append(', ');
|
if (numNamed !== 0) authorsList.append(', ');
|
||||||
|
|
||||||
$('<span />')
|
$('<span />')
|
||||||
.text(author.name || "unnamed")
|
.text(author.name || "unnamed")
|
||||||
.css('background-color', authorColor)
|
.css('background-color', authorColor)
|
||||||
|
@ -199,11 +199,11 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
} else {
|
} else {
|
||||||
authorsList.append(anonymousAuthorString);
|
authorsList.append(anonymousAuthorString);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(colorsAnonymous.length > 0){
|
if(colorsAnonymous.length > 0){
|
||||||
authorsList.append(' (');
|
authorsList.append(' (');
|
||||||
_.each(colorsAnonymous, function(color, i){
|
_.each(colorsAnonymous, function(color, i){
|
||||||
if( i > 0 ) authorsList.append(' ');
|
if( i > 0 ) authorsList.append(' ');
|
||||||
$('<span> </span>')
|
$('<span> </span>')
|
||||||
.css('background-color', color)
|
.css('background-color', color)
|
||||||
.addClass('author author-anonymous')
|
.addClass('author author-anonymous')
|
||||||
|
@ -211,13 +211,13 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
});
|
});
|
||||||
authorsList.append(')');
|
authorsList.append(')');
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (authors.length == 0)
|
if (authors.length == 0)
|
||||||
{
|
{
|
||||||
authorsList.append("No Authors");
|
authorsList.append("No Authors");
|
||||||
}
|
}
|
||||||
|
|
||||||
fixPadHeight();
|
fixPadHeight();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,7 +275,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
{
|
{
|
||||||
disableSelection($("#playpause_button")[0]);
|
disableSelection($("#playpause_button")[0]);
|
||||||
disableSelection($("#timeslider")[0]);
|
disableSelection($("#timeslider")[0]);
|
||||||
|
|
||||||
$(document).keyup(function(e)
|
$(document).keyup(function(e)
|
||||||
{
|
{
|
||||||
var code = -1;
|
var code = -1;
|
||||||
|
@ -320,7 +320,7 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
else if (code == 32) playpause();
|
else if (code == 32) playpause();
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
$(window).resize(function()
|
$(window).resize(function()
|
||||||
{
|
{
|
||||||
updateSliderElements();
|
updateSliderElements();
|
||||||
|
@ -470,16 +470,16 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
$("#revision").css('right', "20px");
|
$("#revision").css('right', "20px");
|
||||||
$("#revision").css('top', "20px");
|
$("#revision").css('top', "20px");
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#timeslider").show();
|
$("#timeslider").show();
|
||||||
setSliderLength(clientVars.collab_client_vars.rev);
|
setSliderLength(clientVars.collab_client_vars.rev);
|
||||||
setSliderPosition(clientVars.collab_client_vars.rev);
|
setSliderPosition(clientVars.collab_client_vars.rev);
|
||||||
|
|
||||||
_.each(clientVars.savedRevisions, function(revision)
|
_.each(clientVars.savedRevisions, function(revision)
|
||||||
{
|
{
|
||||||
addSavedRevision(revision.revNum, revision);
|
addSavedRevision(revision.revNum, revision);
|
||||||
})
|
})
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
})();
|
})();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -30,8 +30,8 @@ var chat = (function()
|
||||||
var isStuck = false;
|
var isStuck = false;
|
||||||
var chatMentions = 0;
|
var chatMentions = 0;
|
||||||
var self = {
|
var self = {
|
||||||
show: function ()
|
show: function ()
|
||||||
{
|
{
|
||||||
$("#chaticon").hide();
|
$("#chaticon").hide();
|
||||||
$("#chatbox").show();
|
$("#chatbox").show();
|
||||||
self.scrollDown();
|
self.scrollDown();
|
||||||
|
@ -55,7 +55,7 @@ var chat = (function()
|
||||||
isStuck = false;
|
isStuck = false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
hide: function ()
|
hide: function ()
|
||||||
{
|
{
|
||||||
$("#chatcounter").text("0");
|
$("#chatcounter").text("0");
|
||||||
$("#chaticon").show();
|
$("#chaticon").show();
|
||||||
|
@ -69,7 +69,7 @@ var chat = (function()
|
||||||
self.lastMessage = $('#chattext > p').eq(-1);
|
self.lastMessage = $('#chattext > p').eq(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
send: function()
|
send: function()
|
||||||
{
|
{
|
||||||
var text = $("#chatinput").val();
|
var text = $("#chatinput").val();
|
||||||
|
@ -77,10 +77,10 @@ var chat = (function()
|
||||||
$("#chatinput").val("");
|
$("#chatinput").val("");
|
||||||
},
|
},
|
||||||
addMessage: function(msg, increment)
|
addMessage: function(msg, increment)
|
||||||
{
|
{
|
||||||
//correct the time
|
//correct the time
|
||||||
msg.time += this._pad.clientTimeOffset;
|
msg.time += this._pad.clientTimeOffset;
|
||||||
|
|
||||||
//create the time string
|
//create the time string
|
||||||
var minutes = "" + new Date(msg.time).getMinutes();
|
var minutes = "" + new Date(msg.time).getMinutes();
|
||||||
var hours = "" + new Date(msg.time).getHours();
|
var hours = "" + new Date(msg.time).getHours();
|
||||||
|
@ -89,7 +89,7 @@ var chat = (function()
|
||||||
if(hours.length == 1)
|
if(hours.length == 1)
|
||||||
hours = "0" + hours ;
|
hours = "0" + hours ;
|
||||||
var timeStr = hours + ":" + minutes;
|
var timeStr = hours + ":" + minutes;
|
||||||
|
|
||||||
//create the authorclass
|
//create the authorclass
|
||||||
var authorClass = "author-" + msg.userId.replace(/[^a-y0-9]/g, function(c)
|
var authorClass = "author-" + msg.userId.replace(/[^a-y0-9]/g, function(c)
|
||||||
{
|
{
|
||||||
|
@ -109,20 +109,20 @@ var chat = (function()
|
||||||
}
|
}
|
||||||
/* End of new action */
|
/* End of new action */
|
||||||
|
|
||||||
var authorName = msg.userName == null ? "unnamed" : padutils.escapeHtml(msg.userName);
|
var authorName = msg.userName == null ? "unnamed" : padutils.escapeHtml(msg.userName);
|
||||||
|
|
||||||
var html = "<p class='" + authorClass + "'><b>" + authorName + ":</b><span class='time " + authorClass + "'>" + timeStr + "</span> " + text + "</p>";
|
var html = "<p class='" + authorClass + "'><b>" + authorName + ":</b><span class='time " + authorClass + "'>" + timeStr + "</span> " + text + "</p>";
|
||||||
$("#chattext").append(html);
|
$("#chattext").append(html);
|
||||||
|
|
||||||
//should we increment the counter??
|
//should we increment the counter??
|
||||||
if(increment)
|
if(increment)
|
||||||
{
|
{
|
||||||
var count = Number($("#chatcounter").text());
|
var count = Number($("#chatcounter").text());
|
||||||
count++;
|
count++;
|
||||||
|
|
||||||
// is the users focus already in the chatbox?
|
// is the users focus already in the chatbox?
|
||||||
var alreadyFocused = $("#chatinput").is(":focus");
|
var alreadyFocused = $("#chatinput").is(":focus");
|
||||||
|
|
||||||
$("#chatcounter").text(count);
|
$("#chatcounter").text(count);
|
||||||
// chat throb stuff -- Just make it throw for twice as long
|
// chat throb stuff -- Just make it throw for twice as long
|
||||||
if(wasMentioned && !alreadyFocused)
|
if(wasMentioned && !alreadyFocused)
|
||||||
|
@ -156,7 +156,7 @@ var chat = (function()
|
||||||
self.send();
|
self.send();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var that = this;
|
var that = this;
|
||||||
$.each(clientVars.chatHistory, function(i, o){
|
$.each(clientVars.chatHistory, function(i, o){
|
||||||
that.addMessage(o, false);
|
that.addMessage(o, false);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -366,7 +366,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
msg.userInfo.colorId = initialUserInfo.globalUserColor;
|
msg.userInfo.colorId = initialUserInfo.globalUserColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (userSet[id])
|
if (userSet[id])
|
||||||
{
|
{
|
||||||
userSet[id] = userInfo;
|
userSet[id] = userInfo;
|
||||||
|
@ -433,7 +433,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
{
|
{
|
||||||
colorId = clientVars.colorPalette[colorId];
|
colorId = clientVars.colorPalette[colorId];
|
||||||
}
|
}
|
||||||
|
|
||||||
var cssColor = colorId;
|
var cssColor = colorId;
|
||||||
if (inactive)
|
if (inactive)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -241,14 +241,14 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
{
|
{
|
||||||
state.listNesting = (state.listNesting || 0) + 1;
|
state.listNesting = (state.listNesting || 0) + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(listType === 'none' || !listType ){
|
if(listType === 'none' || !listType ){
|
||||||
delete state.lineAttributes['list'];
|
delete state.lineAttributes['list'];
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
state.lineAttributes['list'] = listType;
|
state.lineAttributes['list'] = listType;
|
||||||
}
|
}
|
||||||
|
|
||||||
_recalcAttribString(state);
|
_recalcAttribString(state);
|
||||||
return oldListType;
|
return oldListType;
|
||||||
}
|
}
|
||||||
|
@ -315,7 +315,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
return [key, value];
|
return [key, value];
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
lines.appendText('*', Changeset.makeAttribsString('+', attributes , apool));
|
lines.appendText('*', Changeset.makeAttribsString('+', attributes , apool));
|
||||||
}
|
}
|
||||||
cc.startNewLine = function(state)
|
cc.startNewLine = function(state)
|
||||||
|
@ -385,7 +385,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
text:txt,
|
text:txt,
|
||||||
styl: null,
|
styl: null,
|
||||||
cls: null
|
cls: null
|
||||||
});
|
});
|
||||||
var txt = (typeof(txtFromHook)=='object'&&txtFromHook.length==0)?dom.nodeValue(node):txtFromHook[0];
|
var txt = (typeof(txtFromHook)=='object'&&txtFromHook.length==0)?dom.nodeValue(node):txtFromHook[0];
|
||||||
|
|
||||||
var rest = '';
|
var rest = '';
|
||||||
|
@ -454,7 +454,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
{
|
{
|
||||||
var tname = (dom.nodeTagName(node) || "").toLowerCase();
|
var tname = (dom.nodeTagName(node) || "").toLowerCase();
|
||||||
if (tname == "br")
|
if (tname == "br")
|
||||||
{
|
{
|
||||||
this.breakLine = true;
|
this.breakLine = true;
|
||||||
var tvalue = dom.nodeAttr(node, 'value');
|
var tvalue = dom.nodeAttr(node, 'value');
|
||||||
var induceLineBreak = hooks.callAll('collectContentLineBreak', {
|
var induceLineBreak = hooks.callAll('collectContentLineBreak', {
|
||||||
|
@ -464,11 +464,11 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
||||||
tvalue:tvalue,
|
tvalue:tvalue,
|
||||||
styl: null,
|
styl: null,
|
||||||
cls: null
|
cls: null
|
||||||
});
|
});
|
||||||
var startNewLine= (typeof(induceLineBreak)=='object'&&induceLineBreak.length==0)?true:induceLineBreak[0];
|
var startNewLine= (typeof(induceLineBreak)=='object'&&induceLineBreak.length==0)?true:induceLineBreak[0];
|
||||||
if(startNewLine){
|
if(startNewLine){
|
||||||
cc.startNewLine(state);
|
cc.startNewLine(state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (tname == "script" || tname == "style")
|
else if (tname == "script" || tname == "style")
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -26,7 +26,7 @@ function makeCSSManager(emptyStylesheetTitle)
|
||||||
function getSheetByTitle(title)
|
function getSheetByTitle(title)
|
||||||
{
|
{
|
||||||
var allSheets = document.styleSheets;
|
var allSheets = document.styleSheets;
|
||||||
|
|
||||||
for (var i = 0; i < allSheets.length; i++)
|
for (var i = 0; i < allSheets.length; i++)
|
||||||
{
|
{
|
||||||
var s = allSheets[i];
|
var s = allSheets[i];
|
||||||
|
@ -37,7 +37,7 @@ function makeCSSManager(emptyStylesheetTitle)
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var browserSheet = getSheetByTitle(emptyStylesheetTitle);
|
var browserSheet = getSheetByTitle(emptyStylesheetTitle);
|
||||||
|
|
||||||
function browserRules()
|
function browserRules()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -82,7 +82,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
||||||
}
|
}
|
||||||
|
|
||||||
var html = [];
|
var html = [];
|
||||||
var preHtml = '',
|
var preHtml = '',
|
||||||
postHtml = '';
|
postHtml = '';
|
||||||
var curHTML = null;
|
var curHTML = null;
|
||||||
|
|
||||||
|
@ -118,10 +118,10 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
||||||
preHtml = '<ol '+start+' class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>';
|
preHtml = '<ol '+start+' class="list-' + Security.escapeHTMLAttribute(listType) + '"><li>';
|
||||||
postHtml = '</li></ol>';
|
postHtml = '</li></ol>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
processedMarker = true;
|
processedMarker = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
_.map(hooks.callAll("aceDomLineProcessLineAttributes", {
|
_.map(hooks.callAll("aceDomLineProcessLineAttributes", {
|
||||||
domline: domline,
|
domline: domline,
|
||||||
cls: cls
|
cls: cls
|
||||||
|
@ -131,11 +131,11 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
||||||
postHtml += modifier.postHtml;
|
postHtml += modifier.postHtml;
|
||||||
processedMarker |= modifier.processedMarker;
|
processedMarker |= modifier.processedMarker;
|
||||||
});
|
});
|
||||||
|
|
||||||
if( processedMarker ){
|
if( processedMarker ){
|
||||||
result.lineMarker += txt.length;
|
result.lineMarker += txt.length;
|
||||||
return; // don't append any text
|
return; // don't append any text
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -229,7 +229,7 @@ domline.createDomLine = function(nonEmpty, doesWrap, optBrowser, optDocument)
|
||||||
result.node.innerHTML = curHTML;
|
result.node.innerHTML = curHTML;
|
||||||
}
|
}
|
||||||
if (lineClass !== null) result.node.className = lineClass;
|
if (lineClass !== null) result.node.className = lineClass;
|
||||||
|
|
||||||
hooks.callAll("acePostWriteDomLineHTML", {
|
hooks.callAll("acePostWriteDomLineHTML", {
|
||||||
node: result.node
|
node: result.node
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// Farbtastic 2.0 alpha
|
// Farbtastic 2.0 alpha
|
||||||
(function ($) {
|
(function ($) {
|
||||||
|
|
||||||
var __debug = false;
|
var __debug = false;
|
||||||
var __factor = 0.5;
|
var __factor = 0.5;
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ $.farbtastic = function (container, options) {
|
||||||
|
|
||||||
$._farbtastic = function (container, options) {
|
$._farbtastic = function (container, options) {
|
||||||
var fb = this;
|
var fb = this;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -134,7 +134,7 @@ $._farbtastic = function (container, options) {
|
||||||
fb.ctxOverlay = fb.cnvOverlay[0].getContext('2d');
|
fb.ctxOverlay = fb.cnvOverlay[0].getContext('2d');
|
||||||
fb.ctxMask.translate(fb.mid, fb.mid);
|
fb.ctxMask.translate(fb.mid, fb.mid);
|
||||||
fb.ctxOverlay.translate(fb.mid, fb.mid);
|
fb.ctxOverlay.translate(fb.mid, fb.mid);
|
||||||
|
|
||||||
// Draw widget base layers.
|
// Draw widget base layers.
|
||||||
fb.drawCircle();
|
fb.drawCircle();
|
||||||
fb.drawMask();
|
fb.drawMask();
|
||||||
|
@ -208,7 +208,7 @@ $._farbtastic = function (container, options) {
|
||||||
m.restore();
|
m.restore();
|
||||||
__debug && $('body').append('<div>drawCircle '+ (+(new Date()) - tm) +'ms');
|
__debug && $('body').append('<div>drawCircle '+ (+(new Date()) - tm) +'ms');
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw the saturation/luminance mask.
|
* Draw the saturation/luminance mask.
|
||||||
*/
|
*/
|
||||||
|
@ -232,9 +232,9 @@ $._farbtastic = function (container, options) {
|
||||||
|
|
||||||
outputPixel(x, y, c, a);
|
outputPixel(x, y, c, a);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Method #1: direct pixel access (new Canvas).
|
// Method #1: direct pixel access (new Canvas).
|
||||||
if (fb.ctxMask.getImageData) {
|
if (fb.ctxMask.getImageData) {
|
||||||
// Create half-resolution buffer.
|
// Create half-resolution buffer.
|
||||||
|
@ -295,7 +295,7 @@ $._farbtastic = function (container, options) {
|
||||||
}
|
}
|
||||||
cache.push([c, a]);
|
cache.push([c, a]);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
__debug && $('body').append('<div>drawMask '+ (+(new Date()) - tm) +'ms');
|
__debug && $('body').append('<div>drawMask '+ (+(new Date()) - tm) +'ms');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -343,7 +343,7 @@ $._farbtastic = function (container, options) {
|
||||||
|
|
||||||
// Draw markers
|
// Draw markers
|
||||||
fb.drawMarkers();
|
fb.drawMarkers();
|
||||||
|
|
||||||
// Linked elements or callback
|
// Linked elements or callback
|
||||||
if (typeof fb.callback == 'object') {
|
if (typeof fb.callback == 'object') {
|
||||||
// Set background/foreground color
|
// Set background/foreground color
|
||||||
|
@ -363,15 +363,15 @@ $._farbtastic = function (container, options) {
|
||||||
fb.callback.call(fb, fb.color);
|
fb.callback.call(fb, fb.color);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper for returning coordinates relative to the center.
|
* Helper for returning coordinates relative to the center.
|
||||||
*/
|
*/
|
||||||
fb.widgetCoords = function (event) {
|
fb.widgetCoords = function (event) {
|
||||||
return {
|
return {
|
||||||
x: event.pageX - fb.offset.left - fb.mid,
|
x: event.pageX - fb.offset.left - fb.mid,
|
||||||
y: event.pageY - fb.offset.top - fb.mid
|
y: event.pageY - fb.offset.top - fb.mid
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -434,7 +434,7 @@ $._farbtastic = function (container, options) {
|
||||||
fb.packDX = function (c, a) {
|
fb.packDX = function (c, a) {
|
||||||
return '#' + fb.dec2hex(a) + fb.dec2hex(c) + fb.dec2hex(c) + fb.dec2hex(c);
|
return '#' + fb.dec2hex(a) + fb.dec2hex(c) + fb.dec2hex(c) + fb.dec2hex(c);
|
||||||
};
|
};
|
||||||
|
|
||||||
fb.pack = function (rgb) {
|
fb.pack = function (rgb) {
|
||||||
var r = Math.round(rgb[0] * 255);
|
var r = Math.round(rgb[0] * 255);
|
||||||
var g = Math.round(rgb[1] * 255);
|
var g = Math.round(rgb[1] * 255);
|
||||||
|
|
82
src/static/js/jquery.js
vendored
82
src/static/js/jquery.js
vendored
|
@ -3885,7 +3885,7 @@ var Sizzle = function( selector, context, results, seed ) {
|
||||||
if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
|
if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( !selector || typeof selector !== "string" ) {
|
if ( !selector || typeof selector !== "string" ) {
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
@ -3895,7 +3895,7 @@ var Sizzle = function( selector, context, results, seed ) {
|
||||||
contextXML = Sizzle.isXML( context ),
|
contextXML = Sizzle.isXML( context ),
|
||||||
parts = [],
|
parts = [],
|
||||||
soFar = selector;
|
soFar = selector;
|
||||||
|
|
||||||
// Reset the position of the chunker regexp (start from head)
|
// Reset the position of the chunker regexp (start from head)
|
||||||
do {
|
do {
|
||||||
chunker.exec( "" );
|
chunker.exec( "" );
|
||||||
|
@ -3903,9 +3903,9 @@ var Sizzle = function( selector, context, results, seed ) {
|
||||||
|
|
||||||
if ( m ) {
|
if ( m ) {
|
||||||
soFar = m[3];
|
soFar = m[3];
|
||||||
|
|
||||||
parts.push( m[1] );
|
parts.push( m[1] );
|
||||||
|
|
||||||
if ( m[2] ) {
|
if ( m[2] ) {
|
||||||
extra = m[3];
|
extra = m[3];
|
||||||
break;
|
break;
|
||||||
|
@ -3929,7 +3929,7 @@ var Sizzle = function( selector, context, results, seed ) {
|
||||||
if ( Expr.relative[ selector ] ) {
|
if ( Expr.relative[ selector ] ) {
|
||||||
selector += parts.shift();
|
selector += parts.shift();
|
||||||
}
|
}
|
||||||
|
|
||||||
set = posProcess( selector, set, seed );
|
set = posProcess( selector, set, seed );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4057,7 +4057,7 @@ Sizzle.find = function( expr, context, isXML ) {
|
||||||
|
|
||||||
for ( i = 0, len = Expr.order.length; i < len; i++ ) {
|
for ( i = 0, len = Expr.order.length; i < len; i++ ) {
|
||||||
type = Expr.order[i];
|
type = Expr.order[i];
|
||||||
|
|
||||||
if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
|
if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
|
||||||
left = match[1];
|
left = match[1];
|
||||||
match.splice( 1, 1 );
|
match.splice( 1, 1 );
|
||||||
|
@ -4429,7 +4429,7 @@ var Expr = Sizzle.selectors = {
|
||||||
|
|
||||||
ATTR: function( match, curLoop, inplace, result, not, isXML ) {
|
ATTR: function( match, curLoop, inplace, result, not, isXML ) {
|
||||||
var name = match[1] = match[1].replace( rBackslash, "" );
|
var name = match[1] = match[1].replace( rBackslash, "" );
|
||||||
|
|
||||||
if ( !isXML && Expr.attrMap[name] ) {
|
if ( !isXML && Expr.attrMap[name] ) {
|
||||||
match[1] = Expr.attrMap[name];
|
match[1] = Expr.attrMap[name];
|
||||||
}
|
}
|
||||||
|
@ -4463,7 +4463,7 @@ var Expr = Sizzle.selectors = {
|
||||||
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
|
} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return match;
|
return match;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -4473,7 +4473,7 @@ var Expr = Sizzle.selectors = {
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
filters: {
|
filters: {
|
||||||
enabled: function( elem ) {
|
enabled: function( elem ) {
|
||||||
return elem.disabled === false && elem.type !== "hidden";
|
return elem.disabled === false && elem.type !== "hidden";
|
||||||
|
@ -4486,14 +4486,14 @@ var Expr = Sizzle.selectors = {
|
||||||
checked: function( elem ) {
|
checked: function( elem ) {
|
||||||
return elem.checked === true;
|
return elem.checked === true;
|
||||||
},
|
},
|
||||||
|
|
||||||
selected: function( elem ) {
|
selected: function( elem ) {
|
||||||
// Accessing this property makes selected-by-default
|
// Accessing this property makes selected-by-default
|
||||||
// options in Safari work properly
|
// options in Safari work properly
|
||||||
if ( elem.parentNode ) {
|
if ( elem.parentNode ) {
|
||||||
elem.parentNode.selectedIndex;
|
elem.parentNode.selectedIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
return elem.selected === true;
|
return elem.selected === true;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -4515,7 +4515,7 @@ var Expr = Sizzle.selectors = {
|
||||||
|
|
||||||
text: function( elem ) {
|
text: function( elem ) {
|
||||||
var attr = elem.getAttribute( "type" ), type = elem.type;
|
var attr = elem.getAttribute( "type" ), type = elem.type;
|
||||||
// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
|
// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc)
|
||||||
// use getAttribute instead to test this case
|
// use getAttribute instead to test this case
|
||||||
return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
|
return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
|
||||||
},
|
},
|
||||||
|
@ -4634,21 +4634,21 @@ var Expr = Sizzle.selectors = {
|
||||||
case "only":
|
case "only":
|
||||||
case "first":
|
case "first":
|
||||||
while ( (node = node.previousSibling) ) {
|
while ( (node = node.previousSibling) ) {
|
||||||
if ( node.nodeType === 1 ) {
|
if ( node.nodeType === 1 ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( type === "first" ) {
|
if ( type === "first" ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
node = elem;
|
node = elem;
|
||||||
|
|
||||||
case "last":
|
case "last":
|
||||||
while ( (node = node.nextSibling) ) {
|
while ( (node = node.nextSibling) ) {
|
||||||
if ( node.nodeType === 1 ) {
|
if ( node.nodeType === 1 ) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4661,22 +4661,22 @@ var Expr = Sizzle.selectors = {
|
||||||
if ( first === 1 && last === 0 ) {
|
if ( first === 1 && last === 0 ) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
doneName = match[0];
|
doneName = match[0];
|
||||||
parent = elem.parentNode;
|
parent = elem.parentNode;
|
||||||
|
|
||||||
if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
|
if ( parent && (parent[ expando ] !== doneName || !elem.nodeIndex) ) {
|
||||||
count = 0;
|
count = 0;
|
||||||
|
|
||||||
for ( node = parent.firstChild; node; node = node.nextSibling ) {
|
for ( node = parent.firstChild; node; node = node.nextSibling ) {
|
||||||
if ( node.nodeType === 1 ) {
|
if ( node.nodeType === 1 ) {
|
||||||
node.nodeIndex = ++count;
|
node.nodeIndex = ++count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
parent[ expando ] = doneName;
|
parent[ expando ] = doneName;
|
||||||
}
|
}
|
||||||
|
|
||||||
diff = elem.nodeIndex - last;
|
diff = elem.nodeIndex - last;
|
||||||
|
|
||||||
if ( first === 0 ) {
|
if ( first === 0 ) {
|
||||||
|
@ -4695,7 +4695,7 @@ var Expr = Sizzle.selectors = {
|
||||||
TAG: function( elem, match ) {
|
TAG: function( elem, match ) {
|
||||||
return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
|
return (match === "*" && elem.nodeType === 1) || !!elem.nodeName && elem.nodeName.toLowerCase() === match;
|
||||||
},
|
},
|
||||||
|
|
||||||
CLASS: function( elem, match ) {
|
CLASS: function( elem, match ) {
|
||||||
return (" " + (elem.className || elem.getAttribute("class")) + " ")
|
return (" " + (elem.className || elem.getAttribute("class")) + " ")
|
||||||
.indexOf( match ) > -1;
|
.indexOf( match ) > -1;
|
||||||
|
@ -4765,7 +4765,7 @@ var makeArray = function( array, results ) {
|
||||||
results.push.apply( results, array );
|
results.push.apply( results, array );
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
|
|
||||||
return array;
|
return array;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -4997,7 +4997,7 @@ if ( document.querySelectorAll ) {
|
||||||
if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
|
if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sizzle = function( query, context, extra, seed ) {
|
Sizzle = function( query, context, extra, seed ) {
|
||||||
context = context || document;
|
context = context || document;
|
||||||
|
|
||||||
|
@ -5006,24 +5006,24 @@ if ( document.querySelectorAll ) {
|
||||||
if ( !seed && !Sizzle.isXML(context) ) {
|
if ( !seed && !Sizzle.isXML(context) ) {
|
||||||
// See if we find a selector to speed up
|
// See if we find a selector to speed up
|
||||||
var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
|
var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
|
||||||
|
|
||||||
if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
|
if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
|
||||||
// Speed-up: Sizzle("TAG")
|
// Speed-up: Sizzle("TAG")
|
||||||
if ( match[1] ) {
|
if ( match[1] ) {
|
||||||
return makeArray( context.getElementsByTagName( query ), extra );
|
return makeArray( context.getElementsByTagName( query ), extra );
|
||||||
|
|
||||||
// Speed-up: Sizzle(".CLASS")
|
// Speed-up: Sizzle(".CLASS")
|
||||||
} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
|
} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
|
||||||
return makeArray( context.getElementsByClassName( match[2] ), extra );
|
return makeArray( context.getElementsByClassName( match[2] ), extra );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( context.nodeType === 9 ) {
|
if ( context.nodeType === 9 ) {
|
||||||
// Speed-up: Sizzle("body")
|
// Speed-up: Sizzle("body")
|
||||||
// The body element only exists once, optimize finding it
|
// The body element only exists once, optimize finding it
|
||||||
if ( query === "body" && context.body ) {
|
if ( query === "body" && context.body ) {
|
||||||
return makeArray( [ context.body ], extra );
|
return makeArray( [ context.body ], extra );
|
||||||
|
|
||||||
// Speed-up: Sizzle("#ID")
|
// Speed-up: Sizzle("#ID")
|
||||||
} else if ( match && match[3] ) {
|
} else if ( match && match[3] ) {
|
||||||
var elem = context.getElementById( match[3] );
|
var elem = context.getElementById( match[3] );
|
||||||
|
@ -5036,12 +5036,12 @@ if ( document.querySelectorAll ) {
|
||||||
if ( elem.id === match[3] ) {
|
if ( elem.id === match[3] ) {
|
||||||
return makeArray( [ elem ], extra );
|
return makeArray( [ elem ], extra );
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
return makeArray( [], extra );
|
return makeArray( [], extra );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return makeArray( context.querySelectorAll(query), extra );
|
return makeArray( context.querySelectorAll(query), extra );
|
||||||
} catch(qsaError) {}
|
} catch(qsaError) {}
|
||||||
|
@ -5079,7 +5079,7 @@ if ( document.querySelectorAll ) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return oldSizzle(query, context, extra, seed);
|
return oldSizzle(query, context, extra, seed);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -5106,7 +5106,7 @@ if ( document.querySelectorAll ) {
|
||||||
// This should fail with an exception
|
// This should fail with an exception
|
||||||
// Gecko does not error, returns false instead
|
// Gecko does not error, returns false instead
|
||||||
matches.call( document.documentElement, "[test!='']:sizzle" );
|
matches.call( document.documentElement, "[test!='']:sizzle" );
|
||||||
|
|
||||||
} catch( pseudoError ) {
|
} catch( pseudoError ) {
|
||||||
pseudoWorks = true;
|
pseudoWorks = true;
|
||||||
}
|
}
|
||||||
|
@ -5116,7 +5116,7 @@ if ( document.querySelectorAll ) {
|
||||||
expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
|
expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");
|
||||||
|
|
||||||
if ( !Sizzle.isXML( node ) ) {
|
if ( !Sizzle.isXML( node ) ) {
|
||||||
try {
|
try {
|
||||||
if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
|
if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
|
||||||
var ret = matches.call( node, expr );
|
var ret = matches.call( node, expr );
|
||||||
|
|
||||||
|
@ -5153,7 +5153,7 @@ if ( document.querySelectorAll ) {
|
||||||
if ( div.getElementsByClassName("e").length === 1 ) {
|
if ( div.getElementsByClassName("e").length === 1 ) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Expr.order.splice(1, 0, "CLASS");
|
Expr.order.splice(1, 0, "CLASS");
|
||||||
Expr.find.CLASS = function( match, context, isXML ) {
|
Expr.find.CLASS = function( match, context, isXML ) {
|
||||||
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
|
if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
|
||||||
|
@ -5204,7 +5204,7 @@ function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
|
||||||
|
|
||||||
if ( elem ) {
|
if ( elem ) {
|
||||||
var match = false;
|
var match = false;
|
||||||
|
|
||||||
elem = elem[dir];
|
elem = elem[dir];
|
||||||
|
|
||||||
while ( elem ) {
|
while ( elem ) {
|
||||||
|
@ -5257,7 +5257,7 @@ if ( document.documentElement.contains ) {
|
||||||
|
|
||||||
Sizzle.isXML = function( elem ) {
|
Sizzle.isXML = function( elem ) {
|
||||||
// documentElement is verified for cases where it doesn't yet exist
|
// documentElement is verified for cases where it doesn't yet exist
|
||||||
// (such as loading iframes in IE - #4833)
|
// (such as loading iframes in IE - #4833)
|
||||||
var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
|
var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;
|
||||||
|
|
||||||
return documentElement ? documentElement.nodeName !== "HTML" : false;
|
return documentElement ? documentElement.nodeName !== "HTML" : false;
|
||||||
|
@ -5374,11 +5374,11 @@ jQuery.fn.extend({
|
||||||
},
|
},
|
||||||
|
|
||||||
is: function( selector ) {
|
is: function( selector ) {
|
||||||
return !!selector && (
|
return !!selector && (
|
||||||
typeof selector === "string" ?
|
typeof selector === "string" ?
|
||||||
// If this is a positional selector, check membership in the returned set
|
// If this is a positional selector, check membership in the returned set
|
||||||
// so $("p:first").is("p:last") won't return true for a doc with two "p".
|
// so $("p:first").is("p:last") won't return true for a doc with two "p".
|
||||||
POS.test( selector ) ?
|
POS.test( selector ) ?
|
||||||
jQuery( selector, this.context ).index( this[0] ) >= 0 :
|
jQuery( selector, this.context ).index( this[0] ) >= 0 :
|
||||||
jQuery.filter( selector, this ).length > 0 :
|
jQuery.filter( selector, this ).length > 0 :
|
||||||
this.filter( selector ).length > 0 );
|
this.filter( selector ).length > 0 );
|
||||||
|
@ -5386,7 +5386,7 @@ jQuery.fn.extend({
|
||||||
|
|
||||||
closest: function( selectors, context ) {
|
closest: function( selectors, context ) {
|
||||||
var ret = [], i, l, cur = this[0];
|
var ret = [], i, l, cur = this[0];
|
||||||
|
|
||||||
// Array (deprecated as of jQuery 1.7)
|
// Array (deprecated as of jQuery 1.7)
|
||||||
if ( jQuery.isArray( selectors ) ) {
|
if ( jQuery.isArray( selectors ) ) {
|
||||||
var level = 1;
|
var level = 1;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -74,10 +74,10 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
||||||
{
|
{
|
||||||
var classes = '';
|
var classes = '';
|
||||||
var isLineAttribMarker = false;
|
var isLineAttribMarker = false;
|
||||||
|
|
||||||
Changeset.eachAttribNumber(attribs, function(n)
|
Changeset.eachAttribNumber(attribs, function(n)
|
||||||
{
|
{
|
||||||
var key = apool.getAttribKey(n);
|
var key = apool.getAttribKey(n);
|
||||||
if (key)
|
if (key)
|
||||||
{
|
{
|
||||||
var value = apool.getAttribValue(n);
|
var value = apool.getAttribValue(n);
|
||||||
|
@ -109,11 +109,11 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
||||||
key: key,
|
key: key,
|
||||||
value: value
|
value: value
|
||||||
}, " ", " ", "");
|
}, " ", " ", "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if(isLineAttribMarker) classes += ' ' + lineAttributeMarker;
|
if(isLineAttribMarker) classes += ' ' + lineAttributeMarker;
|
||||||
return classes.substring(1);
|
return classes.substring(1);
|
||||||
}
|
}
|
||||||
|
@ -146,12 +146,12 @@ linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFun
|
||||||
|
|
||||||
return function(txt, cls)
|
return function(txt, cls)
|
||||||
{
|
{
|
||||||
|
|
||||||
var disableAuthColorForThisLine = hooks.callAll("disableAuthorColorsForThisLine", {
|
var disableAuthColorForThisLine = hooks.callAll("disableAuthorColorsForThisLine", {
|
||||||
linestylefilter: linestylefilter,
|
linestylefilter: linestylefilter,
|
||||||
text: txt,
|
text: txt,
|
||||||
"class": cls
|
"class": cls
|
||||||
}, " ", " ", "");
|
}, " ", " ", "");
|
||||||
var disableAuthors = (disableAuthColorForThisLine==null||disableAuthColorForThisLine.length==0)?false:disableAuthColorForThisLine[0];
|
var disableAuthors = (disableAuthColorForThisLine==null||disableAuthColorForThisLine.length==0)?false:disableAuthColorForThisLine[0];
|
||||||
while (txt.length > 0)
|
while (txt.length > 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -60,10 +60,10 @@ function createCookie(name, value, days, path)
|
||||||
var expires = "; expires=" + date.toGMTString();
|
var expires = "; expires=" + date.toGMTString();
|
||||||
}
|
}
|
||||||
else var expires = "";
|
else var expires = "";
|
||||||
|
|
||||||
if(!path)
|
if(!path)
|
||||||
path = "/";
|
path = "/";
|
||||||
|
|
||||||
document.cookie = name + "=" + value + expires + "; path=" + path;
|
document.cookie = name + "=" + value + expires + "; path=" + path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +117,7 @@ function getParams()
|
||||||
if(showControls)
|
if(showControls)
|
||||||
{
|
{
|
||||||
if(showControls == "false")
|
if(showControls == "false")
|
||||||
{
|
{
|
||||||
$('#editbar').hide();
|
$('#editbar').hide();
|
||||||
$('#editorcontainer').css({"top":"0px"});
|
$('#editorcontainer').css({"top":"0px"});
|
||||||
}
|
}
|
||||||
|
@ -220,7 +220,7 @@ function handshake()
|
||||||
token = "t." + randomString();
|
token = "t." + randomString();
|
||||||
createCookie("token", token, 60);
|
createCookie("token", token, 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
var sessionID = readCookie("sessionID");
|
var sessionID = readCookie("sessionID");
|
||||||
var password = readCookie("password");
|
var password = readCookie("password");
|
||||||
|
|
||||||
|
@ -233,14 +233,14 @@ function handshake()
|
||||||
"token": token,
|
"token": token,
|
||||||
"protocolVersion": 2
|
"protocolVersion": 2
|
||||||
};
|
};
|
||||||
|
|
||||||
//this is a reconnect, lets tell the server our revisionnumber
|
//this is a reconnect, lets tell the server our revisionnumber
|
||||||
if(isReconnect == true)
|
if(isReconnect == true)
|
||||||
{
|
{
|
||||||
msg.client_rev=pad.collabClient.getCurrentRevisionNumber();
|
msg.client_rev=pad.collabClient.getCurrentRevisionNumber();
|
||||||
msg.reconnect=true;
|
msg.reconnect=true;
|
||||||
}
|
}
|
||||||
|
|
||||||
socket.json.send(msg);
|
socket.json.send(msg);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ function handshake()
|
||||||
socket.once('connect', function () {
|
socket.once('connect', function () {
|
||||||
sendClientReady(false);
|
sendClientReady(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('reconnect', function () {
|
socket.on('reconnect', function () {
|
||||||
//reconnect is before the timeout, lets stop the timeout
|
//reconnect is before the timeout, lets stop the timeout
|
||||||
if(disconnectTimeout)
|
if(disconnectTimeout)
|
||||||
|
@ -260,7 +260,7 @@ function handshake()
|
||||||
pad.collabClient.setChannelState("CONNECTED");
|
pad.collabClient.setChannelState("CONNECTED");
|
||||||
sendClientReady(true);
|
sendClientReady(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
socket.on('disconnect', function (reason) {
|
socket.on('disconnect', function (reason) {
|
||||||
if(reason == "booted"){
|
if(reason == "booted"){
|
||||||
pad.collabClient.setChannelState("DISCONNECTED");
|
pad.collabClient.setChannelState("DISCONNECTED");
|
||||||
|
@ -269,9 +269,9 @@ function handshake()
|
||||||
{
|
{
|
||||||
pad.collabClient.setChannelState("DISCONNECTED", "reconnect_timeout");
|
pad.collabClient.setChannelState("DISCONNECTED", "reconnect_timeout");
|
||||||
}
|
}
|
||||||
|
|
||||||
pad.collabClient.setChannelState("RECONNECTING");
|
pad.collabClient.setChannelState("RECONNECTING");
|
||||||
|
|
||||||
disconnectTimeout = setTimeout(disconnectEvent, 10000);
|
disconnectTimeout = setTimeout(disconnectEvent, 10000);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -301,7 +301,7 @@ function handshake()
|
||||||
"<button type='button' onclick=\"" + padutils.escapeHtml('require('+JSON.stringify(module.id)+").savePassword()") + "\">ok</button>");
|
"<button type='button' onclick=\"" + padutils.escapeHtml('require('+JSON.stringify(module.id)+").savePassword()") + "\">ok</button>");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//if we haven't recieved the clientVars yet, then this message should it be
|
//if we haven't recieved the clientVars yet, then this message should it be
|
||||||
else if (!receivedClientVars)
|
else if (!receivedClientVars)
|
||||||
{
|
{
|
||||||
|
@ -314,7 +314,7 @@ function handshake()
|
||||||
clientVars = obj.data;
|
clientVars = obj.data;
|
||||||
clientVars.userAgent = "Anonymous";
|
clientVars.userAgent = "Anonymous";
|
||||||
clientVars.collab_client_vars.clientAgent = "Anonymous";
|
clientVars.collab_client_vars.clientAgent = "Anonymous";
|
||||||
|
|
||||||
//initalize the pad
|
//initalize the pad
|
||||||
pad._afterHandshake();
|
pad._afterHandshake();
|
||||||
initalized = true;
|
initalized = true;
|
||||||
|
@ -336,7 +336,7 @@ function handshake()
|
||||||
{
|
{
|
||||||
pad.changeViewOption('noColors', true);
|
pad.changeViewOption('noColors', true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (settings.rtlIsTrue == true)
|
if (settings.rtlIsTrue == true)
|
||||||
{
|
{
|
||||||
pad.changeViewOption('rtl', true);
|
pad.changeViewOption('rtl', true);
|
||||||
|
@ -457,7 +457,7 @@ var pad = {
|
||||||
_afterHandshake: function()
|
_afterHandshake: function()
|
||||||
{
|
{
|
||||||
pad.clientTimeOffset = new Date().getTime() - clientVars.serverTimestamp;
|
pad.clientTimeOffset = new Date().getTime() - clientVars.serverTimestamp;
|
||||||
|
|
||||||
//initialize the chat
|
//initialize the chat
|
||||||
chat.init(this);
|
chat.init(this);
|
||||||
pad.initTime = +(new Date());
|
pad.initTime = +(new Date());
|
||||||
|
@ -481,7 +481,7 @@ var pad = {
|
||||||
|
|
||||||
// order of inits is important here:
|
// order of inits is important here:
|
||||||
padcookie.init(clientVars.cookiePrefsToSet, this);
|
padcookie.init(clientVars.cookiePrefsToSet, this);
|
||||||
|
|
||||||
$("#widthprefcheck").click(pad.toggleWidthPref);
|
$("#widthprefcheck").click(pad.toggleWidthPref);
|
||||||
// $("#sidebarcheck").click(pad.togglewSidebar);
|
// $("#sidebarcheck").click(pad.togglewSidebar);
|
||||||
|
|
||||||
|
@ -749,20 +749,20 @@ var pad = {
|
||||||
pad.diagnosticInfo.disconnectedMessage = message;
|
pad.diagnosticInfo.disconnectedMessage = message;
|
||||||
pad.diagnosticInfo.padId = pad.getPadId();
|
pad.diagnosticInfo.padId = pad.getPadId();
|
||||||
pad.diagnosticInfo.socket = {};
|
pad.diagnosticInfo.socket = {};
|
||||||
|
|
||||||
//we filter non objects from the socket object and put them in the diagnosticInfo
|
//we filter non objects from the socket object and put them in the diagnosticInfo
|
||||||
//this ensures we have no cyclic data - this allows us to stringify the data
|
//this ensures we have no cyclic data - this allows us to stringify the data
|
||||||
for(var i in socket.socket)
|
for(var i in socket.socket)
|
||||||
{
|
{
|
||||||
var value = socket.socket[i];
|
var value = socket.socket[i];
|
||||||
var type = typeof value;
|
var type = typeof value;
|
||||||
|
|
||||||
if(type == "string" || type == "number")
|
if(type == "string" || type == "number")
|
||||||
{
|
{
|
||||||
pad.diagnosticInfo.socket[i] = value;
|
pad.diagnosticInfo.socket[i] = value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pad.asyncSendDiagnosticInfo();
|
pad.asyncSendDiagnosticInfo();
|
||||||
if (typeof window.ajlog == "string")
|
if (typeof window.ajlog == "string")
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -43,7 +43,7 @@ var padconnectionstatus = (function()
|
||||||
status = {
|
status = {
|
||||||
what: 'connected'
|
what: 'connected'
|
||||||
};
|
};
|
||||||
|
|
||||||
padmodals.showModal('connected');
|
padmodals.showModal('connected');
|
||||||
padmodals.hideOverlay(500);
|
padmodals.hideOverlay(500);
|
||||||
},
|
},
|
||||||
|
@ -52,7 +52,7 @@ var padconnectionstatus = (function()
|
||||||
status = {
|
status = {
|
||||||
what: 'reconnecting'
|
what: 'reconnecting'
|
||||||
};
|
};
|
||||||
|
|
||||||
padmodals.showModal('reconnecting');
|
padmodals.showModal('reconnecting');
|
||||||
padmodals.showOverlay(500);
|
padmodals.showOverlay(500);
|
||||||
},
|
},
|
||||||
|
@ -60,18 +60,18 @@ var padconnectionstatus = (function()
|
||||||
{
|
{
|
||||||
if(status.what == "disconnected")
|
if(status.what == "disconnected")
|
||||||
return;
|
return;
|
||||||
|
|
||||||
status = {
|
status = {
|
||||||
what: 'disconnected',
|
what: 'disconnected',
|
||||||
why: msg
|
why: msg
|
||||||
};
|
};
|
||||||
|
|
||||||
var k = String(msg).toLowerCase(); // known reason why
|
var k = String(msg).toLowerCase(); // known reason why
|
||||||
if (!(k == 'userdup' || k == 'deleted' || k == 'looping' || k == 'slowcommit' || k == 'initsocketfail' || k == 'unauth'))
|
if (!(k == 'userdup' || k == 'deleted' || k == 'looping' || k == 'slowcommit' || k == 'initsocketfail' || k == 'unauth'))
|
||||||
{
|
{
|
||||||
k = 'disconnected';
|
k = 'disconnected';
|
||||||
}
|
}
|
||||||
|
|
||||||
padmodals.showModal(k);
|
padmodals.showModal(k);
|
||||||
padmodals.showOverlay(500);
|
padmodals.showOverlay(500);
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -117,7 +117,7 @@ var padeditbar = (function()
|
||||||
$("#editbar").addClass('disabledtoolbar').removeClass("enabledtoolbar");
|
$("#editbar").addClass('disabledtoolbar').removeClass("enabledtoolbar");
|
||||||
},
|
},
|
||||||
toolbarClick: function(cmd)
|
toolbarClick: function(cmd)
|
||||||
{
|
{
|
||||||
if (self.isEnabled())
|
if (self.isEnabled())
|
||||||
{
|
{
|
||||||
if(cmd == "showusers")
|
if(cmd == "showusers")
|
||||||
|
@ -189,7 +189,7 @@ var padeditbar = (function()
|
||||||
toggleDropDown: function(moduleName, cb)
|
toggleDropDown: function(moduleName, cb)
|
||||||
{
|
{
|
||||||
var modules = ["settings", "connectivity", "importexport", "embed", "users"];
|
var modules = ["settings", "connectivity", "importexport", "embed", "users"];
|
||||||
|
|
||||||
// hide all modules and remove highlighting of all buttons
|
// hide all modules and remove highlighting of all buttons
|
||||||
if(moduleName == "none")
|
if(moduleName == "none")
|
||||||
{
|
{
|
||||||
|
@ -199,9 +199,9 @@ var padeditbar = (function()
|
||||||
//skip the userlist
|
//skip the userlist
|
||||||
if(modules[i] == "users")
|
if(modules[i] == "users")
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
var module = $("#" + modules[i]);
|
var module = $("#" + modules[i]);
|
||||||
|
|
||||||
if(module.css('display') != "none")
|
if(module.css('display') != "none")
|
||||||
{
|
{
|
||||||
$("#" + modules[i] + "link").removeClass("selected");
|
$("#" + modules[i] + "link").removeClass("selected");
|
||||||
|
@ -211,14 +211,14 @@ var padeditbar = (function()
|
||||||
}
|
}
|
||||||
if(!returned && cb) return cb();
|
if(!returned && cb) return cb();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// hide all modules that are not selected and remove highlighting
|
// hide all modules that are not selected and remove highlighting
|
||||||
// respectively add highlighting to the corresponding button
|
// respectively add highlighting to the corresponding button
|
||||||
for(var i=0;i<modules.length;i++)
|
for(var i=0;i<modules.length;i++)
|
||||||
{
|
{
|
||||||
var module = $("#" + modules[i]);
|
var module = $("#" + modules[i]);
|
||||||
|
|
||||||
if(module.css('display') != "none")
|
if(module.css('display') != "none")
|
||||||
{
|
{
|
||||||
$("#" + modules[i] + "link").removeClass("selected");
|
$("#" + modules[i] + "link").removeClass("selected");
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -71,7 +71,7 @@ var padimpexp = (function()
|
||||||
$('#importmessagefail').fadeOut("fast");
|
$('#importmessagefail').fadeOut("fast");
|
||||||
var ret = window.confirm("Importing a file will overwrite the current text of the pad." + " Are you sure you want to proceed?");
|
var ret = window.confirm("Importing a file will overwrite the current text of the pad." + " Are you sure you want to proceed?");
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
hidePanelCall = paddocbar.hideLaterIfNoOtherInteraction();
|
hidePanelCall = paddocbar.hideLaterIfNoOtherInteraction();
|
||||||
currentImportTimer = window.setTimeout(function()
|
currentImportTimer = window.setTimeout(function()
|
||||||
{
|
{
|
||||||
|
@ -128,13 +128,13 @@ var padimpexp = (function()
|
||||||
function importErrorMessage(status)
|
function importErrorMessage(status)
|
||||||
{
|
{
|
||||||
var msg="";
|
var msg="";
|
||||||
|
|
||||||
if(status === "convertFailed"){
|
if(status === "convertFailed"){
|
||||||
msg = "We were not able to import this file. Please use a different document format or copy paste manually";
|
msg = "We were not able to import this file. Please use a different document format or copy paste manually";
|
||||||
} else if(status === "uploadFailed"){
|
} else if(status === "uploadFailed"){
|
||||||
msg = "The upload failed, please try again";
|
msg = "The upload failed, please try again";
|
||||||
}
|
}
|
||||||
|
|
||||||
function showError(fade)
|
function showError(fade)
|
||||||
{
|
{
|
||||||
$('#importmessagefail').html('<strong style="color: red">Import failed:</strong> ' + (msg || 'Please copy paste'))[(fade ? "fadeIn" : "show")]();
|
$('#importmessagefail').html('<strong style="color: red">Import failed:</strong> ' + (msg || 'Please copy paste'))[(fade ? "fadeIn" : "show")]();
|
||||||
|
@ -218,7 +218,7 @@ var padimpexp = (function()
|
||||||
$("#exporthtmla").attr("href", pad_root_path + "/export/html");
|
$("#exporthtmla").attr("href", pad_root_path + "/export/html");
|
||||||
$("#exportplaina").attr("href", pad_root_path + "/export/txt");
|
$("#exportplaina").attr("href", pad_root_path + "/export/txt");
|
||||||
$("#exportdokuwikia").attr("href", pad_root_path + "/export/dokuwiki");
|
$("#exportdokuwikia").attr("href", pad_root_path + "/export/dokuwiki");
|
||||||
|
|
||||||
//hide stuff thats not avaible if abiword is disabled
|
//hide stuff thats not avaible if abiword is disabled
|
||||||
if(clientVars.abiwordAvailable == "no")
|
if(clientVars.abiwordAvailable == "no")
|
||||||
{
|
{
|
||||||
|
@ -231,24 +231,24 @@ var padimpexp = (function()
|
||||||
else if(clientVars.abiwordAvailable == "withoutPDF")
|
else if(clientVars.abiwordAvailable == "withoutPDF")
|
||||||
{
|
{
|
||||||
$("#exportpdfa").remove();
|
$("#exportpdfa").remove();
|
||||||
|
|
||||||
$("#exportworda").attr("href", pad_root_path + "/export/doc");
|
$("#exportworda").attr("href", pad_root_path + "/export/doc");
|
||||||
$("#exportopena").attr("href", pad_root_path + "/export/odt");
|
$("#exportopena").attr("href", pad_root_path + "/export/odt");
|
||||||
|
|
||||||
$("#importexport").css({"height":"142px"});
|
$("#importexport").css({"height":"142px"});
|
||||||
$("#importexportline").css({"height":"142px"});
|
$("#importexportline").css({"height":"142px"});
|
||||||
|
|
||||||
$("#importform").attr('action', pad_root_url + "/import");
|
$("#importform").attr('action', pad_root_url + "/import");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$("#exportworda").attr("href", pad_root_path + "/export/doc");
|
$("#exportworda").attr("href", pad_root_path + "/export/doc");
|
||||||
$("#exportpdfa").attr("href", pad_root_path + "/export/pdf");
|
$("#exportpdfa").attr("href", pad_root_path + "/export/pdf");
|
||||||
$("#exportopena").attr("href", pad_root_path + "/export/odt");
|
$("#exportopena").attr("href", pad_root_path + "/export/odt");
|
||||||
|
|
||||||
$("#importform").attr('action', pad_root_path + "/import");
|
$("#importform").attr('action', pad_root_path + "/import");
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#impexp-close").click(function()
|
$("#impexp-close").click(function()
|
||||||
{
|
{
|
||||||
paddocbar.setShownPanel(null);
|
paddocbar.setShownPanel(null);
|
||||||
|
@ -265,7 +265,7 @@ var padimpexp = (function()
|
||||||
{
|
{
|
||||||
importFailed(status);
|
importFailed(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
importDone();
|
importDone();
|
||||||
},
|
},
|
||||||
disable: function()
|
disable: function()
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -19,7 +19,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var padutils = require('./pad_utils').padutils;
|
var padutils = require('./pad_utils').padutils;
|
||||||
var padeditbar = require('./pad_editbar').padeditbar;
|
var padeditbar = require('./pad_editbar').padeditbar;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -516,7 +516,7 @@ var paduserlist = (function()
|
||||||
{
|
{
|
||||||
info.colorId = clientVars.colorPalette[info.colorId];
|
info.colorId = clientVars.colorPalette[info.colorId];
|
||||||
}
|
}
|
||||||
|
|
||||||
myUserInfo = $.extend(
|
myUserInfo = $.extend(
|
||||||
{}, info);
|
{}, info);
|
||||||
|
|
||||||
|
@ -725,9 +725,9 @@ var paduserlist = (function()
|
||||||
{
|
{
|
||||||
$("#myswatchbox").addClass('myswatchboxhoverable').removeClass('myswatchboxunhoverable');
|
$("#myswatchbox").addClass('myswatchboxhoverable').removeClass('myswatchboxunhoverable');
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#myswatch").css({'background-color': myUserInfo.colorId});
|
$("#myswatch").css({'background-color': myUserInfo.colorId});
|
||||||
|
|
||||||
if ($.browser.msie && parseInt($.browser.version) <= 8) {
|
if ($.browser.msie && parseInt($.browser.version) <= 8) {
|
||||||
$("#usericon a").css({'box-shadow': 'inset 0 0 30px ' + myUserInfo.colorId,'background-color': myUserInfo.colorId});
|
$("#usericon a").css({'box-shadow': 'inset 0 0 30px ' + myUserInfo.colorId,'background-color': myUserInfo.colorId});
|
||||||
}
|
}
|
||||||
|
@ -749,7 +749,7 @@ function getColorPickerSwatchIndex(jnode)
|
||||||
function closeColorPicker(accept)
|
function closeColorPicker(accept)
|
||||||
{
|
{
|
||||||
if (accept)
|
if (accept)
|
||||||
{
|
{
|
||||||
var newColor = $("#mycolorpickerpreview").css("background-color");
|
var newColor = $("#mycolorpickerpreview").css("background-color");
|
||||||
var parts = newColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
|
var parts = newColor.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
|
||||||
// parts now should be ["rgb(0, 70, 255", "0", "70", "255"]
|
// parts now should be ["rgb(0, 70, 255", "0", "70", "255"]
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -518,9 +518,9 @@ function setupGlobalExceptionHandler() {
|
||||||
var errObj = {errorInfo: JSON.stringify({errorId: errorId, msg: msg, url: url, linenumber: linenumber, userAgent: navigator.userAgent})};
|
var errObj = {errorInfo: JSON.stringify({errorId: errorId, msg: msg, url: url, linenumber: linenumber, userAgent: navigator.userAgent})};
|
||||||
var loc = document.location;
|
var loc = document.location;
|
||||||
var url = loc.protocol + "//" + loc.hostname + ":" + loc.port + "/" + loc.pathname.substr(1, loc.pathname.indexOf("/p/")) + "jserror";
|
var url = loc.protocol + "//" + loc.hostname + ":" + loc.port + "/" + loc.pathname.substr(1, loc.pathname.indexOf("/p/")) + "jserror";
|
||||||
|
|
||||||
$.post(url, errObj);
|
$.post(url, errObj);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
window.onerror = globalExceptionHandler;
|
window.onerror = globalExceptionHandler;
|
||||||
|
|
|
@ -43,7 +43,7 @@ exports.uninstall = function(plugin_name, cb) {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function () {
|
function () {
|
||||||
hooks.aCallAll("restartServer", {}, function () {});
|
hooks.aCallAll("restartServer", {}, function () {});
|
||||||
},
|
},
|
||||||
cb
|
cb
|
||||||
);
|
);
|
||||||
|
@ -61,7 +61,7 @@ exports.install = function(plugin_name, cb) {
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
function () {
|
function () {
|
||||||
hooks.aCallAll("restartServer", {}, function () {});
|
hooks.aCallAll("restartServer", {}, function () {});
|
||||||
},
|
},
|
||||||
cb
|
cb
|
||||||
);
|
);
|
||||||
|
|
|
@ -105,11 +105,11 @@ exports.getPackages = function (cb) {
|
||||||
delete packages[name].dependencies;
|
delete packages[name].dependencies;
|
||||||
delete packages[name].parent;
|
delete packages[name].parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deps[name].dependencies !== undefined) flatten(deps[name].dependencies);
|
if (deps[name].dependencies !== undefined) flatten(deps[name].dependencies);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var tmp = {};
|
var tmp = {};
|
||||||
tmp[data.name] = data;
|
tmp[data.name] = data;
|
||||||
flatten(tmp);
|
flatten(tmp);
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
@ -155,7 +155,7 @@ function SkipList()
|
||||||
var widthLoc = point.widthSkips[0] + point.nodes[0].downSkipWidths[0];
|
var widthLoc = point.widthSkips[0] + point.nodes[0].downSkipWidths[0];
|
||||||
var newWidth = _entryWidth(entry);
|
var newWidth = _entryWidth(entry);
|
||||||
p.mark("loop1");
|
p.mark("loop1");
|
||||||
|
|
||||||
// The new node will have at least level 1
|
// The new node will have at least level 1
|
||||||
// With a proability of 0.01^(n-1) the nodes level will be >= n
|
// With a proability of 0.01^(n-1) the nodes level will be >= n
|
||||||
while (newNode.levels == 0 || Math.random() < 0.01)
|
while (newNode.levels == 0 || Math.random() < 0.01)
|
||||||
|
|
|
@ -60,7 +60,7 @@ function init() {
|
||||||
var url = loc.protocol + "//" + loc.hostname + ":" + port + "/";
|
var url = loc.protocol + "//" + loc.hostname + ":" + port + "/";
|
||||||
//find out in which subfolder we are
|
//find out in which subfolder we are
|
||||||
var resource = exports.baseURL.substring(1) + 'socket.io';
|
var resource = exports.baseURL.substring(1) + 'socket.io';
|
||||||
|
|
||||||
//build up the socket io connection
|
//build up the socket io connection
|
||||||
socket = io.connect(url, {resource: resource});
|
socket = io.connect(url, {resource: resource});
|
||||||
|
|
||||||
|
@ -128,13 +128,13 @@ function sendSocketMsg(type, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
var fireWhenAllScriptsAreLoaded = [];
|
var fireWhenAllScriptsAreLoaded = [];
|
||||||
|
|
||||||
var BroadcastSlider, changesetLoader;
|
var BroadcastSlider, changesetLoader;
|
||||||
function handleClientVars(message)
|
function handleClientVars(message)
|
||||||
{
|
{
|
||||||
//save the client Vars
|
//save the client Vars
|
||||||
clientVars = message.data;
|
clientVars = message.data;
|
||||||
|
|
||||||
//load all script that doesn't work without the clientVars
|
//load all script that doesn't work without the clientVars
|
||||||
BroadcastSlider = require('./broadcast_slider').loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded);
|
BroadcastSlider = require('./broadcast_slider').loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded);
|
||||||
require('./broadcast_revisions').loadBroadcastRevisionsJS();
|
require('./broadcast_revisions').loadBroadcastRevisionsJS();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
* This code is mostly from the old Etherpad. Please help us to comment this code.
|
||||||
* This helps other people to understand this code better and helps them to improve it.
|
* This helps other people to understand this code better and helps them to improve it.
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
.test_group table {
|
.test_group table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
#apikeyDIV {
|
#apikeyDIV {
|
||||||
width: 100%
|
width: 100%
|
||||||
}
|
}
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
|
|
||||||
callFunction(name, results_node, params);
|
callFunction(name, results_node, params);
|
||||||
});
|
});
|
||||||
|
|
||||||
var template = $('#template')
|
var template = $('#template')
|
||||||
$('.define').each(function() {
|
$('.define').each(function() {
|
||||||
var functionName = parseName($(this).text());
|
var functionName = parseName($(this).text());
|
||||||
|
@ -95,7 +95,7 @@
|
||||||
{
|
{
|
||||||
// parse out the parameters by looking for parens
|
// parse out the parameters by looking for parens
|
||||||
var parens = str.substring(str.indexOf("("));
|
var parens = str.substring(str.indexOf("("));
|
||||||
|
|
||||||
// return empty array if there are no paremeters
|
// return empty array if there are no paremeters
|
||||||
if(parens.length < 3)
|
if(parens.length < 3)
|
||||||
{
|
{
|
||||||
|
@ -109,10 +109,10 @@
|
||||||
return parens.split(',');
|
return parens.split(',');
|
||||||
}
|
}
|
||||||
|
|
||||||
function callFunction(memberName, results_node, params)
|
function callFunction(memberName, results_node, params)
|
||||||
{
|
{
|
||||||
$('#result').text('Calling ' + memberName + "()...");
|
$('#result').text('Calling ' + memberName + "()...");
|
||||||
|
|
||||||
params["apikey"]=$("#apikey").val();
|
params["apikey"]=$("#apikey").val();
|
||||||
$.ajax({
|
$.ajax({
|
||||||
type: "GET",
|
type: "GET",
|
||||||
|
@ -138,7 +138,7 @@
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<div class="results"></div>
|
<div class="results"></div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div class="define">createGroup()</div>
|
<div class="define">createGroup()</div>
|
||||||
<div class="define">deleteGroup(groupID)</div>
|
<div class="define">deleteGroup(groupID)</div>
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Etherpad Lite Admin Dashboard</title>
|
<title>Etherpad Lite Admin Dashboard</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
||||||
<link rel="stylesheet" href="../static/css/admin.css">
|
<link rel="stylesheet" href="../static/css/admin.css">
|
||||||
<script src="../static/js/jquery.js"></script>
|
<script src="../static/js/jquery.js"></script>
|
||||||
<script src="../socket.io/socket.io.js"></script>
|
<script src="../socket.io/socket.io.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<h1>Etherpad Lite Admin Dashboard</h1>
|
<h1>Etherpad Lite Admin Dashboard</h1>
|
||||||
<div>
|
<div>
|
||||||
<a href="../admin/plugins">Install and Uninstall plugins</a>
|
<a href="../admin/plugins">Install and Uninstall plugins</a>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<a href="../admin/settings">Modify Server and Plugin Settings</a>
|
<a href="../admin/settings">Modify Server and Plugin Settings</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,90 +1,90 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Plugin manager</title>
|
<title>Plugin manager</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
||||||
<link rel="stylesheet" href="../static/css/admin.css">
|
<link rel="stylesheet" href="../static/css/admin.css">
|
||||||
<script src="../static/js/jquery.js"></script>
|
<script src="../static/js/jquery.js"></script>
|
||||||
<script src="../socket.io/socket.io.js"></script>
|
<script src="../socket.io/socket.io.js"></script>
|
||||||
<script src="../static/js/admin/plugins.js"></script>
|
<script src="../static/js/admin/plugins.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
|
|
||||||
<% if (errors.length) { %>
|
<% if (errors.length) { %>
|
||||||
<div class="errors">
|
<div class="errors">
|
||||||
<% errors.forEach(function (item) { %>
|
<% errors.forEach(function (item) { %>
|
||||||
<div class="error"><%= item.toString() %></div>
|
<div class="error"><%= item.toString() %></div>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
|
|
||||||
<h1>Etherpad Lite</h1>
|
<h1>Etherpad Lite</h1>
|
||||||
|
|
||||||
<a href="plugins/info">Technical information on installed plugins</a>
|
<a href="plugins/info">Technical information on installed plugins</a>
|
||||||
|
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
<h2>Installed plugins</h2>
|
<h2>Installed plugins</h2>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="template">
|
<tbody class="template">
|
||||||
<tr id="installed-plugin-template">
|
<tr id="installed-plugin-template">
|
||||||
<td class="name"></td>
|
<td class="name"></td>
|
||||||
<td class="description"></td>
|
<td class="description"></td>
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
<input type="button" value="Uninstall" class="do-uninstall">
|
<input type="button" value="Uninstall" class="do-uninstall">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tbody id="installed-plugins">
|
<tbody id="installed-plugins">
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div class="paged listing search-results">
|
<div class="paged listing search-results">
|
||||||
<div class="separator"></div>
|
<div class="separator"></div>
|
||||||
<h2>Search for plugins to install</h2>
|
<h2>Search for plugins to install</h2>
|
||||||
<form>
|
<form>
|
||||||
<input type="text" name="search" placeholder="Search term" id="search-query">
|
<input type="text" name="search" placeholder="Search term" id="search-query">
|
||||||
<input type="button" value="Search" id="do-search">
|
<input type="button" value="Search" id="do-search">
|
||||||
</form>
|
</form>
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Name</th>
|
<th>Name</th>
|
||||||
<th>Description</th>
|
<th>Description</th>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="template">
|
<tbody class="template">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name"></td>
|
<td class="name"></td>
|
||||||
<td class="description"></td>
|
<td class="description"></td>
|
||||||
<td class="actions">
|
<td class="actions">
|
||||||
<input type="button" value="Install" class="do-install">
|
<input type="button" value="Install" class="do-install">
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
<tbody class="results">
|
<tbody class="results">
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
<input type="button" value="<<" class="do-prev-page">
|
<input type="button" value="<<" class="do-prev-page">
|
||||||
<span class="offset"></span>..<span class="limit"></span> of <span class="total"></span>.
|
<span class="offset"></span>..<span class="limit"></span> of <span class="total"></span>.
|
||||||
<input type="button" value=">>" class="do-next-page">
|
<input type="button" value=">>" class="do-next-page">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="progress" class="dialog">
|
<div id="progress" class="dialog">
|
||||||
<h1 class="title">
|
<h1 class="title">
|
||||||
Please wait: <span class="message"></span>
|
Please wait: <span class="message"></span>
|
||||||
<input type="button" class="close" value="Close">
|
<input type="button" class="close" value="Close">
|
||||||
</h1>
|
</h1>
|
||||||
<div class="history"></div>
|
<div class="history"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,34 +1,34 @@
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Settings manager</title>
|
<title>Settings manager</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
||||||
<link rel="stylesheet" href="../static/css/admin.css">
|
<link rel="stylesheet" href="../static/css/admin.css">
|
||||||
<script src="../static/js/jquery.js"></script>
|
<script src="../static/js/jquery.js"></script>
|
||||||
<script src="../socket.io/socket.io.js"></script>
|
<script src="../socket.io/socket.io.js"></script>
|
||||||
<script src="../static/js/admin/minify.json.js"></script>
|
<script src="../static/js/admin/minify.json.js"></script>
|
||||||
<script src="../static/js/admin/settings.js"></script>
|
<script src="../static/js/admin/settings.js"></script>
|
||||||
<script src="../static/js/admin/jquery.autosize.js"></script>
|
<script src="../static/js/admin/jquery.autosize.js"></script>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
|
|
||||||
<% if (errors.length) { %>
|
<% if (errors.length) { %>
|
||||||
<div class="errors">
|
<div class="errors">
|
||||||
<% errors.forEach(function (item) { %>
|
<% errors.forEach(function (item) { %>
|
||||||
<div class="error"><%= item.toString() %></div>
|
<div class="error"><%= item.toString() %></div>
|
||||||
<% }) %>
|
<% }) %>
|
||||||
</div>
|
</div>
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
|
|
||||||
<h1>Etherpad Lite Settings</h1>
|
<h1>Etherpad Lite Settings</h1>
|
||||||
<a href='https://github.com/Pita/etherpad-lite/wiki/Example-Production-Settings.JSON'>Example production settings template</a>
|
<a href='https://github.com/Pita/etherpad-lite/wiki/Example-Production-Settings.JSON'>Example production settings template</a>
|
||||||
<a href='https://github.com/Pita/etherpad-lite/wiki/Example-Development-Settings.JSON'>Example development settings template</a>
|
<a href='https://github.com/Pita/etherpad-lite/wiki/Example-Development-Settings.JSON'>Example development settings template</a>
|
||||||
<textarea class="settings"></textarea>
|
<textarea class="settings"></textarea>
|
||||||
<input type="button" class="settingsButton" id="saveSettings" value="Save Settings">
|
<input type="button" class="settingsButton" id="saveSettings" value="Save Settings">
|
||||||
<input type="button" class="settingsButton" id="restartEtherpad" value="Restart Etherpad">
|
<input type="button" class="settingsButton" id="restartEtherpad" value="Restart Etherpad">
|
||||||
<div id="response"></div>
|
<div id="response"></div>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -29,7 +29,7 @@
|
||||||
*/
|
*/
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="<%=settings.favicon%>">
|
<link rel="shortcut icon" href="<%=settings.favicon%>">
|
||||||
|
@ -111,7 +111,7 @@
|
||||||
input[type="text"] {
|
input[type="text"] {
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
padding: 0 45px 0 10px;
|
padding: 0 45px 0 10px;
|
||||||
*padding: 0; /* IE7 hack */
|
*padding: 0; /* IE7 hack */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
@ -137,53 +137,53 @@
|
||||||
margin-top: 0;
|
margin-top: 0;
|
||||||
}
|
}
|
||||||
#inner {
|
#inner {
|
||||||
width: 95%;
|
width: 95%;
|
||||||
}
|
}
|
||||||
#label {
|
#label {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
<link href="static/custom/index.css" rel="stylesheet">
|
<link href="static/custom/index.css" rel="stylesheet">
|
||||||
|
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<div id="inner">
|
<div id="inner">
|
||||||
<div id="button" onclick="go2Random()" class="translate">New Pad</div>
|
<div id="button" onclick="go2Random()" class="translate">New Pad</div>
|
||||||
<div id="label" class="translate">or create/open a Pad with the name</div>
|
<div id="label" class="translate">or create/open a Pad with the name</div>
|
||||||
<form action="#" onsubmit="go2Name();return false;">
|
<form action="#" onsubmit="go2Name();return false;">
|
||||||
<input type="text" id="padname" autofocus x-webkit-speech>
|
<input type="text" id="padname" autofocus x-webkit-speech>
|
||||||
<button type="submit">OK</button>
|
<button type="submit">OK</button>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="static/custom/index.js"></script>
|
<script src="static/custom/index.js"></script>
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
function go2Name()
|
function go2Name()
|
||||||
{
|
{
|
||||||
var padname = document.getElementById("padname").value;
|
var padname = document.getElementById("padname").value;
|
||||||
padname.length > 0 ? window.location = "p/" + padname : alert("Please enter a name")
|
padname.length > 0 ? window.location = "p/" + padname : alert("Please enter a name")
|
||||||
}
|
}
|
||||||
|
|
||||||
function go2Random()
|
function go2Random()
|
||||||
{
|
{
|
||||||
window.location = "p/" + randomPadName();
|
window.location = "p/" + randomPadName();
|
||||||
}
|
}
|
||||||
|
|
||||||
function randomPadName()
|
function randomPadName()
|
||||||
{
|
{
|
||||||
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
var chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
|
||||||
var string_length = 10;
|
var string_length = 10;
|
||||||
var randomstring = '';
|
var randomstring = '';
|
||||||
for (var i = 0; i < string_length; i++)
|
for (var i = 0; i < string_length; i++)
|
||||||
{
|
{
|
||||||
var rnum = Math.floor(Math.random() * chars.length);
|
var rnum = Math.floor(Math.random() * chars.length);
|
||||||
randomstring += chars.substring(rnum, rnum + 1);
|
randomstring += chars.substring(rnum, rnum + 1);
|
||||||
}
|
}
|
||||||
return randomstring;
|
return randomstring;
|
||||||
}
|
}
|
||||||
|
|
||||||
// start the custom js
|
// start the custom js
|
||||||
if (typeof customStart == "function") customStart();
|
if (typeof customStart == "function") customStart();
|
||||||
</script>
|
</script>
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue