mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-24 17:36:14 -04:00
Merge branch 'develop' of github.com:Pita/etherpad-lite into feature/frontend-tests
This commit is contained in:
commit
f59b643aa6
25 changed files with 378 additions and 83 deletions
|
@ -141,22 +141,6 @@ exports.getAuthor = function (author, callback)
|
|||
db.get("globalAuthor:" + author, callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Author Name of the author
|
||||
* @param {String} author The id of the author
|
||||
* @param {Function} callback callback(err, name)
|
||||
*/
|
||||
|
||||
exports.getAuthorName = function (authorID, callback)
|
||||
{
|
||||
db.getSub("globalAuthor:" + author, ["name"], callback);
|
||||
console.log(authorID);
|
||||
db.getSub("globalAuthor:" + authorID, ["name"], function(err, authorName){
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, {authorName: authorName});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
|
|
@ -16,6 +16,7 @@ var padMessageHandler = require("../handler/PadMessageHandler");
|
|||
var readOnlyManager = require("./ReadOnlyManager");
|
||||
var crypto = require("crypto");
|
||||
var randomString = require("../utils/randomstring");
|
||||
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||
|
||||
//serialization/deserialization attributes
|
||||
var attributeBlackList = ["id"];
|
||||
|
@ -86,6 +87,12 @@ Pad.prototype.appendRevision = function appendRevision(aChangeset, author) {
|
|||
// set the author to pad
|
||||
if(author)
|
||||
authorManager.addPad(author, this.id);
|
||||
|
||||
if (this.head == 0) {
|
||||
hooks.callAll("padCreate", {'pad':this});
|
||||
} else {
|
||||
hooks.callAll("padUpdate", {'pad':this});
|
||||
}
|
||||
};
|
||||
|
||||
//save all attributes to the database
|
||||
|
@ -368,6 +375,7 @@ Pad.prototype.init = function init(text, callback) {
|
|||
_this.appendRevision(firstChangeset, '');
|
||||
}
|
||||
|
||||
hooks.callAll("padLoad", {'pad':_this});
|
||||
callback(null);
|
||||
});
|
||||
};
|
||||
|
@ -467,6 +475,7 @@ Pad.prototype.remove = function remove(callback) {
|
|||
{
|
||||
db.remove("pad:"+padID);
|
||||
padManager.unloadPad(padID);
|
||||
hooks.callAll("padRemove", {'padID':padID});
|
||||
callback();
|
||||
}
|
||||
], function(err)
|
||||
|
|
|
@ -176,9 +176,11 @@ exports.handleMessage = function(client, message)
|
|||
|
||||
// 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
|
||||
hooks.aCallAll("handleMessage", { client: client, message: message }, function ( messages ) {
|
||||
hooks.aCallAll("handleMessage", { client: client, message: message }, function ( err, messages ) {
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
_.each(messages, function(newMessage){
|
||||
if ( newmessage === null ) {
|
||||
if ( newMessage === null ) {
|
||||
dropMessage = true;
|
||||
}
|
||||
});
|
||||
|
@ -415,22 +417,34 @@ function handleUserInfoUpdate(client, message)
|
|||
authorManager.setAuthorName(author, message.data.userInfo.name);
|
||||
|
||||
var padId = sessioninfos[client.id].padId;
|
||||
|
||||
var infoMsg = {
|
||||
type: "COLLABROOM",
|
||||
data: {
|
||||
// The Client doesn't know about USERINFO_UPDATE, use USER_NEWINFO
|
||||
type: "USER_NEWINFO",
|
||||
userInfo: {
|
||||
userId: author,
|
||||
name: message.data.userInfo.name,
|
||||
colorId: message.data.userInfo.colorId,
|
||||
userAgent: "Anonymous",
|
||||
ip: "127.0.0.1",
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
//set a null name, when there is no name set. cause the client wants it null
|
||||
if(message.data.userInfo.name == null)
|
||||
if(infoMsg.data.userInfo.name == null)
|
||||
{
|
||||
message.data.userInfo.name = null;
|
||||
infoMsg.data.userInfo.name = null;
|
||||
}
|
||||
|
||||
//The Client don't know about a USERINFO_UPDATE, it can handle only new user_newinfo, so change the message type
|
||||
message.data.type = "USER_NEWINFO";
|
||||
|
||||
//Send the other clients on the pad the update message
|
||||
for(var i in pad2sessions[padId])
|
||||
{
|
||||
if(pad2sessions[padId][i] != client.id)
|
||||
{
|
||||
socketio.sockets.sockets[pad2sessions[padId][i]].json.send(message);
|
||||
socketio.sockets.sockets[pad2sessions[padId][i]].json.send(infoMsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ exports.ip = "0.0.0.0";
|
|||
/**
|
||||
* The Port ep-lite should listen to
|
||||
*/
|
||||
exports.port = 9001;
|
||||
exports.port = process.env.PORT || 9001;
|
||||
/*
|
||||
* The Type of the database
|
||||
*/
|
||||
|
|
|
@ -48,7 +48,7 @@ CachingMiddleware.prototype = new function () {
|
|||
var old_res = {};
|
||||
|
||||
var supportsGzip =
|
||||
req.header('Accept-Encoding', '').indexOf('gzip') != -1;
|
||||
(req.get('Accept-Encoding') || '').indexOf('gzip') != -1;
|
||||
|
||||
var path = require('url').parse(req.url).path;
|
||||
var cacheKey = (new Buffer(path)).toString('base64').replace(/[\/\+=]/g, '');
|
||||
|
|
|
@ -5,9 +5,10 @@
|
|||
"keywords" : ["etherpad", "realtime", "collaborative", "editor"],
|
||||
"author" : "Peter 'Pita' Martischka <petermartischka@googlemail.com> - Primary Technology Ltd",
|
||||
"contributors" : [
|
||||
{ "name": "John McLear",
|
||||
"name": "Hans Pinckaers",
|
||||
"name": "Robin Buse" }
|
||||
{ "name": "John McLear" },
|
||||
{ "name": "Hans Pinckaers" },
|
||||
{ "name": "Robin Buse" },
|
||||
{ "name": "Marcel Klehr" }
|
||||
],
|
||||
"dependencies" : {
|
||||
"yajsml" : "1.1.6",
|
||||
|
@ -15,7 +16,7 @@
|
|||
"require-kernel" : "1.0.5",
|
||||
"resolve" : "0.2.x",
|
||||
"socket.io" : "0.9.x",
|
||||
"ueberDB" : "0.1.7",
|
||||
"ueberDB" : "0.1.8",
|
||||
"async" : "0.1.22",
|
||||
"express" : "3.x",
|
||||
"connect" : "2.4.x",
|
||||
|
@ -25,7 +26,7 @@
|
|||
"log4js" : "0.5.x",
|
||||
"jsdom-nocontextifiy" : "0.2.10",
|
||||
"async-stacktrace" : "0.0.2",
|
||||
"npm" : "1.1.24",
|
||||
"npm" : "1.1.x",
|
||||
"ejs" : "0.6.1",
|
||||
"graceful-fs" : "1.1.5",
|
||||
"slide" : "1.1.3",
|
||||
|
@ -42,5 +43,5 @@
|
|||
"engines" : { "node" : ">=0.6.0",
|
||||
"npm" : ">=1.0"
|
||||
},
|
||||
"version" : "1.1.2"
|
||||
"version" : "1.1.4"
|
||||
}
|
||||
|
|
|
@ -122,6 +122,11 @@ function Ace2Editor()
|
|||
return info.ace_getDebugProperty(prop);
|
||||
};
|
||||
|
||||
editor.getInInternationalComposition = function()
|
||||
{
|
||||
return info.ace_getInInternationalComposition();
|
||||
};
|
||||
|
||||
// prepareUserChangeset:
|
||||
// Returns null if no new changes or ACE not ready. Otherwise, bundles up all user changes
|
||||
// to the latest base text into a Changeset, which is returned (as a string if encodeAsString).
|
||||
|
|
|
@ -1173,7 +1173,7 @@ function Ace2Inner(){
|
|||
//if (! top.BEFORE) top.BEFORE = [];
|
||||
//top.BEFORE.push(magicdom.root.dom.innerHTML);
|
||||
//if (! isEditable) return; // and don't reschedule
|
||||
if (window.parent.parent.inInternationalComposition)
|
||||
if (inInternationalComposition)
|
||||
{
|
||||
// don't do idle input incorporation during international input composition
|
||||
idleWorkTimer.atLeast(500);
|
||||
|
@ -3729,7 +3729,7 @@ function Ace2Inner(){
|
|||
thisKeyDoesntTriggerNormalize = true;
|
||||
}
|
||||
|
||||
if ((!specialHandled) && (!thisKeyDoesntTriggerNormalize) && (!window.parent.parent.inInternationalComposition))
|
||||
if ((!specialHandled) && (!thisKeyDoesntTriggerNormalize) && (!inInternationalComposition))
|
||||
{
|
||||
if (type != "keyup" || !incorpIfQuick())
|
||||
{
|
||||
|
@ -4589,9 +4589,24 @@ function Ace2Inner(){
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
var inInternationalComposition = false;
|
||||
function handleCompositionEvent(evt)
|
||||
{
|
||||
window.parent.parent.handleCompositionEvent(evt);
|
||||
// international input events, fired in FF3, at least; allow e.g. Japanese input
|
||||
if (evt.type == "compositionstart")
|
||||
{
|
||||
inInternationalComposition = true;
|
||||
}
|
||||
else if (evt.type == "compositionend")
|
||||
{
|
||||
inInternationalComposition = false;
|
||||
}
|
||||
}
|
||||
|
||||
editorInfo.ace_getInInternationalComposition = function ()
|
||||
{
|
||||
return inInternationalComposition;
|
||||
}
|
||||
|
||||
function bindTheEventHandlers()
|
||||
|
|
|
@ -111,7 +111,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
|
||||
function handleUserChanges()
|
||||
{
|
||||
if (window.parent.parent.inInternationalComposition) return;
|
||||
if (editor.getInInternationalComposition()) return;
|
||||
if ((!getSocket()) || channelState == "CONNECTING")
|
||||
{
|
||||
if (channelState == "CONNECTING" && (((+new Date()) - initialStartConnectTime) > 20000))
|
||||
|
@ -288,7 +288,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
var apool = msg.apool;
|
||||
|
||||
// When inInternationalComposition, msg pushed msgQueue.
|
||||
if (msgQueue.length > 0 || window.parent.parent.inInternationalComposition) {
|
||||
if (msgQueue.length > 0 || editor.getInInternationalComposition()) {
|
||||
if (msgQueue.length > 0) oldRev = msgQueue[msgQueue.length - 1].newRev;
|
||||
else oldRev = rev;
|
||||
|
||||
|
@ -358,6 +358,14 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
|||
{
|
||||
var userInfo = msg.userInfo;
|
||||
var id = userInfo.userId;
|
||||
|
||||
// Avoid a race condition when setting colors. If our color was set by a
|
||||
// query param, ignore our own "new user" message's color value.
|
||||
if (id === initialUserInfo.userId && initialUserInfo.globalUserColor)
|
||||
{
|
||||
msg.userInfo.colorId = initialUserInfo.globalUserColor;
|
||||
}
|
||||
|
||||
|
||||
if (userSet[id])
|
||||
{
|
||||
|
|
|
@ -24,6 +24,13 @@
|
|||
|
||||
var colorutils = {};
|
||||
|
||||
// Check that a given value is a css hex color value, e.g.
|
||||
// "#ffffff" or "#fff"
|
||||
colorutils.isCssHex = function(cssColor)
|
||||
{
|
||||
return /^#([0-9a-f]{3}|[0-9a-f]{6})$/i.test(cssColor);
|
||||
}
|
||||
|
||||
// "#ffffff" or "#fff" or "ffffff" or "fff" to [1.0, 1.0, 1.0]
|
||||
colorutils.css2triple = function(cssColor)
|
||||
{
|
||||
|
|
|
@ -311,7 +311,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class
|
|||
['insertorder', 'first']
|
||||
].concat(
|
||||
_.map(state.lineAttributes,function(value,key){
|
||||
if (window.console) console.log([key, value])
|
||||
if (typeof(window)!= 'undefined' && window.console) console.log([key, value])
|
||||
return [key, value];
|
||||
})
|
||||
);
|
||||
|
|
|
@ -43,6 +43,7 @@ var padmodals = require('./pad_modals').padmodals;
|
|||
var padsavedrevs = require('./pad_savedrevs');
|
||||
var paduserlist = require('./pad_userlist').paduserlist;
|
||||
var padutils = require('./pad_utils').padutils;
|
||||
var colorutils = require('./colorutils').colorutils;
|
||||
|
||||
var createCookie = require('./pad_utils').createCookie;
|
||||
var readCookie = require('./pad_utils').readCookie;
|
||||
|
@ -50,22 +51,6 @@ var randomString = require('./pad_utils').randomString;
|
|||
|
||||
var hooks = require('./pluginfw/hooks');
|
||||
|
||||
window.inInternationalComposition = false;
|
||||
var inInternationalComposition = window.inInternationalComposition;
|
||||
|
||||
window.handleCompositionEvent = function handleCompositionEvent(evt)
|
||||
{
|
||||
// international input events, fired in FF3, at least; allow e.g. Japanese input
|
||||
if (evt.type == "compositionstart")
|
||||
{
|
||||
this.inInternationalComposition = true;
|
||||
}
|
||||
else if (evt.type == "compositionend")
|
||||
{
|
||||
this.inInternationalComposition = false;
|
||||
}
|
||||
}
|
||||
|
||||
function createCookie(name, value, days, path)
|
||||
{
|
||||
if (days)
|
||||
|
@ -114,6 +99,7 @@ function getParams()
|
|||
var showControls = params["showControls"];
|
||||
var showChat = params["showChat"];
|
||||
var userName = params["userName"];
|
||||
var userColor = params["userColor"];
|
||||
var showLineNumbers = params["showLineNumbers"];
|
||||
var useMonospaceFont = params["useMonospaceFont"];
|
||||
var IsnoColors = params["noColors"];
|
||||
|
@ -162,6 +148,11 @@ function getParams()
|
|||
// If the username is set as a parameter we should set a global value that we can call once we have initiated the pad.
|
||||
settings.globalUserName = decodeURIComponent(userName);
|
||||
}
|
||||
if(userColor)
|
||||
// If the userColor is set as a parameter, set a global value to use once we have initiated the pad.
|
||||
{
|
||||
settings.globalUserColor = decodeURIComponent(userColor);
|
||||
}
|
||||
if(rtl)
|
||||
{
|
||||
if(rtl == "true")
|
||||
|
@ -363,6 +354,14 @@ function handshake()
|
|||
pad.myUserInfo.name = settings.globalUserName;
|
||||
$('#myusernameedit').attr({"value":settings.globalUserName}); // Updates the current users UI
|
||||
}
|
||||
if (settings.globalUserColor !== false && colorutils.isCssHex(settings.globalUserColor))
|
||||
{
|
||||
|
||||
// Add a 'globalUserColor' property to myUserInfo, so collabClient knows we have a query parameter.
|
||||
pad.myUserInfo.globalUserColor = settings.globalUserColor;
|
||||
pad.notifyChangeColor(settings.globalUserColor); // Updates pad.myUserInfo.colorId
|
||||
paduserlist.setMyUserInfo(pad.myUserInfo);
|
||||
}
|
||||
}
|
||||
//This handles every Message after the clientVars
|
||||
else
|
||||
|
@ -1029,6 +1028,7 @@ var settings = {
|
|||
, noColors: false
|
||||
, useMonospaceFontGlobal: false
|
||||
, globalUserName: false
|
||||
, globalUserColor: false
|
||||
, rtlIsTrue: false
|
||||
};
|
||||
|
||||
|
|
|
@ -144,13 +144,12 @@ function handleClientVars(message)
|
|||
require('./pad_impexp').padimpexp.init();
|
||||
|
||||
//change export urls when the slider moves
|
||||
var export_rev_regex = /(\/\d+)?\/export/
|
||||
BroadcastSlider.onSlider(function(revno)
|
||||
{
|
||||
// export_links is a jQuery Array, so .each is allowed.
|
||||
export_links.each(function()
|
||||
{
|
||||
this.setAttribute('href', this.href.replace(export_rev_regex, '/' + revno + '/export'));
|
||||
this.setAttribute('href', this.href.replace( /(.+?)\/\w+\/(\d+\/)?export/ , '$1/' + padId + '/' + revno + '/export'));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -2,6 +2,29 @@
|
|||
<html>
|
||||
|
||||
<title>Etherpad Lite</title>
|
||||
<script>
|
||||
/*
|
||||
|@licstart The following is the entire license notice for the
|
||||
JavaScript code in this page.|
|
||||
|
||||
Copyright 2011 Peter Martischka, Primary Technology.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|@licend The above is the entire license notice
|
||||
for the JavaScript code in this page.|
|
||||
*/
|
||||
</script>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
||||
|
@ -9,9 +32,11 @@
|
|||
<link rel="shortcut icon" href="favicon.ico">
|
||||
|
||||
<style>
|
||||
html, body {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
color: #333;
|
||||
font: 14px helvetica, sans-serif;
|
||||
background: #ddd;
|
||||
|
|
|
@ -3,8 +3,30 @@
|
|||
%>
|
||||
<!doctype html>
|
||||
<html>
|
||||
|
||||
<title>Etherpad Lite</title>
|
||||
<script>
|
||||
/*
|
||||
|@licstart The following is the entire license notice for the
|
||||
JavaScript code in this page.|
|
||||
|
||||
Copyright 2011 Peter Martischka, Primary Technology.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|@licend The above is the entire license notice
|
||||
for the JavaScript code in this page.|
|
||||
*/
|
||||
</script>
|
||||
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
|
@ -233,7 +255,7 @@
|
|||
</div>
|
||||
<div class="reconnecting">
|
||||
<h1>Reestablishing connection...</h1>
|
||||
<p><img alt="" border="0" src="/static/img/connectingbar.gif" /></p>
|
||||
<p><img alt="" border="0" src="../static/img/connectingbar.gif" /></p>
|
||||
</div>
|
||||
<div class="userdup">
|
||||
<h1>Opened in another window.</h1>
|
||||
|
|
|
@ -1,11 +1,32 @@
|
|||
<!doctype html>
|
||||
<html lang="en">
|
||||
<title>Etherpad Lite Timeslider</title>
|
||||
<script>
|
||||
/*
|
||||
|@licstart The following is the entire license notice for the
|
||||
JavaScript code in this page.|
|
||||
|
||||
Copyright 2011 Peter Martischka, Primary Technology.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|@licend The above is the entire license notice
|
||||
for the JavaScript code in this page.|
|
||||
*/
|
||||
</script>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="robots" content="noindex, nofollow">
|
||||
|
||||
<title>Etherpad Lite Timeslider</title>
|
||||
|
||||
<link rel="shortcut icon" href="../../favicon.ico">
|
||||
<link rel="stylesheet" href="../../static/css/pad.css">
|
||||
<link rel="stylesheet" href="../../static/css/timeslider.css">
|
||||
|
@ -83,7 +104,7 @@
|
|||
</div>
|
||||
<div class="reconnecting">
|
||||
<h1>Reestablishing connection...</h1>
|
||||
<p><img alt="" border="0" src="/static/img/connectingbar.gif" /></p>
|
||||
<p><img alt="" border="0" src="../../static/img/connectingbar.gif" /></p>
|
||||
</div>
|
||||
<div class="userdup">
|
||||
<h1>Opened in another window.</h1>
|
||||
|
|
32
src/web.config
Normal file
32
src/web.config
Normal file
|
@ -0,0 +1,32 @@
|
|||
<configuration>
|
||||
<system.webServer>
|
||||
|
||||
<handlers>
|
||||
<add name="iisnode" path="node_modules/ep_etherpad-lite/node/server.js" verb="*" modules="iisnode" />
|
||||
</handlers>
|
||||
|
||||
<rewrite>
|
||||
<rules>
|
||||
<!-- uncomment this section to enable debugging
|
||||
<rule name="LogFile" patternSyntax="ECMAScript" stopProcessing="true">
|
||||
<match url="iisnode"/>
|
||||
<action type="Rewrite" url="node_modules/ep_etherpad-lite/node/iisnode" />
|
||||
</rule>
|
||||
<rule name="NodeInspector" patternSyntax="ECMAScript" stopProcessing="true">
|
||||
<match url="^server.js\/debug[\/]?" />
|
||||
</rule>
|
||||
-->
|
||||
<rule name="StaticContent">
|
||||
<action type="Rewrite" url="public{{REQUEST_URI}}"/>
|
||||
</rule>
|
||||
<rule name="DynamicContent">
|
||||
<conditions>
|
||||
<add input="{{REQUEST_FILENAME}}" matchType="IsFile" negate="True"/>
|
||||
</conditions>
|
||||
<action type="Rewrite" url="node_modules/ep_etherpad-lite/node/server.js" />
|
||||
</rule>
|
||||
</rules>
|
||||
</rewrite>
|
||||
|
||||
</system.webServer>
|
||||
</configuration>
|
Loading…
Add table
Add a link
Reference in a new issue