mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-21 16:06:16 -04:00
Merge branch 'develop' of github.com:Pita/etherpad-lite into feature/frontend-tests
This commit is contained in:
commit
c74aed986e
17 changed files with 331 additions and 168 deletions
|
@ -436,15 +436,22 @@ function handleUserInfoUpdate(client, message)
|
|||
}
|
||||
|
||||
/**
|
||||
* Handles a USERINFO_UPDATE, that means that a user have changed his color or name. Anyway, we get both informations
|
||||
* This Method is nearly 90% copied out of the Etherpad Source Code. So I can't tell you what happens here exactly
|
||||
* Look at https://github.com/ether/pad/blob/master/etherpad/src/etherpad/collab/collab_server.js in the function applyUserChanges()
|
||||
* Handles a USER_CHANGES message, where the client submits its local
|
||||
* edits as a changeset.
|
||||
*
|
||||
* This handler's job is to update the incoming changeset so that it applies
|
||||
* to the latest revision, then add it to the pad, broadcast the changes
|
||||
* to all other clients, and send a confirmation to the submitting client.
|
||||
*
|
||||
* This function is based on a similar one in the original Etherpad.
|
||||
* See https://github.com/ether/pad/blob/master/etherpad/src/etherpad/collab/collab_server.js in the function applyUserChanges()
|
||||
*
|
||||
* @param client the client that send this message
|
||||
* @param message the message from the client
|
||||
*/
|
||||
function handleUserChanges(client, message)
|
||||
{
|
||||
//check if all ok
|
||||
// Make sure all required fields are present
|
||||
if(message.data.baseRev == null)
|
||||
{
|
||||
messageLogger.warn("Dropped message, USER_CHANGES Message has no baseRev!");
|
||||
|
@ -487,22 +494,23 @@ function handleUserChanges(client, message)
|
|||
{
|
||||
//ex. _checkChangesetAndPool
|
||||
|
||||
//Copied from Etherpad, don't know what it does exactly
|
||||
try
|
||||
{
|
||||
//this looks like a changeset check, it throws errors sometimes
|
||||
// Verify that the changeset has valid syntax and is in canonical form
|
||||
Changeset.checkRep(changeset);
|
||||
|
||||
|
||||
// Verify that the attribute indexes used in the changeset are all
|
||||
// defined in the accompanying attribute pool.
|
||||
Changeset.eachAttribNumber(changeset, function(n) {
|
||||
if (! wireApool.getAttrib(n)) {
|
||||
throw "Attribute pool is missing attribute "+n+" for changeset "+changeset;
|
||||
}
|
||||
});
|
||||
}
|
||||
//there is an error in this changeset, so just refuse it
|
||||
catch(e)
|
||||
{
|
||||
console.warn("Can't apply USER_CHANGES "+changeset+", cause it faild checkRep");
|
||||
// There is an error in this changeset, so just refuse it
|
||||
console.warn("Can't apply USER_CHANGES "+changeset+", because it failed checkRep");
|
||||
client.json.send({disconnect:"badChangeset"});
|
||||
return;
|
||||
}
|
||||
|
@ -515,7 +523,10 @@ function handleUserChanges(client, message)
|
|||
//ex. applyUserChanges
|
||||
apool = pad.pool;
|
||||
r = baseRev;
|
||||
|
||||
|
||||
// The client's changeset might not be based on the latest revision,
|
||||
// since other clients are sending changes at the same time.
|
||||
// Update the changeset so that it can be applied to the latest revision.
|
||||
//https://github.com/caolan/async#whilst
|
||||
async.whilst(
|
||||
function() { return r < pad.getHeadRevisionNumber(); },
|
||||
|
@ -526,8 +537,13 @@ function handleUserChanges(client, message)
|
|||
pad.getRevisionChangeset(r, function(err, c)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
|
||||
// At this point, both "c" (from the pad) and "changeset" (from the
|
||||
// client) are relative to revision r - 1. The follow function
|
||||
// rebases "changeset" so that it is relative to revision r
|
||||
// and can be applied after "c".
|
||||
changeset = Changeset.follow(c, changeset, false, apool);
|
||||
|
||||
if ((r - baseRev) % 200 == 0) { // don't let the stack get too deep
|
||||
async.nextTick(callback);
|
||||
} else {
|
||||
|
@ -558,7 +574,8 @@ function handleUserChanges(client, message)
|
|||
if (correctionChangeset) {
|
||||
pad.appendRevision(correctionChangeset);
|
||||
}
|
||||
|
||||
|
||||
// Make sure the pad always ends with an empty line.
|
||||
if (pad.text().lastIndexOf("\n\n") != pad.text().length-2) {
|
||||
var nlChangeset = Changeset.makeSplice(pad.text(), pad.text().length-1, 0, "\n");
|
||||
pad.appendRevision(nlChangeset);
|
||||
|
@ -865,6 +882,13 @@ function handleClientReady(client, message)
|
|||
},
|
||||
function(callback)
|
||||
{
|
||||
//Check that the client is still here. It might have disconnected between callbacks.
|
||||
if(sessioninfos[client.id] === undefined)
|
||||
{
|
||||
callback();
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if this author is already on the pad, if yes, kick the other sessions!
|
||||
if(pad2sessions[padIds.padId])
|
||||
{
|
||||
|
@ -879,10 +903,9 @@ function handleClientReady(client, message)
|
|||
}
|
||||
|
||||
//Save in sessioninfos that this session belonges to this pad
|
||||
var sessionId=String(client.id);
|
||||
sessioninfos[sessionId].padId = padIds.padId;
|
||||
sessioninfos[sessionId].readOnlyPadId = padIds.readOnlyPadId;
|
||||
sessioninfos[sessionId].readonly = padIds.readonly;
|
||||
sessioninfos[client.id].padId = padIds.padId;
|
||||
sessioninfos[client.id].readOnlyPadId = padIds.readOnlyPadId;
|
||||
sessioninfos[client.id].readonly = padIds.readonly;
|
||||
|
||||
//check if there is already a pad2sessions entry, if not, create one
|
||||
if(!pad2sessions[padIds.padId])
|
||||
|
@ -891,7 +914,7 @@ function handleClientReady(client, message)
|
|||
}
|
||||
|
||||
//Saves in pad2sessions that this session belongs to this pad
|
||||
pad2sessions[padIds.padId].push(sessionId);
|
||||
pad2sessions[padIds.padId].push(client.id);
|
||||
|
||||
//prepare all values for the wire
|
||||
var atext = Changeset.cloneAText(pad.atext);
|
||||
|
@ -956,26 +979,22 @@ function handleClientReady(client, message)
|
|||
clientVars.userName = authorName;
|
||||
}
|
||||
|
||||
if(sessioninfos[client.id] !== undefined)
|
||||
//If this is a reconnect, we don't have to send the client the ClientVars again
|
||||
if(message.reconnect == true)
|
||||
{
|
||||
//This is a reconnect, so we don't have to send the client the ClientVars again
|
||||
if(message.reconnect == true)
|
||||
{
|
||||
//Save the revision in sessioninfos, we take the revision from the info the client send to us
|
||||
sessioninfos[client.id].rev = message.client_rev;
|
||||
}
|
||||
//This is a normal first connect
|
||||
else
|
||||
{
|
||||
//Send the clientVars to the Client
|
||||
client.json.send({type: "CLIENT_VARS", data: clientVars});
|
||||
//Save the revision in sessioninfos
|
||||
sessioninfos[client.id].rev = pad.getHeadRevisionNumber();
|
||||
}
|
||||
|
||||
//Save the revision and the author id in sessioninfos
|
||||
sessioninfos[client.id].author = author;
|
||||
//Save the revision in sessioninfos, we take the revision from the info the client send to us
|
||||
sessioninfos[client.id].rev = message.client_rev;
|
||||
}
|
||||
//This is a normal first connect
|
||||
else
|
||||
{
|
||||
//Send the clientVars to the Client
|
||||
client.json.send({type: "CLIENT_VARS", data: clientVars});
|
||||
//Save the current revision in sessioninfos, should be the same as in clientVars
|
||||
sessioninfos[client.id].rev = pad.getHeadRevisionNumber();
|
||||
}
|
||||
|
||||
sessioninfos[client.id].author = author;
|
||||
|
||||
//prepare the notification for the other users on the pad, that this user joined
|
||||
var messageToTheOtherUsers = {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
|
||||
var http = require('http');
|
||||
var express = require('express');
|
||||
var settings = require('../utils/Settings');
|
||||
var fs = require('fs');
|
||||
|
@ -42,22 +43,24 @@ exports.createServer = function () {
|
|||
}
|
||||
|
||||
exports.restartServer = function () {
|
||||
|
||||
if (server) {
|
||||
console.log("Restarting express server");
|
||||
server.close();
|
||||
}
|
||||
|
||||
server = express.createServer();
|
||||
var app = express(); // New syntax for express v3
|
||||
server = http.createServer(app);
|
||||
|
||||
server.use(function (req, res, next) {
|
||||
app.use(function (req, res, next) {
|
||||
res.header("Server", serverName);
|
||||
next();
|
||||
});
|
||||
|
||||
server.configure(function() {
|
||||
hooks.callAll("expressConfigure", {"app": server});
|
||||
app.configure(function() {
|
||||
hooks.callAll("expressConfigure", {"app": app});
|
||||
});
|
||||
hooks.callAll("expressCreateServer", {"app": server});
|
||||
hooks.callAll("expressCreateServer", {"app": app, "server": server});
|
||||
|
||||
server.listen(settings.port, settings.ip);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,14 +12,10 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
errors: [],
|
||||
};
|
||||
|
||||
res.send(eejs.require(
|
||||
"ep_etherpad-lite/templates/admin/plugins.html",
|
||||
render_args), {});
|
||||
res.send( eejs.require("ep_etherpad-lite/templates/admin/plugins.html", render_args) );
|
||||
});
|
||||
args.app.get('/admin/plugins/info', function(req, res) {
|
||||
res.send(eejs.require(
|
||||
"ep_etherpad-lite/templates/admin/plugins-info.html",
|
||||
{}), {});
|
||||
res.send( eejs.require("ep_etherpad-lite/templates/admin/plugins-info.html", {}) );
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,6 @@ exports.gracefulShutdown = function(err) {
|
|||
|
||||
console.log("graceful shutdown...");
|
||||
|
||||
//stop the http server
|
||||
exports.app.close();
|
||||
|
||||
//do the db shutdown
|
||||
db.db.doShutdown(function() {
|
||||
console.log("db sucessfully closed.");
|
||||
|
@ -35,11 +32,14 @@ exports.gracefulShutdown = function(err) {
|
|||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
exports.app = args.app;
|
||||
|
||||
args.app.error(function(err, req, res, next){
|
||||
res.send(500);
|
||||
console.error(err.stack ? err.stack : err.toString());
|
||||
exports.gracefulShutdown();
|
||||
});
|
||||
// Handle errors
|
||||
args.app.use(function(err, req, res, next){
|
||||
// if an error occurs Connect will pass it down
|
||||
// through these "error-handling" middleware
|
||||
// allowing you to respond however you like
|
||||
res.send(500, { error: 'Sorry, something bad happened!' });
|
||||
console.error(err.stack? err.stack : err.toString());
|
||||
})
|
||||
|
||||
//connect graceful shutdown with sigint and uncaughtexception
|
||||
if(os.type().indexOf("Windows") == -1) {
|
||||
|
|
|
@ -56,7 +56,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
ERR(err);
|
||||
|
||||
if(err == "notfound")
|
||||
res.send('404 - Not Found', 404);
|
||||
res.send(404, '404 - Not Found');
|
||||
else
|
||||
res.send(html);
|
||||
});
|
||||
|
|
|
@ -7,7 +7,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
//ensure the padname is valid and the url doesn't end with a /
|
||||
if(!padManager.isValidPadId(padId) || /\/$/.test(req.url))
|
||||
{
|
||||
res.send('Such a padname is forbidden', 404);
|
||||
res.send(404, 'Such a padname is forbidden');
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -19,7 +19,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
var query = url.parse(req.url).query;
|
||||
if ( query ) real_url += '?' + query;
|
||||
res.header('Location', real_url);
|
||||
res.send('You should be redirected to <a href="' + real_url + '">' + real_url + '</a>', 302);
|
||||
res.send(302, 'You should be redirected to <a href="' + real_url + '">' + real_url + '</a>');
|
||||
}
|
||||
//the pad id was fine, so just render it
|
||||
else
|
||||
|
|
|
@ -3,6 +3,7 @@ var socketio = require('socket.io');
|
|||
var settings = require('../../utils/Settings');
|
||||
var socketIORouter = require("../../handler/SocketIORouter");
|
||||
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
|
||||
var webaccess = require("ep_etherpad-lite/node/hooks/express/webaccess");
|
||||
|
||||
var padMessageHandler = require("../../handler/PadMessageHandler");
|
||||
|
||||
|
@ -10,19 +11,28 @@ var connect = require('connect');
|
|||
|
||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||
//init socket.io and redirect all requests to the MessageHandler
|
||||
var io = socketio.listen(args.app);
|
||||
var io = socketio.listen(args.server);
|
||||
|
||||
/* Require an express session cookie to be present, and load the
|
||||
* session. See http://www.danielbaulig.de/socket-ioexpress for more
|
||||
* info */
|
||||
io.set('authorization', function (data, accept) {
|
||||
if (!data.headers.cookie) return accept('No session cookie transmitted.', false);
|
||||
data.cookie = connect.utils.parseCookie(data.headers.cookie);
|
||||
data.sessionID = data.cookie.express_sid;
|
||||
args.app.sessionStore.get(data.sessionID, function (err, session) {
|
||||
if (err || !session) return accept('Bad session / session has expired', false);
|
||||
data.session = new connect.middleware.session.Session(data, session);
|
||||
accept(null, true);
|
||||
|
||||
// Use connect's cookie parser, because it knows how to parse signed cookies
|
||||
connect.cookieParser(webaccess.secret)(data, {}, function(err){
|
||||
if(err) {
|
||||
console.error(err);
|
||||
accept("Couldn't parse request cookies. ", false);
|
||||
return;
|
||||
}
|
||||
|
||||
data.sessionID = data.signedCookies.express_sid;
|
||||
args.app.sessionStore.get(data.sessionID, function (err, session) {
|
||||
if (err || !session) return accept('Bad session / session has expired', false);
|
||||
data.session = new connect.middleware.session.Session(data, session);
|
||||
accept(null, true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -62,5 +72,5 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
socketIORouter.setSocketIO(io);
|
||||
socketIORouter.addComponent("pad", padMessageHandler);
|
||||
|
||||
hooks.callAll("socketio", {"app": args.app, "io": io});
|
||||
hooks.callAll("socketio", {"app": args.app, "io": io, "server": args.server});
|
||||
}
|
||||
|
|
|
@ -56,10 +56,10 @@ exports.basicAuth = function (req, res, next) {
|
|||
res.header('WWW-Authenticate', 'Basic realm="Protected Area"');
|
||||
if (req.headers.authorization) {
|
||||
setTimeout(function () {
|
||||
res.send('Authentication required', 401);
|
||||
res.send(401, 'Authentication required');
|
||||
}, 1000);
|
||||
} else {
|
||||
res.send('Authentication required', 401);
|
||||
res.send(401, 'Authentication required');
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -88,14 +88,13 @@ exports.basicAuth = function (req, res, next) {
|
|||
});
|
||||
}
|
||||
|
||||
var secret = null;
|
||||
exports.secret = null;
|
||||
|
||||
exports.expressConfigure = function (hook_name, args, cb) {
|
||||
// If the log level specified in the config file is WARN or ERROR the application server never starts listening to requests as reported in issue #158.
|
||||
// Not installing the log4js connect logger when the log level has a higher severity than INFO since it would not log at that level anyway.
|
||||
if (!(settings.loglevel === "WARN" || settings.loglevel == "ERROR"))
|
||||
args.app.use(log4js.connectLogger(httpLogger, { level: log4js.levels.INFO, format: ':status, :method :url'}));
|
||||
args.app.use(express.cookieParser());
|
||||
|
||||
/* Do not let express create the session, so that we can retain a
|
||||
* reference to it for socket.io to use. Also, set the key (cookie
|
||||
|
@ -104,13 +103,14 @@ exports.expressConfigure = function (hook_name, args, cb) {
|
|||
|
||||
if (!exports.sessionStore) {
|
||||
exports.sessionStore = new express.session.MemoryStore();
|
||||
secret = randomString(32);
|
||||
exports.secret = randomString(32);
|
||||
}
|
||||
|
||||
args.app.use(express.cookieParser(exports.secret));
|
||||
|
||||
args.app.sessionStore = exports.sessionStore;
|
||||
args.app.use(express.session({store: args.app.sessionStore,
|
||||
key: 'express_sid',
|
||||
secret: secret}));
|
||||
key: 'express_sid' }));
|
||||
|
||||
args.app.use(exports.basicAuth);
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ module.exports = function (req, res, callback) {
|
|||
callback();
|
||||
//no access
|
||||
} else {
|
||||
res.send("403 - Can't touch this", 403);
|
||||
res.send(403, "403 - Can't touch this");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -21,8 +21,15 @@
|
|||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// set up logger
|
||||
var log4js = require('log4js');
|
||||
log4js.replaceConsole();
|
||||
|
||||
var settings = require('./utils/Settings');
|
||||
|
||||
//set loglevel
|
||||
log4js.setGlobalLogLevel(settings.loglevel);
|
||||
|
||||
var db = require('./db/DB');
|
||||
var async = require('async');
|
||||
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins");
|
||||
|
@ -31,9 +38,6 @@ var npm = require("npm/lib/npm.js");
|
|||
|
||||
hooks.plugins = plugins;
|
||||
|
||||
//set loglevel
|
||||
log4js.setGlobalLogLevel(settings.loglevel);
|
||||
|
||||
async.waterfall([
|
||||
//initalize the database
|
||||
function (callback)
|
||||
|
|
|
@ -10,19 +10,19 @@
|
|||
"name": "Robin Buse" }
|
||||
],
|
||||
"dependencies" : {
|
||||
"yajsml" : "1.1.5",
|
||||
"yajsml" : "1.1.6",
|
||||
"request" : "2.9.100",
|
||||
"require-kernel" : "1.0.5",
|
||||
"resolve" : "0.2.x",
|
||||
"socket.io" : "0.9.x",
|
||||
"ueberDB" : "0.1.7",
|
||||
"async" : "0.1.x",
|
||||
"express" : "2.5.x",
|
||||
"connect" : "1.x",
|
||||
"async" : "0.1.22",
|
||||
"express" : "3.x",
|
||||
"connect" : "2.4.x",
|
||||
"clean-css" : "0.3.2",
|
||||
"uglify-js" : "1.2.5",
|
||||
"formidable" : "1.0.9",
|
||||
"log4js" : "0.4.1",
|
||||
"log4js" : "0.5.x",
|
||||
"jsdom-nocontextifiy" : "0.2.10",
|
||||
"async-stacktrace" : "0.0.2",
|
||||
"npm" : "1.1.24",
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
// requires: plugins
|
||||
// requires: undefined
|
||||
|
||||
var KERNEL_SOURCE = '../static/js/require-kernel.js';
|
||||
|
||||
Ace2Editor.registry = {
|
||||
nextId: 1
|
||||
};
|
||||
|
@ -31,6 +33,14 @@ Ace2Editor.registry = {
|
|||
var hooks = require('./pluginfw/hooks');
|
||||
var _ = require('./underscore');
|
||||
|
||||
function scriptTag(source) {
|
||||
return (
|
||||
'<script type="text/javascript">\n'
|
||||
+ source.replace(/<\//g, '<\\/') +
|
||||
'</script>'
|
||||
)
|
||||
}
|
||||
|
||||
function Ace2Editor()
|
||||
{
|
||||
var ace2 = Ace2Editor;
|
||||
|
@ -155,24 +165,6 @@ function Ace2Editor()
|
|||
|
||||
return {embeded: embededFiles, remote: remoteFiles};
|
||||
}
|
||||
function pushRequireScriptTo(buffer) {
|
||||
var KERNEL_SOURCE = '../static/js/require-kernel.js';
|
||||
var KERNEL_BOOT = '\
|
||||
require.setRootURI("../javascripts/src");\n\
|
||||
require.setLibraryURI("../javascripts/lib");\n\
|
||||
require.setGlobalKeyPath("require");\n\
|
||||
';
|
||||
if (Ace2Editor.EMBEDED && Ace2Editor.EMBEDED[KERNEL_SOURCE]) {
|
||||
buffer.push('<script type="text/javascript">');
|
||||
buffer.push(Ace2Editor.EMBEDED[KERNEL_SOURCE]);
|
||||
buffer.push(KERNEL_BOOT);
|
||||
buffer.push('<\/script>');
|
||||
} else {
|
||||
// Remotely src'd script tag will not work in IE; it must be embedded, so
|
||||
// throw an error if it is not.
|
||||
throw new Error("Require script could not be embedded.");
|
||||
}
|
||||
}
|
||||
function pushStyleTagsFor(buffer, files) {
|
||||
var sorted = sortFilesByEmbeded(files);
|
||||
var embededFiles = sorted.embeded;
|
||||
|
@ -236,23 +228,30 @@ require.setGlobalKeyPath("require");\n\
|
|||
|
||||
pushStyleTagsFor(iframeHTML, includedCSS);
|
||||
|
||||
var includedJS = [];
|
||||
pushRequireScriptTo(iframeHTML);
|
||||
if (!Ace2Editor.EMBEDED && Ace2Editor.EMBEDED[KERNEL_SOURCE]) {
|
||||
// Remotely src'd script tag will not work in IE; it must be embedded, so
|
||||
// throw an error if it is not.
|
||||
throw new Error("Require kernel could not be found.");
|
||||
}
|
||||
|
||||
// Inject my plugins into my child.
|
||||
iframeHTML.push('\
|
||||
<script type="text/javascript">\n\
|
||||
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");\n\
|
||||
var plugins = require("ep_etherpad-lite/static/js/pluginfw/client_plugins");\n\
|
||||
hooks.plugins = plugins;\n\
|
||||
plugins.adoptPluginsFromAncestorsOf(window);\n\
|
||||
</script>\
|
||||
');
|
||||
|
||||
iframeHTML.push('<script type="text/javascript">');
|
||||
iframeHTML.push('$ = jQuery = require("ep_etherpad-lite/static/js/rjquery").jQuery; // Expose jQuery #HACK');
|
||||
iframeHTML.push('require("ep_etherpad-lite/static/js/ace2_inner");');
|
||||
iframeHTML.push('<\/script>');
|
||||
iframeHTML.push(scriptTag(
|
||||
Ace2Editor.EMBEDED[KERNEL_SOURCE] + '\n\
|
||||
require.setRootURI("../javascripts/src");\n\
|
||||
require.setLibraryURI("../javascripts/lib");\n\
|
||||
require.setGlobalKeyPath("require");\n\
|
||||
\n\
|
||||
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");\n\
|
||||
var plugins = require("ep_etherpad-lite/static/js/pluginfw/client_plugins");\n\
|
||||
hooks.plugins = plugins;\n\
|
||||
plugins.adoptPluginsFromAncestorsOf(window);\n\
|
||||
\n\
|
||||
$ = jQuery = require("ep_etherpad-lite/static/js/rjquery").jQuery; // Expose jQuery #HACK\n\
|
||||
var Ace2Inner = require("ep_etherpad-lite/static/js/ace2_inner");\n\
|
||||
\n\
|
||||
plugins.ensure(function () {\n\
|
||||
Ace2Inner.init();\n\
|
||||
});\n\
|
||||
'));
|
||||
|
||||
iframeHTML.push('<style type="text/css" title="dynamicsyntax"></style>');
|
||||
|
||||
|
@ -266,8 +265,32 @@ require.setGlobalKeyPath("require");\n\
|
|||
var thisFunctionsName = "ChildAccessibleAce2Editor";
|
||||
(function () {return this}())[thisFunctionsName] = Ace2Editor;
|
||||
|
||||
var outerScript = 'editorId = "' + info.id + '"; editorInfo = parent.' + thisFunctionsName + '.registry[editorId]; ' + 'window.onload = function() ' + '{ window.onload = null; setTimeout' + '(function() ' + '{ var iframe = document.createElement("IFRAME"); iframe.name = "ace_inner";' + 'iframe.scrolling = "no"; var outerdocbody = document.getElementById("outerdocbody"); ' + 'iframe.frameBorder = 0; iframe.allowTransparency = true; ' + // for IE
|
||||
'outerdocbody.insertBefore(iframe, outerdocbody.firstChild); ' + 'iframe.ace_outerWin = window; ' + 'readyFunc = function() { editorInfo.onEditorReady(); readyFunc = null; editorInfo = null; }; ' + 'var doc = iframe.contentWindow.document; doc.open(); var text = (' + JSON.stringify(iframeHTML.join('\n')) + ');doc.write(text); doc.close(); ' + '}, 0); }';
|
||||
var outerScript = '\
|
||||
editorId = ' + JSON.stringify(info.id) + ';\n\
|
||||
editorInfo = parent[' + JSON.stringify(thisFunctionsName) + '].registry[editorId];\n\
|
||||
window.onload = function () {\n\
|
||||
window.onload = null;\n\
|
||||
setTimeout(function () {\n\
|
||||
var iframe = document.createElement("IFRAME");\n\
|
||||
iframe.name = "ace_inner";\n\
|
||||
iframe.scrolling = "no";\n\
|
||||
var outerdocbody = document.getElementById("outerdocbody");\n\
|
||||
iframe.frameBorder = 0;\n\
|
||||
iframe.allowTransparency = true; // for IE\n\
|
||||
outerdocbody.insertBefore(iframe, outerdocbody.firstChild);\n\
|
||||
iframe.ace_outerWin = window;\n\
|
||||
readyFunc = function () {\n\
|
||||
editorInfo.onEditorReady();\n\
|
||||
readyFunc = null;\n\
|
||||
editorInfo = null;\n\
|
||||
};\n\
|
||||
var doc = iframe.contentWindow.document;\n\
|
||||
doc.open();\n\
|
||||
var text = (' + JSON.stringify(iframeHTML.join('\n')) + ');\n\
|
||||
doc.write(text);\n\
|
||||
doc.close();\n\
|
||||
}, 0);\n\
|
||||
}';
|
||||
|
||||
var outerHTML = [doctype, '<html><head>']
|
||||
|
||||
|
@ -285,7 +308,7 @@ require.setGlobalKeyPath("require");\n\
|
|||
|
||||
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly
|
||||
// (throbs busy while typing)
|
||||
outerHTML.push('<link rel="stylesheet" type="text/css" href="data:text/css,"/>', '\x3cscript>\n', outerScript.replace(/<\//g, '<\\/'), '\n\x3c/script>', '</head><body id="outerdocbody"><div id="sidediv"><!-- --></div><div id="linemetricsdiv">x</div><div id="overlaysdiv"><!-- --></div></body></html>');
|
||||
outerHTML.push('<link rel="stylesheet" type="text/css" href="data:text/css,"/>', scriptTag(outerScript), '</head><body id="outerdocbody"><div id="sidediv"><!-- --></div><div id="linemetricsdiv">x</div><div id="overlaysdiv"><!-- --></div></body></html>');
|
||||
|
||||
var outerFrame = document.createElement("IFRAME");
|
||||
outerFrame.name = "ace_outer";
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
var editor, _, $, jQuery, plugins, Ace2Common;
|
||||
var _, $, jQuery, plugins, Ace2Common;
|
||||
|
||||
Ace2Common = require('./ace2_common');
|
||||
|
||||
|
@ -5430,62 +5430,64 @@ function Ace2Inner(){
|
|||
return documentAttributeManager.setAttributesOnRange.apply(documentAttributeManager, arguments);
|
||||
};
|
||||
|
||||
$(document).ready(function(){
|
||||
doc = document; // defined as a var in scope outside
|
||||
inCallStack("setup", function()
|
||||
{
|
||||
var body = doc.getElementById("innerdocbody");
|
||||
root = body; // defined as a var in scope outside
|
||||
if (browser.mozilla) $(root).addClass("mozilla");
|
||||
if (browser.safari) $(root).addClass("safari");
|
||||
if (browser.msie) $(root).addClass("msie");
|
||||
if (browser.msie)
|
||||
this.init = function () {
|
||||
$(document).ready(function(){
|
||||
doc = document; // defined as a var in scope outside
|
||||
inCallStack("setup", function()
|
||||
{
|
||||
// cache CSS background images
|
||||
try
|
||||
var body = doc.getElementById("innerdocbody");
|
||||
root = body; // defined as a var in scope outside
|
||||
if (browser.mozilla) $(root).addClass("mozilla");
|
||||
if (browser.safari) $(root).addClass("safari");
|
||||
if (browser.msie) $(root).addClass("msie");
|
||||
if (browser.msie)
|
||||
{
|
||||
doc.execCommand("BackgroundImageCache", false, true);
|
||||
// cache CSS background images
|
||||
try
|
||||
{
|
||||
doc.execCommand("BackgroundImageCache", false, true);
|
||||
}
|
||||
catch (e)
|
||||
{ /* throws an error in some IE 6 but not others! */
|
||||
}
|
||||
}
|
||||
catch (e)
|
||||
{ /* throws an error in some IE 6 but not others! */
|
||||
}
|
||||
}
|
||||
setClassPresence(root, "authorColors", true);
|
||||
setClassPresence(root, "doesWrap", doesWrap);
|
||||
setClassPresence(root, "authorColors", true);
|
||||
setClassPresence(root, "doesWrap", doesWrap);
|
||||
|
||||
initDynamicCSS();
|
||||
initDynamicCSS();
|
||||
|
||||
enforceEditability();
|
||||
enforceEditability();
|
||||
|
||||
// set up dom and rep
|
||||
while (root.firstChild) root.removeChild(root.firstChild);
|
||||
var oneEntry = createDomLineEntry("");
|
||||
doRepLineSplice(0, rep.lines.length(), [oneEntry]);
|
||||
insertDomLines(null, [oneEntry.domInfo], null);
|
||||
rep.alines = Changeset.splitAttributionLines(
|
||||
Changeset.makeAttribution("\n"), "\n");
|
||||
// set up dom and rep
|
||||
while (root.firstChild) root.removeChild(root.firstChild);
|
||||
var oneEntry = createDomLineEntry("");
|
||||
doRepLineSplice(0, rep.lines.length(), [oneEntry]);
|
||||
insertDomLines(null, [oneEntry.domInfo], null);
|
||||
rep.alines = Changeset.splitAttributionLines(
|
||||
Changeset.makeAttribution("\n"), "\n");
|
||||
|
||||
bindTheEventHandlers();
|
||||
bindTheEventHandlers();
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
hooks.callAll('aceInitialized', {
|
||||
editorInfo: editorInfo,
|
||||
rep: rep,
|
||||
documentAttributeManager: documentAttributeManager
|
||||
});
|
||||
hooks.callAll('aceInitialized', {
|
||||
editorInfo: editorInfo,
|
||||
rep: rep,
|
||||
documentAttributeManager: documentAttributeManager
|
||||
});
|
||||
|
||||
scheduler.setTimeout(function()
|
||||
{
|
||||
parent.readyFunc(); // defined in code that sets up the inner iframe
|
||||
}, 0);
|
||||
scheduler.setTimeout(function()
|
||||
{
|
||||
parent.readyFunc(); // defined in code that sets up the inner iframe
|
||||
}, 0);
|
||||
|
||||
isSetUp = true;
|
||||
});
|
||||
isSetUp = true;
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Ensure that plugins are loaded before initializing the editor
|
||||
plugins.ensure(function () {
|
||||
var editor = new Ace2Inner();
|
||||
});
|
||||
exports.init = function () {
|
||||
var editor = new Ace2Inner()
|
||||
editor.init();
|
||||
};
|
||||
|
|
|
@ -249,13 +249,13 @@ var padeditbar = (function()
|
|||
{
|
||||
var basePath = document.location.href.substring(0, document.location.href.indexOf("/p/"));
|
||||
var readonlyLink = basePath + "/p/" + clientVars.readOnlyId;
|
||||
$('#embedinput').val("<iframe name='embed_readonly' src='" + readonlyLink + "?showControls=true&showChat=true&showLineNumbers=true&useMonospaceFont=false' width=600 height=400>");
|
||||
$('#embedinput').val("<iframe name='embed_readonly' src='" + readonlyLink + "?showControls=true&showChat=true&showLineNumbers=true&useMonospaceFont=false' width=600 height=400></iframe>");
|
||||
$('#linkinput').val(readonlyLink);
|
||||
}
|
||||
else
|
||||
{
|
||||
var padurl = window.location.href.split("?")[0];
|
||||
$('#embedinput').val("<iframe name='embed_readwrite' src='" + padurl + "?showControls=true&showChat=true&showLineNumbers=true&useMonospaceFont=false' width=600 height=400>");
|
||||
$('#embedinput').val("<iframe name='embed_readwrite' src='" + padurl + "?showControls=true&showChat=true&showLineNumbers=true&useMonospaceFont=false' width=600 height=400></iframe>");
|
||||
$('#linkinput').val(padurl);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue