mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-04-23 00:46:16 -04:00
Merge branch 'release/1.2.8'
This commit is contained in:
commit
cb2d148734
95 changed files with 7555 additions and 6982 deletions
36
CHANGELOG.md
36
CHANGELOG.md
|
@ -1,3 +1,39 @@
|
||||||
|
# 1.2.8
|
||||||
|
! IMPORTANT: New setting.json value is required to automatically reconnect clients on disconnect
|
||||||
|
* NEW: Use Socket IO for rooms (allows for pads to be load balanced with sticky rooms)
|
||||||
|
* NEW: Plugins can now provide their own frontend tests
|
||||||
|
* NEW: Improved server-side logging
|
||||||
|
* NEW: Admin dashboard mobile device support and new hooks for Admin dashboard
|
||||||
|
* NEW: Get current API version from API
|
||||||
|
* NEW: CLI script to delete pads
|
||||||
|
* Fix: Automatic client reconnection on disonnect
|
||||||
|
* Fix: Text Export indentation now supports multiple indentations
|
||||||
|
* Fix: Bugfix getChatHistory API method
|
||||||
|
* Fix: Stop Chrome losing caret after paste is texted
|
||||||
|
* Fix: Make colons on end of line create 4 spaces on indent
|
||||||
|
* Fix: Stop the client disconnecting if a rev is in the wrong order
|
||||||
|
* Fix: Various server crash issues based on rev in wrong order
|
||||||
|
* Fix: Various tests
|
||||||
|
* Fix: Make indent when on middle of the line stop creating list
|
||||||
|
* Fix: Stop long strings breaking the UX by moving focus away from beginning of line
|
||||||
|
* Fix: Redis findKeys support
|
||||||
|
* Fix: padUsersCount no longer hangs server
|
||||||
|
* Fix: Issue with two part locale specs not working
|
||||||
|
* Fix: Make plugin search case insensitive
|
||||||
|
* Fix: Indentation and bullets on text export
|
||||||
|
* Fix: Resolve various warnings on dependencies during install
|
||||||
|
* Fix: Page up / Page down now works in all browsers
|
||||||
|
* Fix: Stop Opera browser inserting two new lines on enter keypress
|
||||||
|
* Fix: Stop timeslider from showing NaN on pads with only one revision
|
||||||
|
* Other: Allow timeslider tests to run and provide & fix various other frontend-tests
|
||||||
|
* Other: Begin dropping referene to Lite. Etherpad Lite is now named "Etherpad"
|
||||||
|
* Other: Update to latest jQuery
|
||||||
|
* Other: Change loading message asking user to please wait on first build
|
||||||
|
* Other: Allow etherpad to use global npm installation (Safe since node 6.3)
|
||||||
|
* Other: Better documentation for log rotation and log message handling
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 1.2.7
|
# 1.2.7
|
||||||
* NEW: notifications are now modularized and can be stacked
|
* NEW: notifications are now modularized and can be stacked
|
||||||
* NEW: Visit a specific revision in the timeslider by suffixing #%revNumber% IE http://localhost/p/test/timeslider#12
|
* NEW: Visit a specific revision in the timeslider by suffixing #%revNumber% IE http://localhost/p/test/timeslider#12
|
||||||
|
|
|
@ -28,7 +28,7 @@ documented codebase makes it easier for developers to improve the code and contr
|
||||||
|
|
||||||
|
|
||||||
Etherpad Lite is designed to be easily embeddable and provides a [HTTP API](https://github.com/ether/etherpad-lite/wiki/HTTP-API)
|
Etherpad Lite is designed to be easily embeddable and provides a [HTTP API](https://github.com/ether/etherpad-lite/wiki/HTTP-API)
|
||||||
that allows your web application to manage pads, users and groups. It is recommended to use the [available client implementations](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) in order to interact with this API. There is also a [jQuery plugin](https://github.com/johnyma22/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website.
|
that allows your web application to manage pads, users and groups. It is recommended to use the [available client implementations](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) in order to interact with this API. There is also a [jQuery plugin](https://github.com/ether/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website.
|
||||||
There's also a full-featured plugin framework, allowing you to easily add your own features.
|
There's also a full-featured plugin framework, allowing you to easily add your own features.
|
||||||
Finally, Etherpad Lite comes with translations into tons of different languages!
|
Finally, Etherpad Lite comes with translations into tons of different languages!
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ You know all this and just want to know how you can help?
|
||||||
|
|
||||||
Look at the [TODO list](https://github.com/ether/etherpad-lite/wiki/TODO) and our [Issue tracker](https://github.com/ether/etherpad-lite/issues). (Please consider using [jshint](http://www.jshint.com/about/), if you plan to contribute code.)
|
Look at the [TODO list](https://github.com/ether/etherpad-lite/wiki/TODO) and our [Issue tracker](https://github.com/ether/etherpad-lite/issues). (Please consider using [jshint](http://www.jshint.com/about/), if you plan to contribute code.)
|
||||||
|
|
||||||
Also, and most importantly, read our [**Developer Guidelines**](https://github.com/ether/etherpad-lite/wiki/Developer-Guidelines), really!
|
Also, and most importantly, read our [**Developer Guidelines**](https://github.com/ether/etherpad-lite/blob/master/CONTRIBUTING.md), really!
|
||||||
|
|
||||||
# Get in touch
|
# Get in touch
|
||||||
Join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) and make some noise on our freenode irc channel [#etherpad-lite-dev](http://webchat.freenode.net?channels=#etherpad-lite-dev)!
|
Join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) and make some noise on our freenode irc channel [#etherpad-lite-dev](http://webchat.freenode.net?channels=#etherpad-lite-dev)!
|
||||||
|
@ -122,6 +122,7 @@ Join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) and mak
|
||||||
# Donate!
|
# Donate!
|
||||||
* [Flattr] (http://flattr.com/thing/71378/Etherpad-Foundation)
|
* [Flattr] (http://flattr.com/thing/71378/Etherpad-Foundation)
|
||||||
* Paypal - Press the donate button on [etherpad.org](http://etherpad.org)
|
* Paypal - Press the donate button on [etherpad.org](http://etherpad.org)
|
||||||
|
* [Bitcoin] (https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a)
|
||||||
|
|
||||||
# License
|
# License
|
||||||
[Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html)
|
[Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html)
|
||||||
|
|
63
bin/deletePad.js
Normal file
63
bin/deletePad.js
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
/*
|
||||||
|
A tool for deleting pads from the CLI, because sometimes a brick is required to fix a window.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(process.argv.length != 3)
|
||||||
|
{
|
||||||
|
console.error("Use: node deletePad.js $PADID");
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
//get the padID
|
||||||
|
var padId = process.argv[2];
|
||||||
|
|
||||||
|
var db, padManager, pad, settings;
|
||||||
|
var neededDBValues = ["pad:"+padId];
|
||||||
|
|
||||||
|
var npm = require("../src/node_modules/npm");
|
||||||
|
var async = require("../src/node_modules/async");
|
||||||
|
|
||||||
|
async.series([
|
||||||
|
// load npm
|
||||||
|
function(callback) {
|
||||||
|
npm.load({}, function(er) {
|
||||||
|
if(er)
|
||||||
|
{
|
||||||
|
console.error("Could not load NPM: " + er)
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
},
|
||||||
|
// load modules
|
||||||
|
function(callback) {
|
||||||
|
settings = require('../src/node/utils/Settings');
|
||||||
|
db = require('../src/node/db/DB');
|
||||||
|
callback();
|
||||||
|
},
|
||||||
|
// intallize the database
|
||||||
|
function (callback)
|
||||||
|
{
|
||||||
|
db.init(callback);
|
||||||
|
},
|
||||||
|
// delete the pad and it's links
|
||||||
|
function (callback)
|
||||||
|
{
|
||||||
|
padManager = require('../src/node/db/PadManager');
|
||||||
|
|
||||||
|
padManager.removePad(padId, function(err){
|
||||||
|
callback(err);
|
||||||
|
});
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
], function (err)
|
||||||
|
{
|
||||||
|
if(err) throw err;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
console.log("Finished deleting padId: "+padId);
|
||||||
|
process.exit();
|
||||||
|
}
|
||||||
|
});
|
|
@ -13,8 +13,8 @@ var padId = process.argv[2];
|
||||||
var db, dirty, padManager, pad, settings;
|
var db, dirty, padManager, pad, settings;
|
||||||
var neededDBValues = ["pad:"+padId];
|
var neededDBValues = ["pad:"+padId];
|
||||||
|
|
||||||
var npm = require("../src/node_modules/npm");
|
var npm = require("../node_modules/ep_etherpad-lite/node_modules/npm");
|
||||||
var async = require("../src/node_modules/async");
|
var async = require("../node_modules/ep_etherpad-lite/node_modules/async");
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
// load npm
|
// load npm
|
||||||
|
@ -33,9 +33,10 @@ async.series([
|
||||||
},
|
},
|
||||||
// load modules
|
// load modules
|
||||||
function(callback) {
|
function(callback) {
|
||||||
settings = require('../src/node/utils/Settings');
|
settings = require('../node_modules/ep_etherpad-lite/node/utils/Settings');
|
||||||
db = require('../src/node/db/DB');
|
db = require('../node_modules/ep_etherpad-lite/node/db/DB');
|
||||||
dirty = require("../src/node_modules/ueberDB/node_modules/dirty")(padId + ".db");
|
dirty = require("../node_modules/ep_etherpad-lite/node_modules/ueberDB/node_modules/dirty")(padId + ".db");
|
||||||
|
callback();
|
||||||
},
|
},
|
||||||
//intallize the database
|
//intallize the database
|
||||||
function (callback)
|
function (callback)
|
||||||
|
@ -45,7 +46,7 @@ async.series([
|
||||||
//get the pad
|
//get the pad
|
||||||
function (callback)
|
function (callback)
|
||||||
{
|
{
|
||||||
padManager = require('../node/db/PadManager');
|
padManager = require('../node_modules/ep_etherpad-lite/node/db/PadManager');
|
||||||
|
|
||||||
padManager.getPad(padId, function(err, _pad)
|
padManager.getPad(padId, function(err, _pad)
|
||||||
{
|
{
|
||||||
|
@ -82,7 +83,10 @@ async.series([
|
||||||
db.db.db.wrappedDB.get(dbkey, function(err, dbvalue)
|
db.db.db.wrappedDB.get(dbkey, function(err, dbvalue)
|
||||||
{
|
{
|
||||||
if(err) { callback(err); return}
|
if(err) { callback(err); return}
|
||||||
dbvalue=JSON.parse(dbvalue);
|
|
||||||
|
if(dbvalue && typeof dbvalue != 'object'){
|
||||||
|
dbvalue=JSON.parse(dbvalue); // if its not json then parse it as json
|
||||||
|
}
|
||||||
|
|
||||||
dirty.set(dbkey, dbvalue, callback);
|
dirty.set(dbkey, dbvalue, callback);
|
||||||
});
|
});
|
||||||
|
|
|
@ -63,7 +63,7 @@ if [ ! -f $settings ]; then
|
||||||
cp settings.json.template $settings || exit 1
|
cp settings.json.template $settings || exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "Ensure that all dependencies are up to date..."
|
echo "Ensure that all dependencies are up to date... If this is the first time you have run Etherpad please be patient."
|
||||||
(
|
(
|
||||||
mkdir -p node_modules
|
mkdir -p node_modules
|
||||||
cd node_modules
|
cd node_modules
|
||||||
|
@ -77,7 +77,7 @@ echo "Ensure that all dependencies are up to date..."
|
||||||
|
|
||||||
echo "Ensure jQuery is downloaded and up to date..."
|
echo "Ensure jQuery is downloaded and up to date..."
|
||||||
DOWNLOAD_JQUERY="true"
|
DOWNLOAD_JQUERY="true"
|
||||||
NEEDED_VERSION="1.7.1"
|
NEEDED_VERSION="1.9.1"
|
||||||
if [ -f "src/static/js/jquery.js" ]; then
|
if [ -f "src/static/js/jquery.js" ]; then
|
||||||
if [ $(uname) = "SunOS" ]; then
|
if [ $(uname) = "SunOS" ]; then
|
||||||
VERSION=$(cat src/static/js/jquery.js | head -n 3 | ggrep -o "v[0-9]\.[0-9]\(\.[0-9]\)\?");
|
VERSION=$(cat src/static/js/jquery.js | head -n 3 | ggrep -o "v[0-9]\.[0-9]\(\.[0-9]\)\?");
|
||||||
|
|
|
@ -12,7 +12,7 @@ set check_version="if(['6','8'].indexOf(process.version.split('.')[1].toString()
|
||||||
cmd /C node -e %check_version% || exit /B 1
|
cmd /C node -e %check_version% || exit /B 1
|
||||||
|
|
||||||
echo _
|
echo _
|
||||||
echo Installing etherpad-lite and dependencies...
|
echo Ensure that all dependencies are up to date... If this is the first time you have run Etherpad please be patient.
|
||||||
cmd /C npm install src/ --loglevel warn || exit /B 1
|
cmd /C npm install src/ --loglevel warn || exit /B 1
|
||||||
|
|
||||||
echo _
|
echo _
|
||||||
|
@ -36,4 +36,4 @@ IF NOT EXIST settings.json (
|
||||||
)
|
)
|
||||||
|
|
||||||
echo _
|
echo _
|
||||||
echo Installed Etherpad-lite! To run Etherpad type start.bat
|
echo Installed Etherpad! To run Etherpad type start.bat
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
This is the new load testing file: https://bitbucket.org/rbraakman/etherpad-stresstest
|
||||||
|
|
||||||
|
BELOW is the original load testing file.
|
||||||
|
|
||||||
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:
|
||||||
|
|
|
@ -129,6 +129,11 @@ Things in context:
|
||||||
|
|
||||||
There doesn't appear to be any example available of this particular hook being used, but it gets fired after the editor is all set up.
|
There doesn't appear to be any example available of this particular hook being used, but it gets fired after the editor is all set up.
|
||||||
|
|
||||||
|
## postTimesliderInit
|
||||||
|
Called from: src/static/js/timeslider.js
|
||||||
|
|
||||||
|
There doesn't appear to be any example available of this particular hook being used, but it gets fired after the timeslider is all set up.
|
||||||
|
|
||||||
## userJoinOrUpdate
|
## userJoinOrUpdate
|
||||||
Called from: src/static/js/pad_userlist.js
|
Called from: src/static/js/pad_userlist.js
|
||||||
|
|
||||||
|
|
|
@ -61,7 +61,9 @@ Portal submits content into new blog post
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### API version
|
### API version
|
||||||
The latest version is `1.2`
|
The latest version is `1.2.7`
|
||||||
|
|
||||||
|
The current version can be queried via /api.
|
||||||
|
|
||||||
### Request Format
|
### Request Format
|
||||||
|
|
||||||
|
|
|
@ -105,3 +105,15 @@ Your plugin must also contain a [package definition file](http://npmjs.org/doc/j
|
||||||
|
|
||||||
## Templates
|
## Templates
|
||||||
If your plugin adds or modifies the front end HTML (e.g. adding buttons or changing their functions), you should put the necessary HTML code for such operations in `templates/`, in files of type ".ejs", since Etherpad-Lite uses EJS for HTML templating. See the following link for more information about EJS: <https://github.com/visionmedia/ejs>.
|
If your plugin adds or modifies the front end HTML (e.g. adding buttons or changing their functions), you should put the necessary HTML code for such operations in `templates/`, in files of type ".ejs", since Etherpad-Lite uses EJS for HTML templating. See the following link for more information about EJS: <https://github.com/visionmedia/ejs>.
|
||||||
|
|
||||||
|
## Writing and running front-end tests for your plugin
|
||||||
|
|
||||||
|
Etherpad allows you to easily create front-end tests for plugins.
|
||||||
|
|
||||||
|
1. Create a new folder
|
||||||
|
```
|
||||||
|
%your_plugin%/static/tests/frontend/specs
|
||||||
|
```
|
||||||
|
2. Put your spec file in here (Example spec files are visible in %etherpad_root_folder%/frontend/tests/specs)
|
||||||
|
|
||||||
|
3. Visit http://yourserver.com/frontend/tests your front-end tests will run.
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
// Name your instance!
|
// Name your instance!
|
||||||
"title": "Etherpad Lite",
|
"title": "Etherpad",
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -15,6 +15,10 @@
|
||||||
"ip": "0.0.0.0",
|
"ip": "0.0.0.0",
|
||||||
"port" : 9001,
|
"port" : 9001,
|
||||||
|
|
||||||
|
// Session Key, used for reconnecting user sessions
|
||||||
|
// Set this to a secure string at least 10 characters long. Do not share this value.
|
||||||
|
"sessionKey" : "",
|
||||||
|
|
||||||
/*
|
/*
|
||||||
// Node native SSL support
|
// Node native SSL support
|
||||||
// this is disabled by default
|
// this is disabled by default
|
||||||
|
@ -47,15 +51,8 @@
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//Logging configuration. See log4js documentation for further information
|
|
||||||
// https://github.com/nomiddlename/log4js-node
|
|
||||||
"logconfig" :
|
|
||||||
{ "appenders": [
|
|
||||||
{ "type": "console" }
|
|
||||||
] },
|
|
||||||
|
|
||||||
//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!\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,
|
||||||
|
@ -97,9 +94,50 @@
|
||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// restrict socket.io transport methods
|
||||||
|
"socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"],
|
||||||
|
|
||||||
/* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */
|
/* The log level we are using, can be: DEBUG, INFO, WARN, ERROR */
|
||||||
"loglevel": "INFO",
|
"loglevel": "INFO",
|
||||||
|
|
||||||
// restrict socket.io transport methods
|
//Logging configuration. See log4js documentation for further information
|
||||||
"socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"]
|
// https://github.com/nomiddlename/log4js-node
|
||||||
|
// You can add as many appenders as you want here:
|
||||||
|
"logconfig" :
|
||||||
|
{ "appenders": [
|
||||||
|
{ "type": "console"
|
||||||
|
//, "category": "access"// only logs pad access
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
, { "type": "file"
|
||||||
|
, "filename": "your-log-file-here.log"
|
||||||
|
, "maxLogSize": 1024
|
||||||
|
, "backups": 3 // how many log files there're gonna be at max
|
||||||
|
//, "category": "test" // only log a specific category
|
||||||
|
}*/
|
||||||
|
/*
|
||||||
|
, { "type": "logLevelFilter"
|
||||||
|
, "level": "warn" // filters out all log messages that have a lower level than "error"
|
||||||
|
, "appender":
|
||||||
|
{ Use whatever appender you want here }
|
||||||
|
}*/
|
||||||
|
/*
|
||||||
|
, { "type": "logLevelFilter"
|
||||||
|
, "level": "error" // filters out all log messages that have a lower level than "error"
|
||||||
|
, "appender":
|
||||||
|
{ "type": "smtp"
|
||||||
|
, "subject": "An error occured in your EPL instance!"
|
||||||
|
, "recipients": "bar@blurdybloop.com, baz@blurdybloop.com"
|
||||||
|
, "sendInterval": 60*5 // in secs -- will buffer log messages; set to 0 to send a mail for every message
|
||||||
|
, "transport": "SMTP", "SMTP": { // see https://github.com/andris9/Nodemailer#possible-transport-methods
|
||||||
|
"host": "smtp.example.com", "port": 465,
|
||||||
|
"secureConnection": true,
|
||||||
|
"auth": {
|
||||||
|
"user": "foo@example.com",
|
||||||
|
"pass": "bar_foo"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
] }
|
||||||
}
|
}
|
||||||
|
|
1
src/README.md
Normal file
1
src/README.md
Normal file
|
@ -0,0 +1 @@
|
||||||
|
Ignore this file and see the file in the base installation folder
|
|
@ -2,26 +2,60 @@
|
||||||
"@metadata": {
|
"@metadata": {
|
||||||
"authors": [
|
"authors": [
|
||||||
"Bellayet",
|
"Bellayet",
|
||||||
"Nasir8891"
|
"Nasir8891",
|
||||||
|
"Sankarshan"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"index.newPad": "\u09a8\u09a4\u09c1\u09a8 \u09aa\u09cd\u09af\u09be\u09a1",
|
"index.newPad": "\u09a8\u09a4\u09c1\u09a8 \u09aa\u09cd\u09af\u09be\u09a1",
|
||||||
"index.createOpenPad": "\u0985\u09a5\u09ac\u09be \u09a8\u09be\u09ae \u09b2\u09bf\u0996\u09c7 \u09aa\u09cd\u09af\u09be\u09a1 \u0996\u09c1\u09b2\u09c1\u09a8\/\u09a4\u09c8\u09b0\u09c0 \u0995\u09b0\u09c1\u09a8:",
|
"index.createOpenPad": "\u0985\u09a5\u09ac\u09be \u09a8\u09be\u09ae \u09b2\u09bf\u0996\u09c7 \u09aa\u09cd\u09af\u09be\u09a1 \u0996\u09c1\u09b2\u09c1\u09a8\/\u09a4\u09c8\u09b0\u09c0 \u0995\u09b0\u09c1\u09a8:",
|
||||||
"pad.toolbar.bold.title": "\u0997\u09be\u09a1\u09bc \u0995\u09b0\u09be (Ctrl-B)",
|
"pad.toolbar.bold.title": "\u0997\u09be\u09a1\u09bc \u0995\u09b0\u09be (Ctrl-B)",
|
||||||
"pad.toolbar.italic.title": "\u09ac\u09be\u0981\u0995\u09be \u0995\u09b0\u09be (Ctrl-I)",
|
"pad.toolbar.italic.title": "\u09ac\u09be\u0981\u0995\u09be \u0995\u09b0\u09be (Ctrl-I)",
|
||||||
|
"pad.toolbar.underline.title": "\u0986\u09a8\u09cd\u09a1\u09be\u09b0\u09b2\u09be\u0987\u09a8 (Ctrl-U)",
|
||||||
|
"pad.toolbar.ol.title": "\u09b8\u09be\u09b0\u09bf\u09ac\u09a6\u09cd\u09a7 \u09a4\u09be\u09b2\u09bf\u0995\u09be",
|
||||||
"pad.toolbar.indent.title": "\u09aa\u09cd\u09b0\u09be\u09a8\u09cd\u09a4\u09bf\u0995\u0995\u09b0\u09a3",
|
"pad.toolbar.indent.title": "\u09aa\u09cd\u09b0\u09be\u09a8\u09cd\u09a4\u09bf\u0995\u0995\u09b0\u09a3",
|
||||||
|
"pad.toolbar.unindent.title": "\u0986\u0989\u099f\u09a1\u09c7\u09a8\u09cd\u099f",
|
||||||
|
"pad.toolbar.undo.title": "\u09ac\u09be\u09a4\u09bf\u09b2 \u0995\u09b0\u09c1\u09a8 (Ctrl-Z)",
|
||||||
|
"pad.toolbar.redo.title": "\u09aa\u09c1\u09a8\u09b0\u09be\u09af\u09bc \u0995\u09b0\u09c1\u09a8 (Ctrl-Y)",
|
||||||
|
"pad.toolbar.clearAuthorship.title": "\u0995\u09c3\u09a4\u09bf \u09b0\u0982 \u09aa\u09b0\u09bf\u09b7\u09cd\u0995\u09be\u09b0 \u0995\u09b0\u09c1\u09a8",
|
||||||
|
"pad.toolbar.timeslider.title": "\u099f\u09be\u0987\u09ae\u09b8\u09cd\u09b2\u09be\u0987\u09a1\u09be\u09b0",
|
||||||
|
"pad.toolbar.savedRevision.title": "\u09b8\u0982\u09b8\u09cd\u0995\u09b0\u09a3 \u09b8\u0982\u09b0\u0995\u09cd\u09b7\u09a3 \u0995\u09b0\u09c1\u09a8",
|
||||||
"pad.toolbar.settings.title": "\u09b8\u09c7\u099f\u09bf\u0982",
|
"pad.toolbar.settings.title": "\u09b8\u09c7\u099f\u09bf\u0982",
|
||||||
|
"pad.toolbar.embed.title": "\u098f\u0987 \u09aa\u09cd\u09af\u09be\u09a1-\u099f\u09bf \u098f\u09ae\u09cd\u09ac\u09c7\u09a1 \u0995\u09b0\u09c1\u09a8",
|
||||||
|
"pad.toolbar.showusers.title": "\u098f\u0987 \u09aa\u09cd\u09af\u09be\u09a1\u09c7\u09b0 \u09ac\u09cd\u09af\u09ac\u09b9\u09be\u09b0\u0995\u09be\u09b0\u09c0\u09a6\u09c7\u09b0 \u09a6\u09c7\u0996\u09be\u09a8",
|
||||||
"pad.colorpicker.save": "\u09b8\u0982\u09b0\u0995\u09cd\u09b7\u09a3",
|
"pad.colorpicker.save": "\u09b8\u0982\u09b0\u0995\u09cd\u09b7\u09a3",
|
||||||
"pad.colorpicker.cancel": "\u09ac\u09be\u09a4\u09bf\u09b2",
|
"pad.colorpicker.cancel": "\u09ac\u09be\u09a4\u09bf\u09b2",
|
||||||
"pad.loading": "\u09b2\u09cb\u09a1\u09bf\u0982...",
|
"pad.loading": "\u09b2\u09cb\u09a1\u09bf\u0982...",
|
||||||
|
"pad.passwordRequired": "\u098f\u0987 \u09aa\u09cd\u09af\u09be\u09a1-\u099f\u09bf \u09a6\u09c7\u0996\u09be\u09b0 \u099c\u09a8\u09cd\u09af \u0986\u09aa\u09a8\u09be\u0995\u09c7 \u09aa\u09be\u09b8\u0993\u09af\u09bc\u09be\u09b0\u09cd\u09a1 \u09ac\u09cd\u09af\u09ac\u09b9\u09be\u09b0 \u0995\u09b0\u09a4\u09c7 \u09b9\u09ac\u09c7",
|
||||||
|
"pad.permissionDenied": "\u09a6\u09c1\u0983\u0996\u09bf\u09a4, \u098f \u09aa\u09cd\u09af\u09be\u09a1-\u099f\u09bf \u09a6\u09c7\u0996\u09be\u09b0 \u0985\u09a7\u09bf\u0995\u09be\u09b0 \u0986\u09aa\u09a8\u09be\u09b0 \u09a8\u09c7\u0987",
|
||||||
|
"pad.wrongPassword": "\u0986\u09aa\u09a8\u09be\u09b0 \u09aa\u09be\u09b8\u0993\u09af\u09bc\u09be\u09b0\u09cd\u09a1 \u09b8\u09a0\u09bf\u0995 \u09a8\u09af\u09bc",
|
||||||
|
"pad.settings.padSettings": "\u09aa\u09cd\u09af\u09be\u09a1\u09c7\u09b0 \u09b8\u09cd\u09a5\u09be\u09aa\u09a8",
|
||||||
|
"pad.settings.myView": "\u0986\u09ae\u09be\u09b0 \u09a6\u09c3\u09b6\u09cd\u09af",
|
||||||
|
"pad.settings.stickychat": "\u099a\u09cd\u09af\u09be\u099f \u09b8\u0995\u09cd\u09b0\u09c0\u09a8\u09c7 \u09aa\u09cd\u09b0\u09a6\u09b0\u09cd\u09b6\u09a8 \u0995\u09b0\u09be \u09b9\u09ac\u09c7",
|
||||||
|
"pad.settings.colorcheck": "\u09b2\u09c7\u0996\u0995\u09a6\u09c7\u09b0 \u09a8\u09bf\u099c\u09b8\u09cd\u09ac \u09a8\u09bf\u09b0\u09cd\u09ac\u09be\u099a\u09bf\u09a4 \u09b0\u0982",
|
||||||
|
"pad.settings.linenocheck": "\u09b2\u09be\u0987\u09a8 \u09a8\u09ae\u09cd\u09ac\u09b0",
|
||||||
|
"pad.settings.fontType": "\u09ab\u09a8\u09cd\u099f-\u098f\u09b0 \u09aa\u09cd\u09b0\u0995\u09be\u09b0:",
|
||||||
"pad.settings.fontType.normal": "\u09b8\u09be\u09a7\u09be\u09b0\u09a3",
|
"pad.settings.fontType.normal": "\u09b8\u09be\u09a7\u09be\u09b0\u09a3",
|
||||||
|
"pad.settings.fontType.monospaced": "Monospace",
|
||||||
|
"pad.settings.globalView": "\u09b8\u09b0\u09cd\u09ac\u09ac\u09cd\u09af\u09be\u09aa\u09c0 \u09a6\u09c3\u09b6\u09cd\u09af",
|
||||||
"pad.settings.language": "\u09ad\u09be\u09b7\u09be:",
|
"pad.settings.language": "\u09ad\u09be\u09b7\u09be:",
|
||||||
|
"pad.importExport.import_export": "\u0987\u09ae\u09cd\u09aa\u09cb\u09b0\u099f\/\u098f\u0995\u09cd\u09b8\u09aa\u09cb\u09b0\u09cd\u099f",
|
||||||
|
"pad.importExport.import": "\u0995\u09cb\u09a8 \u099f\u09c7\u0995\u09cd\u09b8\u099f \u09ab\u09be\u0987\u09b2 \u09ac\u09be \u09a1\u0995\u09c1\u09ae\u09c7\u09a8\u09cd\u099f \u0986\u09aa\u09b2\u09cb\u09a1 \u0995\u09b0\u09c1\u09a8",
|
||||||
|
"pad.importExport.importSuccessful": "\u09b8\u09ab\u09b2!",
|
||||||
"pad.importExport.export": "\u098f\u0987 \u09aa\u09cd\u09af\u09be\u09a1\u099f\u09bf \u098f\u0995\u09cd\u09b8\u09aa\u09cb\u09b0\u09cd\u099f \u0995\u09b0\u09c1\u09a8",
|
"pad.importExport.export": "\u098f\u0987 \u09aa\u09cd\u09af\u09be\u09a1\u099f\u09bf \u098f\u0995\u09cd\u09b8\u09aa\u09cb\u09b0\u09cd\u099f \u0995\u09b0\u09c1\u09a8",
|
||||||
"pad.importExport.exporthtml": "\u098f\u0987\u099a\u099f\u09bf\u098f\u09ae\u098f\u09b2",
|
"pad.importExport.exporthtml": "\u098f\u0987\u099a\u099f\u09bf\u098f\u09ae\u098f\u09b2",
|
||||||
"pad.importExport.exportplain": "\u09b8\u09be\u09a7\u09be\u09b0\u09a3 \u09b2\u09c7\u0996\u09be",
|
"pad.importExport.exportplain": "\u09b8\u09be\u09a7\u09be\u09b0\u09a3 \u09b2\u09c7\u0996\u09be",
|
||||||
"pad.importExport.exportword": "\u09ae\u09be\u0987\u0995\u09cd\u09b0\u09cb\u09b8\u09ab\u099f \u0993\u09af\u09bc\u09be\u09b0\u09cd\u09a1",
|
"pad.importExport.exportword": "\u09ae\u09be\u0987\u0995\u09cd\u09b0\u09cb\u09b8\u09ab\u099f \u0993\u09af\u09bc\u09be\u09b0\u09cd\u09a1",
|
||||||
"pad.importExport.exportpdf": "\u09aa\u09bf\u09a1\u09bf\u098f\u09ab",
|
"pad.importExport.exportpdf": "\u09aa\u09bf\u09a1\u09bf\u098f\u09ab",
|
||||||
"pad.importExport.exportopen": "\u0993\u09a1\u09bf\u098f\u09ab (\u0993\u09aa\u09c7\u09a8 \u09a1\u0995\u09c1\u09ae\u09c7\u09a8\u09cd\u099f \u09ab\u09b0\u09ae\u09cd\u09af\u09be\u099f)",
|
"pad.importExport.exportopen": "\u0993\u09a1\u09bf\u098f\u09ab (\u0993\u09aa\u09c7\u09a8 \u09a1\u0995\u09c1\u09ae\u09c7\u09a8\u09cd\u099f \u09ab\u09b0\u09ae\u09cd\u09af\u09be\u099f)",
|
||||||
|
"pad.importExport.exportdokuwiki": "DokuWiki",
|
||||||
|
"pad.modals.connected": "\u09af\u09cb\u0997\u09be\u09af\u09cb\u0997 \u09b8\u09ab\u09b2",
|
||||||
|
"pad.modals.reconnecting": "\u0986\u09aa\u09a8\u09be\u09b0 \u09aa\u09cd\u09af\u09be\u09a1\u09c7\u09b0 \u09b8\u09be\u09a5\u09c7 \u09b8\u0982\u09af\u09cb\u0997\u09b8\u09cd\u09a5\u09be\u09aa\u09a8 \u0995\u09b0\u09be \u09b9\u099a\u09cd\u099b\u09c7..",
|
||||||
|
"pad.modals.forcereconnect": "\u09aa\u09c1\u09a8\u09b0\u09be\u09af\u09bc \u09b8\u0982\u09af\u09cb\u0997\u09b8\u09cd\u09a5\u09be\u09aa\u09a8\u09c7\u09b0 \u099a\u09c7\u09b7\u09cd\u099f\u09be",
|
||||||
|
"pad.modals.userdup": "\u0985\u09a8\u09cd\u09af \u0989\u0987\u09a8\u09cd\u09a1\u09cb-\u09a4\u09c7 \u0996\u09cb\u09b2\u09be \u09b9\u09af\u09bc\u09c7\u099b\u09c7",
|
||||||
|
"pad.modals.unauth": "\u0986\u09aa\u09a8\u09be\u09b0 \u0985\u09a7\u09bf\u0995\u09be\u09b0 \u09a8\u09c7\u0987",
|
||||||
|
"pad.modals.looping": "\u09af\u09cb\u0997\u09be\u09af\u09cb\u0997 \u09ac\u09bf\u099a\u09cd\u099b\u09bf\u09a8\u09cd\u09a8",
|
||||||
|
"pad.modals.initsocketfail": "\u09b8\u09be\u09b0\u09cd\u09ad\u09be\u09b0-\u098f\u09b0 \u09b8\u09be\u09a5\u09c7 \u09af\u09cb\u0997\u09be\u09af\u09cb\u0997 \u0995\u09b0\u09a4\u09c7 \u0985\u09b8\u0995\u09cd\u09b7\u09ae\u0964",
|
||||||
|
"pad.modals.slowcommit": "\u09af\u09cb\u0997\u09be\u09af\u09cb\u0997 \u09ac\u09bf\u099a\u09cd\u099b\u09bf\u09a8\u09cd\u09a8",
|
||||||
"pad.modals.deleted": "\u0985\u09aa\u09b8\u09be\u09b0\u09bf\u09a4\u0964",
|
"pad.modals.deleted": "\u0985\u09aa\u09b8\u09be\u09b0\u09bf\u09a4\u0964",
|
||||||
"pad.modals.deleted.explanation": "\u098f\u0987 \u09aa\u09cd\u09af\u09be\u09a1\u099f\u09bf \u0985\u09aa\u09b8\u09be\u09b0\u09a3 \u0995\u09b0\u09be \u09b9\u09af\u09bc\u09c7\u099b\u09c7\u0964",
|
"pad.modals.deleted.explanation": "\u098f\u0987 \u09aa\u09cd\u09af\u09be\u09a1\u099f\u09bf \u0985\u09aa\u09b8\u09be\u09b0\u09a3 \u0995\u09b0\u09be \u09b9\u09af\u09bc\u09c7\u099b\u09c7\u0964",
|
||||||
"pad.modals.disconnected.explanation": "\u09b8\u09be\u09b0\u09cd\u09ad\u09be\u09b0\u09c7\u09b0 \u09b8\u09be\u09a5\u09c7 \u09af\u09cb\u0997\u09be\u09af\u09cb\u0997 \u0995\u09b0\u09be \u09af\u09be\u099a\u09cd\u099b\u09c7 \u09a8\u09be",
|
"pad.modals.disconnected.explanation": "\u09b8\u09be\u09b0\u09cd\u09ad\u09be\u09b0\u09c7\u09b0 \u09b8\u09be\u09a5\u09c7 \u09af\u09cb\u0997\u09be\u09af\u09cb\u0997 \u0995\u09b0\u09be \u09af\u09be\u099a\u09cd\u099b\u09c7 \u09a8\u09be",
|
||||||
|
@ -34,6 +68,7 @@
|
||||||
"timeslider.toolbar.authors": "\u09b2\u09c7\u0996\u0995\u0997\u09a3:",
|
"timeslider.toolbar.authors": "\u09b2\u09c7\u0996\u0995\u0997\u09a3:",
|
||||||
"timeslider.toolbar.authorsList": "\u0995\u09cb\u09a8\u09cb \u09b2\u09c7\u0996\u0995 \u09a8\u09c7\u0987",
|
"timeslider.toolbar.authorsList": "\u0995\u09cb\u09a8\u09cb \u09b2\u09c7\u0996\u0995 \u09a8\u09c7\u0987",
|
||||||
"timeslider.exportCurrent": "\u09ac\u09b0\u09cd\u09a4\u09ae\u09be\u09a8 \u09b8\u0982\u09b8\u09cd\u0995\u09b0\u09a3\u099f\u09bf \u098f\u0995\u09cd\u09b8\u09aa\u09cb\u09b0\u09cd\u099f \u0995\u09b0\u09c1\u09a8:",
|
"timeslider.exportCurrent": "\u09ac\u09b0\u09cd\u09a4\u09ae\u09be\u09a8 \u09b8\u0982\u09b8\u09cd\u0995\u09b0\u09a3\u099f\u09bf \u098f\u0995\u09cd\u09b8\u09aa\u09cb\u09b0\u09cd\u099f \u0995\u09b0\u09c1\u09a8:",
|
||||||
|
"timeslider.dateformat": "{{month}}\/{{day}}\/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
||||||
"timeslider.month.january": "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09bf",
|
"timeslider.month.january": "\u099c\u09be\u09a8\u09c1\u09af\u09bc\u09be\u09b0\u09bf",
|
||||||
"timeslider.month.february": "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09af\u09bc\u09be\u09b0\u09bf",
|
"timeslider.month.february": "\u09ab\u09c7\u09ac\u09cd\u09b0\u09c1\u09af\u09bc\u09be\u09b0\u09bf",
|
||||||
"timeslider.month.march": "\u09ae\u09be\u09b0\u09cd\u099a",
|
"timeslider.month.march": "\u09ae\u09be\u09b0\u09cd\u099a",
|
||||||
|
@ -45,5 +80,12 @@
|
||||||
"timeslider.month.september": "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0",
|
"timeslider.month.september": "\u09b8\u09c7\u09aa\u09cd\u099f\u09c7\u09ae\u09cd\u09ac\u09b0",
|
||||||
"timeslider.month.october": "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0",
|
"timeslider.month.october": "\u0985\u0995\u09cd\u099f\u09cb\u09ac\u09b0",
|
||||||
"timeslider.month.november": "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0",
|
"timeslider.month.november": "\u09a8\u09ad\u09c7\u09ae\u09cd\u09ac\u09b0",
|
||||||
"timeslider.month.december": "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0"
|
"timeslider.month.december": "\u09a1\u09bf\u09b8\u09c7\u09ae\u09cd\u09ac\u09b0",
|
||||||
|
"pad.userlist.entername": "\u0986\u09aa\u09a8\u09be\u09b0 \u09a8\u09be\u09ae",
|
||||||
|
"pad.userlist.unnamed": "\u0995\u09cb\u09a8 \u09a8\u09be\u09ae \u09a8\u09bf\u09b0\u09cd\u09ac\u09be\u099a\u09a8 \u0995\u09b0\u09be \u09b9\u09af\u09bc\u09a8\u09bf",
|
||||||
|
"pad.userlist.guest": "\u0985\u09a4\u09bf\u09a5\u09bf",
|
||||||
|
"pad.userlist.approve": "\u0985\u09a8\u09c1\u09ae\u09cb\u09a6\u09bf\u09a4",
|
||||||
|
"pad.impexp.importbutton": "\u098f\u0996\u09a8 \u0987\u09ae\u09cd\u09aa\u09cb\u09b0\u09cd\u099f \u0995\u09b0\u09c1\u09a8",
|
||||||
|
"pad.impexp.importing": "\u0987\u09ae\u09cd\u09aa\u09cb\u09b0\u09cd\u099f \u099a\u09b2\u099b\u09c7...",
|
||||||
|
"pad.impexp.importfailed": "\u0987\u09ae\u09cd\u09aa\u09cb\u09b0\u09cd\u099f \u0985\u09b8\u0995\u09cd\u09b7\u09ae"
|
||||||
}
|
}
|
123
src/locales/br.json
Normal file
123
src/locales/br.json
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
{
|
||||||
|
"@metadata": {
|
||||||
|
"authors": [
|
||||||
|
"Fohanno",
|
||||||
|
"Fulup",
|
||||||
|
"Gwenn-Ael",
|
||||||
|
"Y-M D"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"index.newPad": "Pad nevez",
|
||||||
|
"index.createOpenPad": "pe kroui\u00f1\/digeri\u00f1 ur pad gant an anv :",
|
||||||
|
"pad.toolbar.bold.title": "Tev (Ctrl-B)",
|
||||||
|
"pad.toolbar.italic.title": "Italek (Ctrl-I)",
|
||||||
|
"pad.toolbar.underline.title": "Islinenna\u00f1 (Ctrl-U)",
|
||||||
|
"pad.toolbar.strikethrough.title": "Barrennet",
|
||||||
|
"pad.toolbar.ol.title": "Roll urzhiet",
|
||||||
|
"pad.toolbar.ul.title": "Roll en dizurzh",
|
||||||
|
"pad.toolbar.indent.title": "Endanta\u00f1",
|
||||||
|
"pad.toolbar.unindent.title": "Diendanta\u00f1",
|
||||||
|
"pad.toolbar.undo.title": "Dizober (Ktrl-Z)",
|
||||||
|
"pad.toolbar.redo.title": "Adober (Ktrl-Y)",
|
||||||
|
"pad.toolbar.clearAuthorship.title": "Diverka\u00f1 al livio\u00f9 oc'h anaout an aozerien",
|
||||||
|
"pad.toolbar.import_export.title": "Enporzhia\u00f1\/Ezporzhia\u00f1 eus\/war-zu ur furmad restr dishe\u00f1vel",
|
||||||
|
"pad.toolbar.timeslider.title": "Istor dinamek",
|
||||||
|
"pad.toolbar.savedRevision.title": "Doareo\u00f9 enrollet",
|
||||||
|
"pad.toolbar.settings.title": "Arventenno\u00f9",
|
||||||
|
"pad.toolbar.embed.title": "Enframma\u00f1 ar pad-ma\u00f1",
|
||||||
|
"pad.toolbar.showusers.title": "Diskwelet implijerien ar Pad",
|
||||||
|
"pad.colorpicker.save": "Enrolla\u00f1",
|
||||||
|
"pad.colorpicker.cancel": "Nulla\u00f1",
|
||||||
|
"pad.loading": "O karga\u00f1...",
|
||||||
|
"pad.passwordRequired": "Ezhomm ho peus ur ger-tremen evit mont d'ar Pad-se",
|
||||||
|
"pad.permissionDenied": "\nN'oc'h ket aotreet da vont d'ar pad-ma\u00f1",
|
||||||
|
"pad.wrongPassword": "Fazius e oa ho ker-tremen",
|
||||||
|
"pad.settings.padSettings": "Arventenno\u00f9 Pad",
|
||||||
|
"pad.settings.myView": "Ma diskwel",
|
||||||
|
"pad.settings.stickychat": "Diskwel ar flap bepred",
|
||||||
|
"pad.settings.colorcheck": "Livio\u00f9 anaout",
|
||||||
|
"pad.settings.linenocheck": "Niverenno\u00f9 linenno\u00f9",
|
||||||
|
"pad.settings.fontType": "Seurt font :",
|
||||||
|
"pad.settings.fontType.normal": "Reizh",
|
||||||
|
"pad.settings.fontType.monospaced": "Monospas",
|
||||||
|
"pad.settings.globalView": "Gwel dre vras",
|
||||||
|
"pad.settings.language": "Yezh :",
|
||||||
|
"pad.importExport.import_export": "Enporzhia\u00f1\/Ezporzhia\u00f1",
|
||||||
|
"pad.importExport.import": "Enkarga\u00f1 un destenn pe ur restr",
|
||||||
|
"pad.importExport.importSuccessful": "Deuet eo ganeoc'h !",
|
||||||
|
"pad.importExport.export": "Ezporzhia\u00f1 ar pad brema\u00f1 evel :",
|
||||||
|
"pad.importExport.exporthtml": "HTML",
|
||||||
|
"pad.importExport.exportplain": "Testenn blaen",
|
||||||
|
"pad.importExport.exportword": "Microsoft Word",
|
||||||
|
"pad.importExport.exportpdf": "PDF",
|
||||||
|
"pad.importExport.exportopen": "ODF (Open Document Format)",
|
||||||
|
"pad.importExport.exportdokuwiki": "DokuWiki",
|
||||||
|
"pad.importExport.abiword.innerHTML": "Ne c'hallit ket emporzjia\u00f1 furmado\u00f9 testenno\u00f9 kriz pe html. Evit arc'hwelio\u00f9 enporzhia\u00f1 emdroetoc'h, staliit <a href=\"https:\/\/github.com\/ether\/etherpad-lite\/wiki\/How-to-enable-importing-and-exporting-different-file-formats-in-Ubuntu-or-OpenSuse-or-SLES-with-AbiWord\">abiword<\/a> mar plij.",
|
||||||
|
"pad.modals.connected": "Kevreet.",
|
||||||
|
"pad.modals.reconnecting": "Adkevrea\u00f1 war-zu ho pad...",
|
||||||
|
"pad.modals.forcereconnect": "Adkevrea\u00f1 dre heg",
|
||||||
|
"pad.modals.userdup": "Digor en ur prenestr all",
|
||||||
|
"pad.modals.userdup.explanation": "Digor eo ho pad, war a seblant, e meur a brenestr eus ho merdeer en urzhiataer-ma\u00f1.",
|
||||||
|
"pad.modals.userdup.advice": "Kevrea\u00f1 en ur implijout ar prenestr-ma\u00f1.",
|
||||||
|
"pad.modals.unauth": "N'eo ket aotreet",
|
||||||
|
"pad.modals.unauth.explanation": "Kemmet e vo hoc'h aotreo\u00f9 pa vo diskwelet ar bajenn.-ma\u00f1 Klaskit kevrea\u00f1 en-dro.",
|
||||||
|
"pad.modals.looping": "Digevreet.",
|
||||||
|
"pad.modals.looping.explanation": "Kudenno\u00f9 kehenti\u00f1 zo gant ar servijer sinkronelekaat.",
|
||||||
|
"pad.modals.looping.cause": "Posupl eo e vefe gwarezet ho kevreadur gant ur maltouter diembreget pe ur servijer proksi",
|
||||||
|
"pad.modals.initsocketfail": "Ne c'haller ket tizhout ar servijer.",
|
||||||
|
"pad.modals.initsocketfail.explanation": "Ne c'haller ket kevrea\u00f1 ouzh ar servijer sinkronelaat.",
|
||||||
|
"pad.modals.initsocketfail.cause": "Gallout a ra ar gudenn dont eus ho merdeer Web pe eus ho kevreadur Internet.",
|
||||||
|
"pad.modals.slowcommit": "Digevreet.",
|
||||||
|
"pad.modals.slowcommit.explanation": "Ne respont ket ar serveur.",
|
||||||
|
"pad.modals.slowcommit.cause": "Gallout a ra dont diwar kudenno\u00f9 kevrea\u00f1 gant ar rouedad.",
|
||||||
|
"pad.modals.deleted": "Dilamet.",
|
||||||
|
"pad.modals.deleted.explanation": "Lamet eo bet ar pad-ma\u00f1.",
|
||||||
|
"pad.modals.disconnected": "Digevreet oc'h bet.",
|
||||||
|
"pad.modals.disconnected.explanation": "Kollet eo bet ar c'hevreadur gant ar servijer",
|
||||||
|
"pad.modals.disconnected.cause": "Dizimplijadus eo ar servijer marteze. Kelaouit ac'hanomp ma pad ar gudenn.",
|
||||||
|
"pad.share": "Ranna\u00f1 ar pad-ma\u00f1.",
|
||||||
|
"pad.share.readonly": "Lenn hepken",
|
||||||
|
"pad.share.link": "Liamm",
|
||||||
|
"pad.share.emebdcode": "Enframma\u00f1 an URL",
|
||||||
|
"pad.chat": "Flap",
|
||||||
|
"pad.chat.title": "Digeri\u00f1 ar flap kevelet gant ar pad-ma\u00f1.",
|
||||||
|
"pad.chat.loadmessages": "Karga\u00f1 muioc'h a gemennadenno\u00f9",
|
||||||
|
"timeslider.pageTitle": "Istor dinamek eus {{appTitle}}",
|
||||||
|
"timeslider.toolbar.returnbutton": "Distrei\u00f1 d'ar pad-ma\u00f1.",
|
||||||
|
"timeslider.toolbar.authors": "Aozerien :",
|
||||||
|
"timeslider.toolbar.authorsList": "Aozer ebet",
|
||||||
|
"timeslider.toolbar.exportlink.title": "Ezporzhia\u00f1",
|
||||||
|
"timeslider.exportCurrent": "Ezporzhia\u00f1 an doare brema\u00f1 evel :",
|
||||||
|
"timeslider.version": "Stumm {{version}}",
|
||||||
|
"timeslider.saved": "Enrolla\u00f1 {{day}} {{month}} {{year}}",
|
||||||
|
"timeslider.dateformat": "{{month}}\/{{day}}\/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
||||||
|
"timeslider.month.january": "Genver",
|
||||||
|
"timeslider.month.february": "C'hwevrer",
|
||||||
|
"timeslider.month.march": "Meurzh",
|
||||||
|
"timeslider.month.april": "Ebrel",
|
||||||
|
"timeslider.month.may": "Mae",
|
||||||
|
"timeslider.month.june": "Mezheven",
|
||||||
|
"timeslider.month.july": "Gouere",
|
||||||
|
"timeslider.month.august": "Eost",
|
||||||
|
"timeslider.month.september": "Gwengolo",
|
||||||
|
"timeslider.month.october": "Here",
|
||||||
|
"timeslider.month.november": "Du",
|
||||||
|
"timeslider.month.december": "Kerzu",
|
||||||
|
"timeslider.unnamedauthor": "{{niver}} aozer dianav",
|
||||||
|
"timeslider.unnamedauthors": "Aozerien dianav",
|
||||||
|
"pad.savedrevs.marked": "Merket eo an adweladenn-ma\u00f1 evel adweladenn gwiriet",
|
||||||
|
"pad.userlist.entername": "Ebarzhit hoc'h anv",
|
||||||
|
"pad.userlist.unnamed": "dizanv",
|
||||||
|
"pad.userlist.guest": "Den pedet",
|
||||||
|
"pad.userlist.deny": "Nac'h",
|
||||||
|
"pad.userlist.approve": "Aproui\u00f1",
|
||||||
|
"pad.editbar.clearcolors": "Diverka\u00f1 al livio\u00f9 stag ouzh an aozerien en teul a-bezh ?",
|
||||||
|
"pad.impexp.importbutton": "Enporzhia\u00f1 brema\u00f1",
|
||||||
|
"pad.impexp.importing": "Oc'h enporzhia\u00f1...",
|
||||||
|
"pad.impexp.confirmimport": "Ma vez enporzhiet ur restr e vo diverket ar pezh zo en teul a-vrema\u00f1. Ha sur oc'h e fell deoc'h mont betek penn ?",
|
||||||
|
"pad.impexp.convertFailed": "N'eus ket bet gallet enporzhia\u00f1 ar restr. Ober gant ur furmad teul all pe eila\u00f1\/pega\u00f1 gant an dorn.",
|
||||||
|
"pad.impexp.uploadFailed": "C'hwitet eo bet an enporzhia\u00f1. Klaskit en-dro.",
|
||||||
|
"pad.impexp.importfailed": "C'hwitet eo an enporzhiadenn",
|
||||||
|
"pad.impexp.copypaste": "Eilit\/pegit, mar plij",
|
||||||
|
"pad.impexp.exportdisabled": "Diweredekaet eo ezporzhia\u00f1 d'ar furmad {{type}}. Kit e darempred gant merour ar reizhiad evit gouzout hiroc'h."
|
||||||
|
}
|
|
@ -17,7 +17,7 @@
|
||||||
"pad.toolbar.undo.title": "Desf\u00e9s (Ctrl-Z)",
|
"pad.toolbar.undo.title": "Desf\u00e9s (Ctrl-Z)",
|
||||||
"pad.toolbar.redo.title": "Ref\u00e9s (Ctrl-Y)",
|
"pad.toolbar.redo.title": "Ref\u00e9s (Ctrl-Y)",
|
||||||
"pad.toolbar.clearAuthorship.title": "Neteja els colors d'autoria",
|
"pad.toolbar.clearAuthorship.title": "Neteja els colors d'autoria",
|
||||||
"pad.toolbar.savedRevision.title": "Revisions desades",
|
"pad.toolbar.savedRevision.title": "Desa la revisi\u00f3",
|
||||||
"pad.toolbar.settings.title": "Configuraci\u00f3",
|
"pad.toolbar.settings.title": "Configuraci\u00f3",
|
||||||
"pad.toolbar.showusers.title": "Mostra els usuaris d\u2019aquest pad",
|
"pad.toolbar.showusers.title": "Mostra els usuaris d\u2019aquest pad",
|
||||||
"pad.colorpicker.save": "Desa",
|
"pad.colorpicker.save": "Desa",
|
||||||
|
@ -25,18 +25,25 @@
|
||||||
"pad.loading": "S'est\u00e0 carregant...",
|
"pad.loading": "S'est\u00e0 carregant...",
|
||||||
"pad.wrongPassword": "La contrasenya \u00e9s incorrecta",
|
"pad.wrongPassword": "La contrasenya \u00e9s incorrecta",
|
||||||
"pad.settings.myView": "La meva vista",
|
"pad.settings.myView": "La meva vista",
|
||||||
|
"pad.settings.stickychat": "Xateja sempre a la pantalla",
|
||||||
|
"pad.settings.colorcheck": "Colors d'autoria",
|
||||||
"pad.settings.linenocheck": "N\u00fameros de l\u00ednia",
|
"pad.settings.linenocheck": "N\u00fameros de l\u00ednia",
|
||||||
"pad.settings.fontType": "Tipus de lletra:",
|
"pad.settings.fontType": "Tipus de lletra:",
|
||||||
"pad.settings.fontType.normal": "Normal",
|
"pad.settings.fontType.normal": "Normal",
|
||||||
|
"pad.settings.fontType.monospaced": "D'amplada fixa",
|
||||||
"pad.settings.globalView": "Vista global",
|
"pad.settings.globalView": "Vista global",
|
||||||
"pad.settings.language": "Llengua:",
|
"pad.settings.language": "Llengua:",
|
||||||
"pad.importExport.import_export": "Importaci\u00f3\/exportaci\u00f3",
|
"pad.importExport.import_export": "Importaci\u00f3\/exportaci\u00f3",
|
||||||
"pad.importExport.import": "Puja qualsevol fitxer de text o document",
|
"pad.importExport.import": "Puja qualsevol fitxer de text o document",
|
||||||
"pad.importExport.exporthtml": "HTML",
|
"pad.importExport.exporthtml": "HTML",
|
||||||
"pad.importExport.exportplain": "Text net",
|
"pad.importExport.exportplain": "Text net",
|
||||||
|
"pad.importExport.exportpdf": "PDF",
|
||||||
|
"pad.importExport.exportopen": "ODF (Open Document Format)",
|
||||||
|
"pad.importExport.exportdokuwiki": "DokuWiki",
|
||||||
"pad.modals.connected": "Connectat.",
|
"pad.modals.connected": "Connectat.",
|
||||||
"pad.modals.forcereconnect": "For\u00e7a tornar a connectar",
|
"pad.modals.forcereconnect": "For\u00e7a tornar a connectar",
|
||||||
"pad.modals.unauth": "No autoritzat",
|
"pad.modals.unauth": "No autoritzat",
|
||||||
|
"pad.modals.unauth.explanation": "Els vostres permisos han canviat mentre es visualitzava la p\u00e0gina. Proveu de reconnectar-vos.",
|
||||||
"pad.modals.looping": "Desconnectat.",
|
"pad.modals.looping": "Desconnectat.",
|
||||||
"pad.modals.initsocketfail": "El servidor no \u00e9s accessible.",
|
"pad.modals.initsocketfail": "El servidor no \u00e9s accessible.",
|
||||||
"pad.modals.initsocketfail.explanation": "No s'ha pogut connectar amb el servidor de sincronitzaci\u00f3.",
|
"pad.modals.initsocketfail.explanation": "No s'ha pogut connectar amb el servidor de sincronitzaci\u00f3.",
|
||||||
|
@ -44,6 +51,7 @@
|
||||||
"pad.modals.slowcommit.explanation": "El servidor no respon.",
|
"pad.modals.slowcommit.explanation": "El servidor no respon.",
|
||||||
"pad.modals.deleted": "Suprimit.",
|
"pad.modals.deleted": "Suprimit.",
|
||||||
"pad.modals.disconnected": "Heu estat desconnectat.",
|
"pad.modals.disconnected": "Heu estat desconnectat.",
|
||||||
|
"pad.modals.disconnected.cause": "El servidor sembla que no est\u00e0 disponible. Notifiqueu-nos si continua passant.",
|
||||||
"pad.share.readonly": "Nom\u00e9s de lectura",
|
"pad.share.readonly": "Nom\u00e9s de lectura",
|
||||||
"pad.share.link": "Enlla\u00e7",
|
"pad.share.link": "Enlla\u00e7",
|
||||||
"pad.chat": "Xat",
|
"pad.chat": "Xat",
|
||||||
|
@ -52,6 +60,8 @@
|
||||||
"timeslider.toolbar.exportlink.title": "Exporta",
|
"timeslider.toolbar.exportlink.title": "Exporta",
|
||||||
"timeslider.exportCurrent": "Exporta la versi\u00f3 actual com a:",
|
"timeslider.exportCurrent": "Exporta la versi\u00f3 actual com a:",
|
||||||
"timeslider.version": "Versi\u00f3 {{version}}",
|
"timeslider.version": "Versi\u00f3 {{version}}",
|
||||||
|
"timeslider.saved": "Desat {{month}} {{day}}, {{year}}",
|
||||||
|
"timeslider.dateformat": "{{month}}\/{{day}}\/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
||||||
"timeslider.month.january": "Gener",
|
"timeslider.month.january": "Gener",
|
||||||
"timeslider.month.february": "Febrer",
|
"timeslider.month.february": "Febrer",
|
||||||
"timeslider.month.march": "Mar\u00e7",
|
"timeslider.month.march": "Mar\u00e7",
|
||||||
|
@ -69,9 +79,11 @@
|
||||||
"pad.userlist.guest": "Convidat",
|
"pad.userlist.guest": "Convidat",
|
||||||
"pad.userlist.deny": "Refusa",
|
"pad.userlist.deny": "Refusa",
|
||||||
"pad.userlist.approve": "Aprova",
|
"pad.userlist.approve": "Aprova",
|
||||||
|
"pad.editbar.clearcolors": "Voleu netejar els colors d'autor del document sencer?",
|
||||||
"pad.impexp.importbutton": "Importa ara",
|
"pad.impexp.importbutton": "Importa ara",
|
||||||
"pad.impexp.importing": "Important...",
|
"pad.impexp.importing": "Important...",
|
||||||
"pad.impexp.convertFailed": "No \u00e9s possible d'importar aquest fitxer. Si us plau, podeu provar d'utilitzar un format diferent o copiar i enganxar manualment.",
|
"pad.impexp.convertFailed": "No \u00e9s possible d'importar aquest fitxer. Si us plau, podeu provar d'utilitzar un format diferent o copiar i enganxar manualment.",
|
||||||
|
"pad.impexp.uploadFailed": "Ha fallat la c\u00e0rrega. Torneu-ho a provar",
|
||||||
"pad.impexp.importfailed": "Ha fallat la importaci\u00f3",
|
"pad.impexp.importfailed": "Ha fallat la importaci\u00f3",
|
||||||
"pad.impexp.copypaste": "Si us plau, copieu i enganxeu"
|
"pad.impexp.copypaste": "Si us plau, copieu i enganxeu"
|
||||||
}
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"@metadata": {
|
"@metadata": {
|
||||||
"authors": [
|
"authors": [
|
||||||
"Christian List"
|
"Christian List",
|
||||||
|
"Peter Alberti"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"index.newPad": "Ny Pad",
|
"index.newPad": "Ny Pad",
|
||||||
|
@ -100,6 +101,8 @@
|
||||||
"timeslider.month.october": "oktober",
|
"timeslider.month.october": "oktober",
|
||||||
"timeslider.month.november": "november",
|
"timeslider.month.november": "november",
|
||||||
"timeslider.month.december": "december",
|
"timeslider.month.december": "december",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} unavngiven forfatter",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} unavngivne forfattere",
|
||||||
"pad.savedrevs.marked": "Denne revision er nu markeret som en gemt revision",
|
"pad.savedrevs.marked": "Denne revision er nu markeret som en gemt revision",
|
||||||
"pad.userlist.entername": "Indtast dit navn",
|
"pad.userlist.entername": "Indtast dit navn",
|
||||||
"pad.userlist.unnamed": "ikke-navngivet",
|
"pad.userlist.unnamed": "ikke-navngivet",
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
"pad.toolbar.clearAuthorship.title": "Autorenfarben zur\u00fccksetzen",
|
"pad.toolbar.clearAuthorship.title": "Autorenfarben zur\u00fccksetzen",
|
||||||
"pad.toolbar.import_export.title": "Import\/Export in verschiedenen Dateiformaten",
|
"pad.toolbar.import_export.title": "Import\/Export in verschiedenen Dateiformaten",
|
||||||
"pad.toolbar.timeslider.title": "Pad-Versionsgeschichte anzeigen",
|
"pad.toolbar.timeslider.title": "Pad-Versionsgeschichte anzeigen",
|
||||||
"pad.toolbar.savedRevision.title": "Diese Revision markieren",
|
"pad.toolbar.savedRevision.title": "Version speichern",
|
||||||
"pad.toolbar.settings.title": "Einstellungen",
|
"pad.toolbar.settings.title": "Einstellungen",
|
||||||
"pad.toolbar.embed.title": "Dieses Pad teilen oder einbetten",
|
"pad.toolbar.embed.title": "Dieses Pad teilen oder einbetten",
|
||||||
"pad.toolbar.showusers.title": "Aktuell verbundene Benutzer anzeigen",
|
"pad.toolbar.showusers.title": "Aktuell verbundene Benutzer anzeigen",
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
"pad.toolbar.clearAuthorship.title": "\u039a\u03b1\u03b8\u03b1\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2 \u03a7\u03c1\u03c9\u03bc\u03ac\u03c4\u03c9\u03bd \u03a3\u03c5\u03bd\u03c4\u03b1\u03ba\u03c4\u03ce\u03bd",
|
"pad.toolbar.clearAuthorship.title": "\u039a\u03b1\u03b8\u03b1\u03c1\u03b9\u03c3\u03bc\u03cc\u03c2 \u03a7\u03c1\u03c9\u03bc\u03ac\u03c4\u03c9\u03bd \u03a3\u03c5\u03bd\u03c4\u03b1\u03ba\u03c4\u03ce\u03bd",
|
||||||
"pad.toolbar.import_export.title": "\u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae\/\u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae \u03b1\u03c0\u03cc\/\u03c3\u03b5 \u03b4\u03b9\u03b1\u03c6\u03bf\u03c1\u03b5\u03c4\u03b9\u03ba\u03bf\u03cd\u03c2 \u03c4\u03cd\u03c0\u03bf\u03c5\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd",
|
"pad.toolbar.import_export.title": "\u0395\u03b9\u03c3\u03b1\u03b3\u03c9\u03b3\u03ae\/\u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae \u03b1\u03c0\u03cc\/\u03c3\u03b5 \u03b4\u03b9\u03b1\u03c6\u03bf\u03c1\u03b5\u03c4\u03b9\u03ba\u03bf\u03cd\u03c2 \u03c4\u03cd\u03c0\u03bf\u03c5\u03c2 \u03b1\u03c1\u03c7\u03b5\u03af\u03c9\u03bd",
|
||||||
"pad.toolbar.timeslider.title": "\u03a7\u03c1\u03bf\u03bd\u03bf\u03b4\u03b9\u03ac\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1",
|
"pad.toolbar.timeslider.title": "\u03a7\u03c1\u03bf\u03bd\u03bf\u03b4\u03b9\u03ac\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1",
|
||||||
"pad.toolbar.savedRevision.title": "\u0391\u03c0\u03bf\u03b8\u03ae\u03ba\u03b5\u03c5\u03c3\u03b7 \u0388\u03ba\u03b4\u03bf\u03c3\u03b7\u03c2",
|
"pad.toolbar.savedRevision.title": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03c5\u03bc\u03ad\u03bd\u03b5\u03c2 \u0391\u03bd\u03b1\u03b8\u03b5\u03c9\u03c1\u03ae\u03c3\u03b5\u03b9\u03c2",
|
||||||
"pad.toolbar.settings.title": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2",
|
"pad.toolbar.settings.title": "\u03a1\u03c5\u03b8\u03bc\u03af\u03c3\u03b5\u03b9\u03c2",
|
||||||
"pad.toolbar.embed.title": "\u0395\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7 \u03c4\u03bf\u03c5 pad",
|
"pad.toolbar.embed.title": "\u0395\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7 \u03c4\u03bf\u03c5 pad",
|
||||||
"pad.toolbar.showusers.title": "\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 \u03c4\u03c9\u03bd \u03c7\u03c1\u03b7\u03c3\u03c4\u03ce\u03bd \u03b1\u03c5\u03c4\u03bf\u03cd \u03c4\u03bf\u03c5 pad",
|
"pad.toolbar.showusers.title": "\u0395\u03bc\u03c6\u03ac\u03bd\u03b9\u03c3\u03b7 \u03c4\u03c9\u03bd \u03c7\u03c1\u03b7\u03c3\u03c4\u03ce\u03bd \u03b1\u03c5\u03c4\u03bf\u03cd \u03c4\u03bf\u03c5 pad",
|
||||||
|
@ -81,6 +81,7 @@
|
||||||
"pad.share.emebdcode": "URL \u03b5\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7\u03c2",
|
"pad.share.emebdcode": "URL \u03b5\u03bd\u03c3\u03c9\u03bc\u03ac\u03c4\u03c9\u03c3\u03b7\u03c2",
|
||||||
"pad.chat": "\u03a3\u03c5\u03bd\u03bf\u03bc\u03b9\u03bb\u03af\u03b1",
|
"pad.chat": "\u03a3\u03c5\u03bd\u03bf\u03bc\u03b9\u03bb\u03af\u03b1",
|
||||||
"pad.chat.title": "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c4\u03b7\u03c2 \u03c3\u03c5\u03bd\u03bf\u03bc\u03b9\u03bb\u03af\u03b1\u03c2 \u03b3\u03b9\u03b1 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf pad.",
|
"pad.chat.title": "\u0386\u03bd\u03bf\u03b9\u03b3\u03bc\u03b1 \u03c4\u03b7\u03c2 \u03c3\u03c5\u03bd\u03bf\u03bc\u03b9\u03bb\u03af\u03b1\u03c2 \u03b3\u03b9\u03b1 \u03b1\u03c5\u03c4\u03cc \u03c4\u03bf pad.",
|
||||||
|
"pad.chat.loadmessages": "\u03a6\u03cc\u03c1\u03c4\u03c9\u03c3\u03b7 \u03c0\u03b5\u03c1\u03b9\u03c3\u03c3\u03cc\u03c4\u03b5\u03c1\u03c9\u03bd \u03bc\u03b7\u03bd\u03c5\u03bc\u03ac\u03c4\u03c9\u03bd",
|
||||||
"timeslider.pageTitle": "{{appTitle}} \u03a7\u03c1\u03bf\u03bd\u03bf\u03b4\u03b9\u03ac\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1",
|
"timeslider.pageTitle": "{{appTitle}} \u03a7\u03c1\u03bf\u03bd\u03bf\u03b4\u03b9\u03ac\u03b3\u03c1\u03b1\u03bc\u03bc\u03b1",
|
||||||
"timeslider.toolbar.returnbutton": "\u0395\u03c0\u03b9\u03c3\u03c4\u03c1\u03bf\u03c6\u03ae \u03c3\u03c4\u03bf pad",
|
"timeslider.toolbar.returnbutton": "\u0395\u03c0\u03b9\u03c3\u03c4\u03c1\u03bf\u03c6\u03ae \u03c3\u03c4\u03bf pad",
|
||||||
"timeslider.toolbar.authors": "\u03a3\u03c5\u03bd\u03c4\u03ac\u03ba\u03c4\u03b5\u03c2:",
|
"timeslider.toolbar.authors": "\u03a3\u03c5\u03bd\u03c4\u03ac\u03ba\u03c4\u03b5\u03c2:",
|
||||||
|
@ -88,7 +89,7 @@
|
||||||
"timeslider.toolbar.exportlink.title": "\u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae",
|
"timeslider.toolbar.exportlink.title": "\u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae",
|
||||||
"timeslider.exportCurrent": "\u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae \u03c4\u03c1\u03ad\u03c7\u03bf\u03c5\u03c3\u03b1\u03c2 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7\u03c2 \u03c9\u03c2:",
|
"timeslider.exportCurrent": "\u0395\u03be\u03b1\u03b3\u03c9\u03b3\u03ae \u03c4\u03c1\u03ad\u03c7\u03bf\u03c5\u03c3\u03b1\u03c2 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7\u03c2 \u03c9\u03c2:",
|
||||||
"timeslider.version": "\u0388\u03ba\u03b4\u03bf\u03c3\u03b7 {{version}}",
|
"timeslider.version": "\u0388\u03ba\u03b4\u03bf\u03c3\u03b7 {{version}}",
|
||||||
"timeslider.saved": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c4\u03b7\u03ba\u03b5 {{day}} {{month}}, {{year}}",
|
"timeslider.saved": "\u0391\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03cd\u03c4\u03b7\u03ba\u03b5 \u03c3\u03c4\u03b9\u03c2 {{day}} {{month}} {{year}}",
|
||||||
"timeslider.dateformat": "{{day}}\/{{month}}\/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
"timeslider.dateformat": "{{day}}\/{{month}}\/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
||||||
"timeslider.month.january": "\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5",
|
"timeslider.month.january": "\u0399\u03b1\u03bd\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5",
|
||||||
"timeslider.month.february": "\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5",
|
"timeslider.month.february": "\u03a6\u03b5\u03b2\u03c1\u03bf\u03c5\u03b1\u03c1\u03af\u03bf\u03c5",
|
||||||
|
@ -102,6 +103,8 @@
|
||||||
"timeslider.month.october": "\u039f\u03ba\u03c4\u03c9\u03b2\u03c1\u03af\u03bf\u03c5",
|
"timeslider.month.october": "\u039f\u03ba\u03c4\u03c9\u03b2\u03c1\u03af\u03bf\u03c5",
|
||||||
"timeslider.month.november": "\u039d\u03bf\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5",
|
"timeslider.month.november": "\u039d\u03bf\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5",
|
||||||
"timeslider.month.december": "\u0394\u03b5\u03ba\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5",
|
"timeslider.month.december": "\u0394\u03b5\u03ba\u03b5\u03bc\u03b2\u03c1\u03af\u03bf\u03c5",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} \u03b1\u03bd\u03ce\u03bd\u03c5\u03bc\u03bf\u03c2 \u03c3\u03c5\u03b3\u03b3\u03c1\u03b1\u03c6\u03ad\u03b1\u03c2",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} \u03b1\u03bd\u03ce\u03bd\u03c5\u03bc\u03bf\u03b9 \u03c3\u03c5\u03b3\u03b3\u03c1\u03b1\u03c6\u03b5\u03af\u03c2",
|
||||||
"pad.savedrevs.marked": "\u0391\u03c5\u03c4\u03ae \u03b7 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7 \u03b5\u03c0\u03b9\u03c3\u03b7\u03bc\u03ac\u03bd\u03b8\u03b7\u03ba\u03b5 \u03c9\u03c2 \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03c5\u03bc\u03ad\u03bd\u03b7 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7",
|
"pad.savedrevs.marked": "\u0391\u03c5\u03c4\u03ae \u03b7 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7 \u03b5\u03c0\u03b9\u03c3\u03b7\u03bc\u03ac\u03bd\u03b8\u03b7\u03ba\u03b5 \u03c9\u03c2 \u03b1\u03c0\u03bf\u03b8\u03b7\u03ba\u03b5\u03c5\u03bc\u03ad\u03bd\u03b7 \u03ad\u03ba\u03b4\u03bf\u03c3\u03b7",
|
||||||
"pad.userlist.entername": "\u0395\u03b9\u03c3\u03ac\u03b3\u03b5\u03c4\u03b5 \u03c4\u03bf \u03cc\u03bd\u03bf\u03bc\u03ac \u03c3\u03b1\u03c2",
|
"pad.userlist.entername": "\u0395\u03b9\u03c3\u03ac\u03b3\u03b5\u03c4\u03b5 \u03c4\u03bf \u03cc\u03bd\u03bf\u03bc\u03ac \u03c3\u03b1\u03c2",
|
||||||
"pad.userlist.unnamed": "\u03b1\u03bd\u03ce\u03bd\u03c5\u03bc\u03bf\u03c2",
|
"pad.userlist.unnamed": "\u03b1\u03bd\u03ce\u03bd\u03c5\u03bc\u03bf\u03c2",
|
||||||
|
|
|
@ -4,8 +4,9 @@
|
||||||
"0": "Armando-Martin",
|
"0": "Armando-Martin",
|
||||||
"1": "Jacobo",
|
"1": "Jacobo",
|
||||||
"2": "Joker",
|
"2": "Joker",
|
||||||
"4": "Vivaelcelta",
|
"3": "Rubenwap",
|
||||||
"5": "Xuacu"
|
"5": "Vivaelcelta",
|
||||||
|
"6": "Xuacu"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"index.newPad": "Nuevo Pad",
|
"index.newPad": "Nuevo Pad",
|
||||||
|
@ -104,6 +105,8 @@
|
||||||
"timeslider.month.october": "Octubre",
|
"timeslider.month.october": "Octubre",
|
||||||
"timeslider.month.november": "Noviembre",
|
"timeslider.month.november": "Noviembre",
|
||||||
"timeslider.month.december": "Diciembre",
|
"timeslider.month.december": "Diciembre",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} autor desconocido",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} autores desconocidos",
|
||||||
"pad.savedrevs.marked": "Revisi\u00f3n guardada",
|
"pad.savedrevs.marked": "Revisi\u00f3n guardada",
|
||||||
"pad.userlist.entername": "Escribe tu nombre",
|
"pad.userlist.entername": "Escribe tu nombre",
|
||||||
"pad.userlist.unnamed": "an\u00f3nimo",
|
"pad.userlist.unnamed": "an\u00f3nimo",
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"pad.toolbar.clearAuthorship.title": "Poista kirjoittajav\u00e4rit",
|
"pad.toolbar.clearAuthorship.title": "Poista kirjoittajav\u00e4rit",
|
||||||
"pad.toolbar.import_export.title": "Tuo tai vie eri tiedostomuodoista tai -muotoihin",
|
"pad.toolbar.import_export.title": "Tuo tai vie eri tiedostomuodoista tai -muotoihin",
|
||||||
"pad.toolbar.timeslider.title": "Aikajana",
|
"pad.toolbar.timeslider.title": "Aikajana",
|
||||||
"pad.toolbar.savedRevision.title": "Tallennetut versiot",
|
"pad.toolbar.savedRevision.title": "Tallenna muutos",
|
||||||
"pad.toolbar.settings.title": "Asetukset",
|
"pad.toolbar.settings.title": "Asetukset",
|
||||||
"pad.toolbar.embed.title": "Upota muistio",
|
"pad.toolbar.embed.title": "Upota muistio",
|
||||||
"pad.toolbar.showusers.title": "N\u00e4yt\u00e4 muistion k\u00e4ytt\u00e4j\u00e4t",
|
"pad.toolbar.showusers.title": "N\u00e4yt\u00e4 muistion k\u00e4ytt\u00e4j\u00e4t",
|
||||||
|
@ -105,6 +105,8 @@
|
||||||
"timeslider.month.october": "lokakuu",
|
"timeslider.month.october": "lokakuu",
|
||||||
"timeslider.month.november": "marraskuu",
|
"timeslider.month.november": "marraskuu",
|
||||||
"timeslider.month.december": "joulukuu",
|
"timeslider.month.december": "joulukuu",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} nimet\u00f6n tekij\u00e4",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} nimet\u00f6nt\u00e4 tekij\u00e4\u00e4",
|
||||||
"pad.savedrevs.marked": "T\u00e4m\u00e4 versio on nyt merkitty tallennetuksi versioksi",
|
"pad.savedrevs.marked": "T\u00e4m\u00e4 versio on nyt merkitty tallennetuksi versioksi",
|
||||||
"pad.userlist.entername": "Kirjoita nimesi",
|
"pad.userlist.entername": "Kirjoita nimesi",
|
||||||
"pad.userlist.unnamed": "nimet\u00f6n",
|
"pad.userlist.unnamed": "nimet\u00f6n",
|
||||||
|
|
|
@ -109,6 +109,8 @@
|
||||||
"timeslider.month.october": "Octobre",
|
"timeslider.month.october": "Octobre",
|
||||||
"timeslider.month.november": "Novembre",
|
"timeslider.month.november": "Novembre",
|
||||||
"timeslider.month.december": "D\u00e9cembre",
|
"timeslider.month.december": "D\u00e9cembre",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} auteur anonyme",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} auteurs anonymes",
|
||||||
"pad.savedrevs.marked": "Cette r\u00e9vision est maintenant marqu\u00e9e comme r\u00e9vision enregistr\u00e9e",
|
"pad.savedrevs.marked": "Cette r\u00e9vision est maintenant marqu\u00e9e comme r\u00e9vision enregistr\u00e9e",
|
||||||
"pad.userlist.entername": "Entrez votre nom",
|
"pad.userlist.entername": "Entrez votre nom",
|
||||||
"pad.userlist.unnamed": "sans nom",
|
"pad.userlist.unnamed": "sans nom",
|
||||||
|
|
|
@ -100,6 +100,8 @@
|
||||||
"timeslider.month.october": "outubro",
|
"timeslider.month.october": "outubro",
|
||||||
"timeslider.month.november": "novembro",
|
"timeslider.month.november": "novembro",
|
||||||
"timeslider.month.december": "decembro",
|
"timeslider.month.december": "decembro",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} autor an\u00f3nimo",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} autores an\u00f3nimos",
|
||||||
"pad.savedrevs.marked": "Esta revisi\u00f3n est\u00e1 agora marcada como revisi\u00f3n gardada",
|
"pad.savedrevs.marked": "Esta revisi\u00f3n est\u00e1 agora marcada como revisi\u00f3n gardada",
|
||||||
"pad.userlist.entername": "Insira o seu nome",
|
"pad.userlist.entername": "Insira o seu nome",
|
||||||
"pad.userlist.unnamed": "an\u00f3nimo",
|
"pad.userlist.unnamed": "an\u00f3nimo",
|
||||||
|
|
|
@ -79,6 +79,7 @@
|
||||||
"pad.share.emebdcode": "\u05d4\u05d8\u05de\u05e2\u05ea \u05e7\u05d9\u05e9\u05d5\u05e8",
|
"pad.share.emebdcode": "\u05d4\u05d8\u05de\u05e2\u05ea \u05e7\u05d9\u05e9\u05d5\u05e8",
|
||||||
"pad.chat": "\u05e9\u05d9\u05d7\u05d4",
|
"pad.chat": "\u05e9\u05d9\u05d7\u05d4",
|
||||||
"pad.chat.title": "\u05e4\u05ea\u05d9\u05d7\u05ea \u05d4\u05e9\u05d9\u05d7\u05d4 \u05e9\u05dc \u05d4\u05e4\u05e0\u05e7\u05e1 \u05d4\u05d6\u05d4.",
|
"pad.chat.title": "\u05e4\u05ea\u05d9\u05d7\u05ea \u05d4\u05e9\u05d9\u05d7\u05d4 \u05e9\u05dc \u05d4\u05e4\u05e0\u05e7\u05e1 \u05d4\u05d6\u05d4.",
|
||||||
|
"pad.chat.loadmessages": "\u05d8\u05e2\u05d9\u05e0\u05ea \u05d4\u05d5\u05d3\u05e2\u05d5\u05ea \u05e0\u05d5\u05e1\u05e4\u05d5\u05ea",
|
||||||
"timeslider.pageTitle": "\u05d2\u05d5\u05dc\u05dc \u05d6\u05de\u05df \u05e9\u05dc {{appTitle}}",
|
"timeslider.pageTitle": "\u05d2\u05d5\u05dc\u05dc \u05d6\u05de\u05df \u05e9\u05dc {{appTitle}}",
|
||||||
"timeslider.toolbar.returnbutton": "\u05d7\u05d6\u05e8\u05d4 \u05d0\u05dc \u05d4\u05e4\u05e0\u05e7\u05e1",
|
"timeslider.toolbar.returnbutton": "\u05d7\u05d6\u05e8\u05d4 \u05d0\u05dc \u05d4\u05e4\u05e0\u05e7\u05e1",
|
||||||
"timeslider.toolbar.authors": "\u05db\u05d5\u05ea\u05d1\u05d9\u05dd:",
|
"timeslider.toolbar.authors": "\u05db\u05d5\u05ea\u05d1\u05d9\u05dd:",
|
||||||
|
@ -100,6 +101,8 @@
|
||||||
"timeslider.month.october": "\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8",
|
"timeslider.month.october": "\u05d0\u05d5\u05e7\u05d8\u05d5\u05d1\u05e8",
|
||||||
"timeslider.month.november": "\u05e0\u05d5\u05d1\u05de\u05d1\u05e8",
|
"timeslider.month.november": "\u05e0\u05d5\u05d1\u05de\u05d1\u05e8",
|
||||||
"timeslider.month.december": "\u05d3\u05e6\u05de\u05d1\u05e8",
|
"timeslider.month.december": "\u05d3\u05e6\u05de\u05d1\u05e8",
|
||||||
|
"timeslider.unnamedauthor": "\u05db\u05d5\u05ea\u05d1 \u05d7\u05e1\u05e8\u05be\u05e9\u05dd \u05d0\u05d7\u05d3",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} \u05db\u05d5\u05ea\u05d1\u05d9\u05dd \u05d7\u05e1\u05e8\u05d9\u05be\u05e9\u05dd",
|
||||||
"pad.savedrevs.marked": "\u05d2\u05e8\u05e1\u05d4 \u05d6\u05d5 \u05de\u05e1\u05d5\u05de\u05e0\u05ea \u05db\u05d2\u05e8\u05e1\u05d4 \u05e9\u05de\u05d5\u05e8\u05d4",
|
"pad.savedrevs.marked": "\u05d2\u05e8\u05e1\u05d4 \u05d6\u05d5 \u05de\u05e1\u05d5\u05de\u05e0\u05ea \u05db\u05d2\u05e8\u05e1\u05d4 \u05e9\u05de\u05d5\u05e8\u05d4",
|
||||||
"pad.userlist.entername": "\u05e0\u05d0 \u05dc\u05d4\u05d6\u05d9\u05df \u05d0\u05ea \u05e9\u05de\u05da",
|
"pad.userlist.entername": "\u05e0\u05d0 \u05dc\u05d4\u05d6\u05d9\u05df \u05d0\u05ea \u05e9\u05de\u05da",
|
||||||
"pad.userlist.unnamed": "\u05dc\u05dc\u05d0 \u05e9\u05dd",
|
"pad.userlist.unnamed": "\u05dc\u05dc\u05d0 \u05e9\u05dd",
|
||||||
|
|
|
@ -103,6 +103,8 @@
|
||||||
"timeslider.month.october": "ottobre",
|
"timeslider.month.october": "ottobre",
|
||||||
"timeslider.month.november": "novembre",
|
"timeslider.month.november": "novembre",
|
||||||
"timeslider.month.december": "dicembre",
|
"timeslider.month.december": "dicembre",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} autore senza nome",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} autori senza nome",
|
||||||
"pad.savedrevs.marked": "Questa revisione \u00e8 ora contrassegnata come una versione salvata",
|
"pad.savedrevs.marked": "Questa revisione \u00e8 ora contrassegnata come una versione salvata",
|
||||||
"pad.userlist.entername": "Inserisci il tuo nome",
|
"pad.userlist.entername": "Inserisci il tuo nome",
|
||||||
"pad.userlist.unnamed": "senza nome",
|
"pad.userlist.unnamed": "senza nome",
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"pad.toolbar.clearAuthorship.title": "\u4f5c\u8005\u306e\u8272\u5206\u3051\u3092\u6d88\u53bb",
|
"pad.toolbar.clearAuthorship.title": "\u4f5c\u8005\u306e\u8272\u5206\u3051\u3092\u6d88\u53bb",
|
||||||
"pad.toolbar.import_export.title": "\u4ed6\u306e\u5f62\u5f0f\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\/\u30a8\u30af\u30b9\u30dd\u30fc\u30c8",
|
"pad.toolbar.import_export.title": "\u4ed6\u306e\u5f62\u5f0f\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\/\u30a8\u30af\u30b9\u30dd\u30fc\u30c8",
|
||||||
"pad.toolbar.timeslider.title": "\u30bf\u30a4\u30e0\u30b9\u30e9\u30a4\u30c0\u30fc",
|
"pad.toolbar.timeslider.title": "\u30bf\u30a4\u30e0\u30b9\u30e9\u30a4\u30c0\u30fc",
|
||||||
"pad.toolbar.savedRevision.title": "\u4fdd\u5b58\u6e08\u307f\u306e\u7248",
|
"pad.toolbar.savedRevision.title": "\u7248\u3092\u4fdd\u5b58",
|
||||||
"pad.toolbar.settings.title": "\u8a2d\u5b9a",
|
"pad.toolbar.settings.title": "\u8a2d\u5b9a",
|
||||||
"pad.toolbar.embed.title": "\u3053\u306e\u30d1\u30c3\u30c9\u3092\u57cb\u3081\u8fbc\u3080",
|
"pad.toolbar.embed.title": "\u3053\u306e\u30d1\u30c3\u30c9\u3092\u57cb\u3081\u8fbc\u3080",
|
||||||
"pad.toolbar.showusers.title": "\u3053\u306e\u30d1\u30c3\u30c9\u306e\u30e6\u30fc\u30b6\u30fc\u3092\u8868\u793a",
|
"pad.toolbar.showusers.title": "\u3053\u306e\u30d1\u30c3\u30c9\u306e\u30e6\u30fc\u30b6\u30fc\u3092\u8868\u793a",
|
||||||
|
@ -87,7 +87,7 @@
|
||||||
"timeslider.exportCurrent": "\u73fe\u5728\u306e\u7248\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3059\u308b\u5f62\u5f0f:",
|
"timeslider.exportCurrent": "\u73fe\u5728\u306e\u7248\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3059\u308b\u5f62\u5f0f:",
|
||||||
"timeslider.version": "\u30d0\u30fc\u30b8\u30e7\u30f3 {{version}}",
|
"timeslider.version": "\u30d0\u30fc\u30b8\u30e7\u30f3 {{version}}",
|
||||||
"timeslider.saved": "| {{year}}\u5e74{{month}}{{day}}\u65e5\u306b\u4fdd\u5b58",
|
"timeslider.saved": "| {{year}}\u5e74{{month}}{{day}}\u65e5\u306b\u4fdd\u5b58",
|
||||||
"timeslider.dateformat": "{{year}}\u5e74{{month}}{{day}}\u65e5 {{hours}}:{{minutes}}:{{seconds}}",
|
"timeslider.dateformat": "{{year}}\u5e74{{month}}\u6708{{day}}\u65e5 {{hours}}:{{minutes}}:{{seconds}}",
|
||||||
"timeslider.month.january": "1\u6708",
|
"timeslider.month.january": "1\u6708",
|
||||||
"timeslider.month.february": "2\u6708",
|
"timeslider.month.february": "2\u6708",
|
||||||
"timeslider.month.march": "3\u6708",
|
"timeslider.month.march": "3\u6708",
|
||||||
|
@ -100,6 +100,8 @@
|
||||||
"timeslider.month.october": "10\u6708",
|
"timeslider.month.october": "10\u6708",
|
||||||
"timeslider.month.november": "11\u6708",
|
"timeslider.month.november": "11\u6708",
|
||||||
"timeslider.month.december": "12\u6708",
|
"timeslider.month.december": "12\u6708",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} \u4eba\u306e\u533f\u540d\u306e\u4f5c\u8005",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} \u4eba\u306e\u533f\u540d\u306e\u4f5c\u8005",
|
||||||
"pad.savedrevs.marked": "\u3053\u306e\u7248\u3092\u3001\u4fdd\u5b58\u6e08\u307f\u306e\u7248\u3068\u3057\u3066\u30de\u30fc\u30af\u3057\u307e\u3057\u305f\u3002",
|
"pad.savedrevs.marked": "\u3053\u306e\u7248\u3092\u3001\u4fdd\u5b58\u6e08\u307f\u306e\u7248\u3068\u3057\u3066\u30de\u30fc\u30af\u3057\u307e\u3057\u305f\u3002",
|
||||||
"pad.userlist.entername": "\u540d\u524d\u3092\u5165\u529b",
|
"pad.userlist.entername": "\u540d\u524d\u3092\u5165\u529b",
|
||||||
"pad.userlist.unnamed": "\u540d\u524d\u306a\u3057",
|
"pad.userlist.unnamed": "\u540d\u524d\u306a\u3057",
|
||||||
|
|
|
@ -100,6 +100,8 @@
|
||||||
"timeslider.month.october": "10\uc6d4",
|
"timeslider.month.october": "10\uc6d4",
|
||||||
"timeslider.month.november": "11\uc6d4",
|
"timeslider.month.november": "11\uc6d4",
|
||||||
"timeslider.month.december": "12\uc6d4",
|
"timeslider.month.december": "12\uc6d4",
|
||||||
|
"timeslider.unnamedauthor": "\uc774\ub984 \uc5c6\ub294 \uc800\uc790 {{num}}\uba85",
|
||||||
|
"timeslider.unnamedauthors": "\uc774\ub984 \uc5c6\ub294 \uc800\uc790 {{num}}\uba85",
|
||||||
"pad.savedrevs.marked": "\uc774 \ud310\uc740 \uc774\uc81c \uc800\uc7a5\ud55c \ud310\uc73c\ub85c \ud45c\uc2dc\ud569\ub2c8\ub2e4.",
|
"pad.savedrevs.marked": "\uc774 \ud310\uc740 \uc774\uc81c \uc800\uc7a5\ud55c \ud310\uc73c\ub85c \ud45c\uc2dc\ud569\ub2c8\ub2e4.",
|
||||||
"pad.userlist.entername": "\uc774\ub984\uc744 \uc785\ub825\ud558\uc138\uc694",
|
"pad.userlist.entername": "\uc774\ub984\uc744 \uc785\ub825\ud558\uc138\uc694",
|
||||||
"pad.userlist.unnamed": "\uc774\ub984\uc5c6\uc74c",
|
"pad.userlist.unnamed": "\uc774\ub984\uc5c6\uc74c",
|
||||||
|
|
|
@ -19,13 +19,16 @@
|
||||||
"pad.toolbar.clearAuthorship.title": "d\u00e4 Schriiver ier F\u00e4rve fottn\u00e4mme",
|
"pad.toolbar.clearAuthorship.title": "d\u00e4 Schriiver ier F\u00e4rve fottn\u00e4mme",
|
||||||
"pad.toolbar.import_export.title": "Vun ongerscheidlijje Dattei_Fommaate empotteere udder \u00e4xpotteere",
|
"pad.toolbar.import_export.title": "Vun ongerscheidlijje Dattei_Fommaate empotteere udder \u00e4xpotteere",
|
||||||
"pad.toolbar.timeslider.title": "Verjangeheid afschpelle",
|
"pad.toolbar.timeslider.title": "Verjangeheid afschpelle",
|
||||||
"pad.toolbar.savedRevision.title": "Fa\u00dfjehallde Versione",
|
"pad.toolbar.savedRevision.title": "de Versjohn fa\u00dfhallde",
|
||||||
"pad.toolbar.settings.title": "Enscht\u00e4llonge",
|
"pad.toolbar.settings.title": "Enscht\u00e4llonge",
|
||||||
"pad.toolbar.embed.title": "Donn dat Padd enbenge",
|
"pad.toolbar.embed.title": "Donn dat Padd enbenge",
|
||||||
"pad.toolbar.showusers.title": "Verbonge Metschriiver aanzeije",
|
"pad.toolbar.showusers.title": "Verbonge Metschriiver aanzeije",
|
||||||
"pad.colorpicker.save": "Fa\u00dfhallde",
|
"pad.colorpicker.save": "Fa\u00dfhallde",
|
||||||
"pad.colorpicker.cancel": "Oph\u00fc\u00fcre",
|
"pad.colorpicker.cancel": "Oph\u00fc\u00fcre",
|
||||||
"pad.loading": "Aam Laade …",
|
"pad.loading": "Aam Laade …",
|
||||||
|
"pad.passwordRequired": "Do bruchs e Pa\u00dfwoot f\u00f6r heh dat P\u00e4dd.",
|
||||||
|
"pad.permissionDenied": "Do h\u00e4s nit dat R\u00e4\u00e4sch, op heh dat P\u00e4dd zohzejriife.",
|
||||||
|
"pad.wrongPassword": "Ding Pa\u00dfwoot wohr verkeht.",
|
||||||
"pad.settings.padSettings": "Dam P\u00e4dd sin Enscht\u00e4llonge",
|
"pad.settings.padSettings": "Dam P\u00e4dd sin Enscht\u00e4llonge",
|
||||||
"pad.settings.myView": "Anseesch",
|
"pad.settings.myView": "Anseesch",
|
||||||
"pad.settings.stickychat": "Donn der Klaaf emmer aanzeije",
|
"pad.settings.stickychat": "Donn der Klaaf emmer aanzeije",
|
||||||
|
@ -38,6 +41,7 @@
|
||||||
"pad.settings.language": "Schprooch:",
|
"pad.settings.language": "Schprooch:",
|
||||||
"pad.importExport.import_export": "Empoot\/\u00c4xpoot",
|
"pad.importExport.import_export": "Empoot\/\u00c4xpoot",
|
||||||
"pad.importExport.import": "Donn jeede T\u00e4x udder jeede Zoot Dokem\u00e4nt huhlaade",
|
"pad.importExport.import": "Donn jeede T\u00e4x udder jeede Zoot Dokem\u00e4nt huhlaade",
|
||||||
|
"pad.importExport.importSuccessful": "Jeschaff!",
|
||||||
"pad.importExport.export": "Don dat P\u00e4dd \u00e4xpoteere al\u00df:",
|
"pad.importExport.export": "Don dat P\u00e4dd \u00e4xpoteere al\u00df:",
|
||||||
"pad.importExport.exporthtml": "HTML",
|
"pad.importExport.exporthtml": "HTML",
|
||||||
"pad.importExport.exportplain": "Eijfach T\u00e4x",
|
"pad.importExport.exportplain": "Eijfach T\u00e4x",
|
||||||
|
@ -45,9 +49,11 @@
|
||||||
"pad.importExport.exportpdf": "PDF (Poteerbaa Dokem\u00e4nte Fommaat)",
|
"pad.importExport.exportpdf": "PDF (Poteerbaa Dokem\u00e4nte Fommaat)",
|
||||||
"pad.importExport.exportopen": "ODF (Offe Dokem\u00e4nte-Fommaat)",
|
"pad.importExport.exportopen": "ODF (Offe Dokem\u00e4nte-Fommaat)",
|
||||||
"pad.importExport.exportdokuwiki": "DokuWiki",
|
"pad.importExport.exportdokuwiki": "DokuWiki",
|
||||||
|
"pad.importExport.abiword.innerHTML": "Mer k\u00fcnne blo\u00df eijfaache T\u00e4xte udder HTML_Fommaate empoteere. Opw\u00e4ndejere M\u00fcjjeleschkeite f\u00f6 der Empoot jon och, dof\u00f6r bruch mer en <a href=\"https:\/\/github.com\/ether\/etherpad-lite\/wiki\/How-to-enable-importing-and-exporting-different-file-formats-in-Ubuntu-or-OpenSuse-or-SLES-with-AbiWord\">Enschtallazjuhn met <i lang=\"en\">Abiword<\/i><\/a>.",
|
||||||
"pad.modals.connected": "Verbonge.",
|
"pad.modals.connected": "Verbonge.",
|
||||||
"pad.modals.reconnecting": "Ben wider aam Verbenge …",
|
"pad.modals.reconnecting": "Ben wider aam Verbenge …",
|
||||||
"pad.modals.forcereconnect": "Wider verbenge",
|
"pad.modals.forcereconnect": "Wider verbenge",
|
||||||
|
"pad.modals.userdup": "En enem andere Finster en \u00c4rbeid",
|
||||||
"pad.modals.userdup.explanation": "Heh dat Padd schingk en mieh wi einem Finster vun enem Brauser op heh d\u00e4m R\u00e4\u00e4schner op ze sin.",
|
"pad.modals.userdup.explanation": "Heh dat Padd schingk en mieh wi einem Finster vun enem Brauser op heh d\u00e4m R\u00e4\u00e4schner op ze sin.",
|
||||||
"pad.modals.userdup.advice": "En heh d\u00e4m Finster wider verbenge.",
|
"pad.modals.userdup.advice": "En heh d\u00e4m Finster wider verbenge.",
|
||||||
"pad.modals.unauth": "Nit ber\u00e4\u00e4schtesch",
|
"pad.modals.unauth": "Nit ber\u00e4\u00e4schtesch",
|
||||||
|
@ -72,10 +78,12 @@
|
||||||
"pad.share.emebdcode": "URL enboue",
|
"pad.share.emebdcode": "URL enboue",
|
||||||
"pad.chat": "Klaaf",
|
"pad.chat": "Klaaf",
|
||||||
"pad.chat.title": "Maach d\u00e4 Klaaf f\u00f6r heh dat P\u00e4dd op",
|
"pad.chat.title": "Maach d\u00e4 Klaaf f\u00f6r heh dat P\u00e4dd op",
|
||||||
|
"pad.chat.loadmessages": "Mieh Nohresschte laade...",
|
||||||
"timeslider.pageTitle": "{{appTitle}} - Verjangeheid affschpelle",
|
"timeslider.pageTitle": "{{appTitle}} - Verjangeheid affschpelle",
|
||||||
"timeslider.toolbar.returnbutton": "Jangk retuur nohm P\u00e4dd",
|
"timeslider.toolbar.returnbutton": "Jangk retuur nohm P\u00e4dd",
|
||||||
"timeslider.toolbar.authors": "Schriiver:",
|
"timeslider.toolbar.authors": "Schriiver:",
|
||||||
"timeslider.toolbar.authorsList": "Kein Schriivere",
|
"timeslider.toolbar.authorsList": "Kein Schriivere",
|
||||||
|
"timeslider.toolbar.exportlink.title": "\u00c4xpoot",
|
||||||
"timeslider.exportCurrent": "Donn de meu\u00dfte V\u00e4sjohn \u00e4xpotteere al\u00df:",
|
"timeslider.exportCurrent": "Donn de meu\u00dfte V\u00e4sjohn \u00e4xpotteere al\u00df:",
|
||||||
"timeslider.version": "V\u00e4sjon {{version}}",
|
"timeslider.version": "V\u00e4sjon {{version}}",
|
||||||
"timeslider.saved": "Fa\u00dfjehallde aam {{day}}. {{month}} {{year}}",
|
"timeslider.saved": "Fa\u00dfjehallde aam {{day}}. {{month}} {{year}}",
|
||||||
|
@ -92,11 +100,19 @@
|
||||||
"timeslider.month.october": "Oktoober",
|
"timeslider.month.october": "Oktoober",
|
||||||
"timeslider.month.november": "Nov\u00e4mber",
|
"timeslider.month.november": "Nov\u00e4mber",
|
||||||
"timeslider.month.december": "Dez\u00e4mber",
|
"timeslider.month.december": "Dez\u00e4mber",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} naameloose Schriever",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} naameloose Schriever",
|
||||||
|
"pad.savedrevs.marked": "Heh di V\u00e4sjohn es j\u00e4z fa\u00dfjehallde.",
|
||||||
"pad.userlist.entername": "Jif Dinge Naame en",
|
"pad.userlist.entername": "Jif Dinge Naame en",
|
||||||
"pad.userlist.unnamed": "naamelo\u00df\u00df",
|
"pad.userlist.unnamed": "naamelo\u00df\u00df",
|
||||||
"pad.userlist.guest": "Ja\u00df\u00df",
|
"pad.userlist.guest": "Ja\u00df\u00df",
|
||||||
"pad.userlist.deny": "Aflehne",
|
"pad.userlist.deny": "Aflehne",
|
||||||
|
"pad.userlist.approve": "Joodhei\u00dfe",
|
||||||
|
"pad.editbar.clearcolors": "Sulle mer de F\u00e4rve f\u00f6r de Schriiver uss_em janze T\u00e4x fott maache?",
|
||||||
|
"pad.impexp.importbutton": "J\u00e4z empoteere",
|
||||||
"pad.impexp.importing": "Ben aam Empotteere …",
|
"pad.impexp.importing": "Ben aam Empotteere …",
|
||||||
|
"pad.impexp.confirmimport": "En Dattei ze empotteere m\u00e4\u00e4t der janze T\u00e4x em P\u00e4dd fott. Wess De dat verfaftesch hann?",
|
||||||
|
"pad.impexp.convertFailed": "Mer kunnte di Dattei nit empoteere. Nemm en ander Dattei-Fommaat udder donn d\u00e4 T\u00e4x vun Hand kopeere un ennf\u00f6\u00f6je.",
|
||||||
"pad.impexp.uploadFailed": "Et Huhlaade es don\u00e4vve jejange, bes esu jood un probeer et norr_ens",
|
"pad.impexp.uploadFailed": "Et Huhlaade es don\u00e4vve jejange, bes esu jood un probeer et norr_ens",
|
||||||
"pad.impexp.importfailed": "Et Empoteere es don\u00e4vve jejange",
|
"pad.impexp.importfailed": "Et Empoteere es don\u00e4vve jejange",
|
||||||
"pad.impexp.copypaste": "Bes esu jood un donn et koppeere un enf\u00f6\u00f6je",
|
"pad.impexp.copypaste": "Bes esu jood un donn et koppeere un enf\u00f6\u00f6je",
|
||||||
|
|
|
@ -101,6 +101,8 @@
|
||||||
"timeslider.month.october": "\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438",
|
"timeslider.month.october": "\u043e\u043a\u0442\u043e\u043c\u0432\u0440\u0438",
|
||||||
"timeslider.month.november": "\u043d\u043e\u0435\u043c\u0432\u0440\u0438",
|
"timeslider.month.november": "\u043d\u043e\u0435\u043c\u0432\u0440\u0438",
|
||||||
"timeslider.month.december": "\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438",
|
"timeslider.month.december": "\u0434\u0435\u043a\u0435\u043c\u0432\u0440\u0438",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} \u043d\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d \u0430\u0432\u0442\u043e\u0440",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} \u043d\u0435\u0438\u043c\u0435\u043d\u0443\u0432\u0430\u043d\u0438 \u0430\u0432\u0442\u043e\u0440\u0438",
|
||||||
"pad.savedrevs.marked": "\u041e\u0432\u0430\u0430 \u0440\u0435\u0432\u0438\u0437\u0438\u0458\u0430 \u0441\u0435\u0433\u0430 \u0435 \u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u043a\u0430\u043a\u043e \u0437\u0430\u0447\u0443\u0432\u0430\u043d\u0430",
|
"pad.savedrevs.marked": "\u041e\u0432\u0430\u0430 \u0440\u0435\u0432\u0438\u0437\u0438\u0458\u0430 \u0441\u0435\u0433\u0430 \u0435 \u043e\u0437\u043d\u0430\u0447\u0435\u043d\u0430 \u043a\u0430\u043a\u043e \u0437\u0430\u0447\u0443\u0432\u0430\u043d\u0430",
|
||||||
"pad.userlist.entername": "\u0412\u043d\u0435\u0441\u0435\u0442\u0435 \u0433\u043e \u0432\u0430\u0448\u0435\u0442\u043e \u0438\u043c\u0435",
|
"pad.userlist.entername": "\u0412\u043d\u0435\u0441\u0435\u0442\u0435 \u0433\u043e \u0432\u0430\u0448\u0435\u0442\u043e \u0438\u043c\u0435",
|
||||||
"pad.userlist.unnamed": "\u0431\u0435\u0437 \u0438\u043c\u0435",
|
"pad.userlist.unnamed": "\u0431\u0435\u0437 \u0438\u043c\u0435",
|
||||||
|
|
|
@ -79,6 +79,7 @@
|
||||||
"pad.share.emebdcode": "\u0d0e\u0d02\u0d2c\u0d46\u0d21\u0d4d \u0d2f\u0d41.\u0d06\u0d7c.\u0d0e\u0d7d.",
|
"pad.share.emebdcode": "\u0d0e\u0d02\u0d2c\u0d46\u0d21\u0d4d \u0d2f\u0d41.\u0d06\u0d7c.\u0d0e\u0d7d.",
|
||||||
"pad.chat": "\u0d24\u0d24\u0d4d\u0d38\u0d2e\u0d2f\u0d38\u0d02\u0d35\u0d3e\u0d26\u0d02",
|
"pad.chat": "\u0d24\u0d24\u0d4d\u0d38\u0d2e\u0d2f\u0d38\u0d02\u0d35\u0d3e\u0d26\u0d02",
|
||||||
"pad.chat.title": "\u0d08 \u0d2a\u0d3e\u0d21\u0d3f\u0d28\u0d4d\u0d31\u0d46 \u0d24\u0d24\u0d4d\u0d38\u0d2e\u0d2f\u0d38\u0d02\u0d35\u0d3e\u0d26\u0d02 \u0d24\u0d41\u0d31\u0d15\u0d4d\u0d15\u0d41\u0d15.",
|
"pad.chat.title": "\u0d08 \u0d2a\u0d3e\u0d21\u0d3f\u0d28\u0d4d\u0d31\u0d46 \u0d24\u0d24\u0d4d\u0d38\u0d2e\u0d2f\u0d38\u0d02\u0d35\u0d3e\u0d26\u0d02 \u0d24\u0d41\u0d31\u0d15\u0d4d\u0d15\u0d41\u0d15.",
|
||||||
|
"pad.chat.loadmessages": "\u0d15\u0d42\u0d1f\u0d41\u0d24\u0d7d \u0d38\u0d28\u0d4d\u0d26\u0d47\u0d36\u0d19\u0d4d\u0d19\u0d7e \u0d0e\u0d1f\u0d41\u0d15\u0d4d\u0d15\u0d41\u0d15",
|
||||||
"timeslider.pageTitle": "{{appTitle}} \u0d38\u0d2e\u0d2f\u0d30\u0d47\u0d16",
|
"timeslider.pageTitle": "{{appTitle}} \u0d38\u0d2e\u0d2f\u0d30\u0d47\u0d16",
|
||||||
"timeslider.toolbar.returnbutton": "\u0d2a\u0d3e\u0d21\u0d3f\u0d32\u0d47\u0d15\u0d4d\u0d15\u0d4d \u0d24\u0d3f\u0d30\u0d3f\u0d1a\u0d4d\u0d1a\u0d41\u0d2a\u0d4b\u0d35\u0d41\u0d15",
|
"timeslider.toolbar.returnbutton": "\u0d2a\u0d3e\u0d21\u0d3f\u0d32\u0d47\u0d15\u0d4d\u0d15\u0d4d \u0d24\u0d3f\u0d30\u0d3f\u0d1a\u0d4d\u0d1a\u0d41\u0d2a\u0d4b\u0d35\u0d41\u0d15",
|
||||||
"timeslider.toolbar.authors": "\u0d30\u0d1a\u0d2f\u0d3f\u0d24\u0d3e\u0d15\u0d4d\u0d15\u0d7e:",
|
"timeslider.toolbar.authors": "\u0d30\u0d1a\u0d2f\u0d3f\u0d24\u0d3e\u0d15\u0d4d\u0d15\u0d7e:",
|
||||||
|
|
|
@ -78,6 +78,7 @@
|
||||||
"pad.share.emebdcode": "Benamkan URL",
|
"pad.share.emebdcode": "Benamkan URL",
|
||||||
"pad.chat": "Sembang",
|
"pad.chat": "Sembang",
|
||||||
"pad.chat.title": "Buka ruang sembang untuk pad ini.",
|
"pad.chat.title": "Buka ruang sembang untuk pad ini.",
|
||||||
|
"pad.chat.loadmessages": "Muatkan banyak lagi pesanan",
|
||||||
"timeslider.pageTitle": "Gelangsar Masa {{appTitle}}",
|
"timeslider.pageTitle": "Gelangsar Masa {{appTitle}}",
|
||||||
"timeslider.toolbar.returnbutton": "Kembali ke pad",
|
"timeslider.toolbar.returnbutton": "Kembali ke pad",
|
||||||
"timeslider.toolbar.authors": "Pengarang:",
|
"timeslider.toolbar.authors": "Pengarang:",
|
||||||
|
@ -99,6 +100,8 @@
|
||||||
"timeslider.month.october": "Oktober",
|
"timeslider.month.october": "Oktober",
|
||||||
"timeslider.month.november": "November",
|
"timeslider.month.november": "November",
|
||||||
"timeslider.month.december": "Disember",
|
"timeslider.month.december": "Disember",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} orang pengarang awanama",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} orang pengarang awanama",
|
||||||
"pad.savedrevs.marked": "Semakan ini telah ditandai sebagai semakan tersimpan",
|
"pad.savedrevs.marked": "Semakan ini telah ditandai sebagai semakan tersimpan",
|
||||||
"pad.userlist.entername": "Taipkan nama anda",
|
"pad.userlist.entername": "Taipkan nama anda",
|
||||||
"pad.userlist.unnamed": "tanpa nama",
|
"pad.userlist.unnamed": "tanpa nama",
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"pad.toolbar.clearAuthorship.title": "Kleuren auteurs wissen",
|
"pad.toolbar.clearAuthorship.title": "Kleuren auteurs wissen",
|
||||||
"pad.toolbar.import_export.title": "Naar\/van andere opmaak exporteren\/importeren",
|
"pad.toolbar.import_export.title": "Naar\/van andere opmaak exporteren\/importeren",
|
||||||
"pad.toolbar.timeslider.title": "Tijdlijn",
|
"pad.toolbar.timeslider.title": "Tijdlijn",
|
||||||
"pad.toolbar.savedRevision.title": "Opgeslagen versies",
|
"pad.toolbar.savedRevision.title": "Versie opslaan",
|
||||||
"pad.toolbar.settings.title": "Instellingen",
|
"pad.toolbar.settings.title": "Instellingen",
|
||||||
"pad.toolbar.embed.title": "Pad insluiten",
|
"pad.toolbar.embed.title": "Pad insluiten",
|
||||||
"pad.toolbar.showusers.title": "Gebruikers van dit pad weergeven",
|
"pad.toolbar.showusers.title": "Gebruikers van dit pad weergeven",
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"pad.toolbar.clearAuthorship.title": "\u0424\u044b\u0441\u0441\u04d5\u0434\u0436\u044b \u043d\u044b\u0441\u04d5\u043d\u0442\u0442\u04d5 \u0430\u0439\u0441\u044b\u043d\u04d5\u043d",
|
"pad.toolbar.clearAuthorship.title": "\u0424\u044b\u0441\u0441\u04d5\u0434\u0436\u044b \u043d\u044b\u0441\u04d5\u043d\u0442\u0442\u04d5 \u0430\u0439\u0441\u044b\u043d\u04d5\u043d",
|
||||||
"pad.toolbar.import_export.title": "\u0418\u043c\u043f\u043e\u0440\u0442\/\u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u04d5\u043d\u0434\u04d5\u0440 \u0444\u0430\u0439\u043b\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0442\u04d5\u0439\/\u0444\u043e\u0440\u043c\u0430\u0442\u0442\u04d5\u043c",
|
"pad.toolbar.import_export.title": "\u0418\u043c\u043f\u043e\u0440\u0442\/\u044d\u043a\u0441\u043f\u043e\u0440\u0442 \u04d5\u043d\u0434\u04d5\u0440 \u0444\u0430\u0439\u043b\u044b \u0444\u043e\u0440\u043c\u0430\u0442\u0442\u04d5\u0439\/\u0444\u043e\u0440\u043c\u0430\u0442\u0442\u04d5\u043c",
|
||||||
"pad.toolbar.timeslider.title": "\u0420\u04d5\u0441\u0442\u04d5\u0434\u0436\u044b \u0445\u0430\u0445\u0445",
|
"pad.toolbar.timeslider.title": "\u0420\u04d5\u0441\u0442\u04d5\u0434\u0436\u044b \u0445\u0430\u0445\u0445",
|
||||||
"pad.toolbar.savedRevision.title": "\u04d4\u0432\u04d5\u0440\u0434 \u0444\u04d5\u043b\u0442\u04d5\u0440\u0442\u04d5",
|
"pad.toolbar.savedRevision.title": "\u0424\u04d5\u043b\u0442\u04d5\u0440 \u0431\u0430\u0432\u04d5\u0440\u044b\u043d\u04d5\u043d",
|
||||||
"pad.toolbar.settings.title": "\u0423\u0430\u0433\u04d5\u0432\u04d5\u0440\u0434\u0442\u04d5",
|
"pad.toolbar.settings.title": "\u0423\u0430\u0433\u04d5\u0432\u04d5\u0440\u0434\u0442\u04d5",
|
||||||
"pad.toolbar.embed.title": "\u0410\u0446\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u0431\u0430\u0444\u0442\u0430\u0443\u044b\u043d",
|
"pad.toolbar.embed.title": "\u0410\u0446\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442 \u0431\u0430\u0444\u0442\u0430\u0443\u044b\u043d",
|
||||||
"pad.toolbar.showusers.title": "\u0410\u0446\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b \u0430\u0440\u0445\u0430\u0439\u0434\u0436\u044b\u0442\u044b \u0440\u0430\u0432\u0434\u0438\u0441\u044b\u043d",
|
"pad.toolbar.showusers.title": "\u0410\u0446\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u044b \u0430\u0440\u0445\u0430\u0439\u0434\u0436\u044b\u0442\u044b \u0440\u0430\u0432\u0434\u0438\u0441\u044b\u043d",
|
||||||
|
@ -78,6 +78,7 @@
|
||||||
"pad.share.emebdcode": "URL \u0431\u0430\u0432\u04d5\u0440\u044b\u043d",
|
"pad.share.emebdcode": "URL \u0431\u0430\u0432\u04d5\u0440\u044b\u043d",
|
||||||
"pad.chat": "\u041d\u044b\u0445\u0430\u0441",
|
"pad.chat": "\u041d\u044b\u0445\u0430\u0441",
|
||||||
"pad.chat.title": "\u041e\u0446\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u04d5\u043d \u0447\u0430\u0442 \u0431\u0430\u043a\u04d5\u043d.",
|
"pad.chat.title": "\u041e\u0446\u044b \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u04d5\u043d \u0447\u0430\u0442 \u0431\u0430\u043a\u04d5\u043d.",
|
||||||
|
"pad.chat.loadmessages": "\u0424\u044b\u043b\u0434\u04d5\u0440 \u0444\u044b\u0441\u0442\u04d5\u0433 \u0440\u0430\u0432\u0433\u04d5\u043d\u044b\u043d",
|
||||||
"timeslider.pageTitle": "{{appTitle}}-\u044b \u0440\u04d5\u0442\u04d5\u0434\u0436\u044b \u0445\u0430\u0445\u0445",
|
"timeslider.pageTitle": "{{appTitle}}-\u044b \u0440\u04d5\u0442\u04d5\u0434\u0436\u044b \u0445\u0430\u0445\u0445",
|
||||||
"timeslider.toolbar.returnbutton": "\u0424\u04d5\u0441\u0442\u04d5\u043c\u04d5, \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043c\u04d5",
|
"timeslider.toolbar.returnbutton": "\u0424\u04d5\u0441\u0442\u04d5\u043c\u04d5, \u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u043c\u04d5",
|
||||||
"timeslider.toolbar.authors": "\u0424\u044b\u0441\u0441\u04d5\u0434\u0436\u044b\u0442\u04d5:",
|
"timeslider.toolbar.authors": "\u0424\u044b\u0441\u0441\u04d5\u0434\u0436\u044b\u0442\u04d5:",
|
||||||
|
@ -99,6 +100,8 @@
|
||||||
"timeslider.month.october": "\u043e\u043a\u0442\u044f\u0431\u0440\u044c",
|
"timeslider.month.october": "\u043e\u043a\u0442\u044f\u0431\u0440\u044c",
|
||||||
"timeslider.month.november": "\u043d\u043e\u044f\u0431\u0440\u044c",
|
"timeslider.month.november": "\u043d\u043e\u044f\u0431\u0440\u044c",
|
||||||
"timeslider.month.december": "\u0434\u0435\u043a\u0430\u0431\u0440\u044c",
|
"timeslider.month.december": "\u0434\u0435\u043a\u0430\u0431\u0440\u044c",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} \u04d5\u043d\u04d5\u043d\u043e\u043c \u0444\u044b\u0441\u0441\u04d5\u0433",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} \u04d5\u043d\u04d5\u043d\u043e\u043c \u0444\u044b\u0441\u0441\u04d5\u0434\u0436\u044b",
|
||||||
"pad.savedrevs.marked": "\u0410\u0446\u044b \u0444\u04d5\u043b\u0442\u04d5\u0440 \u043d\u044b\u0440 \u043a\u0443\u044b\u0434 \u04d5\u0432\u04d5\u0440\u0434 \u0444\u04d5\u043b\u0442\u04d5\u0440 \u043d\u044b\u0441\u0430\u043d\u0433\u043e\u043d\u0434 \u04d5\u0440\u0446\u044b\u0434",
|
"pad.savedrevs.marked": "\u0410\u0446\u044b \u0444\u04d5\u043b\u0442\u04d5\u0440 \u043d\u044b\u0440 \u043a\u0443\u044b\u0434 \u04d5\u0432\u04d5\u0440\u0434 \u0444\u04d5\u043b\u0442\u04d5\u0440 \u043d\u044b\u0441\u0430\u043d\u0433\u043e\u043d\u0434 \u04d5\u0440\u0446\u044b\u0434",
|
||||||
"pad.userlist.entername": "\u0414\u04d5 \u043d\u043e\u043c \u0431\u0430\u0444\u044b\u0441\u0441",
|
"pad.userlist.entername": "\u0414\u04d5 \u043d\u043e\u043c \u0431\u0430\u0444\u044b\u0441\u0441",
|
||||||
"pad.userlist.unnamed": "\u04d5\u043d\u04d5\u043d\u043e\u043c",
|
"pad.userlist.unnamed": "\u04d5\u043d\u04d5\u043d\u043e\u043c",
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
"pad.toolbar.clearAuthorship.title": "Usu\u0144 kolory autor\u00f3w",
|
"pad.toolbar.clearAuthorship.title": "Usu\u0144 kolory autor\u00f3w",
|
||||||
"pad.toolbar.import_export.title": "Import\/eksport z\/do r\u00f3\u017cnych format\u00f3w plik\u00f3w",
|
"pad.toolbar.import_export.title": "Import\/eksport z\/do r\u00f3\u017cnych format\u00f3w plik\u00f3w",
|
||||||
"pad.toolbar.timeslider.title": "O\u015b czasu",
|
"pad.toolbar.timeslider.title": "O\u015b czasu",
|
||||||
"pad.toolbar.savedRevision.title": "Zapisane wersje",
|
"pad.toolbar.savedRevision.title": "Zapisz wersj\u0119",
|
||||||
"pad.toolbar.settings.title": "Ustawienia",
|
"pad.toolbar.settings.title": "Ustawienia",
|
||||||
"pad.toolbar.embed.title": "Umie\u015b\u0107 ten Notatnik",
|
"pad.toolbar.embed.title": "Umie\u015b\u0107 ten Notatnik",
|
||||||
"pad.toolbar.showusers.title": "Poka\u017c u\u017cytkownik\u00f3w",
|
"pad.toolbar.showusers.title": "Poka\u017c u\u017cytkownik\u00f3w",
|
||||||
|
@ -102,6 +102,8 @@
|
||||||
"timeslider.month.october": "Pa\u017adziernik",
|
"timeslider.month.october": "Pa\u017adziernik",
|
||||||
"timeslider.month.november": "Listopad",
|
"timeslider.month.november": "Listopad",
|
||||||
"timeslider.month.december": "Grudzie\u0144",
|
"timeslider.month.december": "Grudzie\u0144",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} nienazwany autor",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} autor\u00f3w bez nazw",
|
||||||
"pad.savedrevs.marked": "Ta wersja zosta\u0142a w\u0142a\u015bnie oznaczona jako zapisana.",
|
"pad.savedrevs.marked": "Ta wersja zosta\u0142a w\u0142a\u015bnie oznaczona jako zapisana.",
|
||||||
"pad.userlist.entername": "Wprowad\u017a swoj\u0105 nazw\u0119",
|
"pad.userlist.entername": "Wprowad\u017a swoj\u0105 nazw\u0119",
|
||||||
"pad.userlist.unnamed": "bez nazwy",
|
"pad.userlist.unnamed": "bez nazwy",
|
||||||
|
|
|
@ -17,7 +17,9 @@
|
||||||
"pad.settings.fontType": "\u0644\u064a\u06a9\u0628\u06bc\u06d0 \u0689\u0648\u0644:",
|
"pad.settings.fontType": "\u0644\u064a\u06a9\u0628\u06bc\u06d0 \u0689\u0648\u0644:",
|
||||||
"pad.settings.fontType.normal": "\u0646\u0648\u0631\u0645\u0627\u0644",
|
"pad.settings.fontType.normal": "\u0646\u0648\u0631\u0645\u0627\u0644",
|
||||||
"pad.settings.fontType.monospaced": "\u0645\u0648\u0646\u0648\u0633\u067e\u06d0\u0633",
|
"pad.settings.fontType.monospaced": "\u0645\u0648\u0646\u0648\u0633\u067e\u06d0\u0633",
|
||||||
|
"pad.settings.globalView": "\u0646\u0693\u06d0\u0648\u0627\u0644\u0647 \u069a\u06a9\u0627\u0631\u06d0\u062f\u0646\u0647",
|
||||||
"pad.settings.language": "\u0698\u0628\u0647:",
|
"pad.settings.language": "\u0698\u0628\u0647:",
|
||||||
|
"pad.importExport.importSuccessful": "\u0628\u0631\u064a\u0627\u0644\u06cc \u0634\u0648!",
|
||||||
"pad.importExport.exporthtml": "\u0627\u0686 \u067c\u064a \u0627\u0645 \u0627\u06d0\u0644",
|
"pad.importExport.exporthtml": "\u0627\u0686 \u067c\u064a \u0627\u0645 \u0627\u06d0\u0644",
|
||||||
"pad.importExport.exportplain": "\u0633\u0627\u062f\u0647 \u0645\u062a\u0646",
|
"pad.importExport.exportplain": "\u0633\u0627\u062f\u0647 \u0645\u062a\u0646",
|
||||||
"pad.importExport.exportword": "\u0645\u0627\u064a\u06a9\u0631\u0648\u0633\u0627\u0641\u067c \u0648\u0631\u0689",
|
"pad.importExport.exportword": "\u0645\u0627\u064a\u06a9\u0631\u0648\u0633\u0627\u0641\u067c \u0648\u0631\u0689",
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"pad.toolbar.clearAuthorship.title": "Limpar as cores de identifica\u00e7\u00e3o de autoria",
|
"pad.toolbar.clearAuthorship.title": "Limpar as cores de identifica\u00e7\u00e3o de autoria",
|
||||||
"pad.toolbar.import_export.title": "Importar\/Exportar de\/para diferentes formatos de arquivo",
|
"pad.toolbar.import_export.title": "Importar\/Exportar de\/para diferentes formatos de arquivo",
|
||||||
"pad.toolbar.timeslider.title": "Linha do tempo",
|
"pad.toolbar.timeslider.title": "Linha do tempo",
|
||||||
"pad.toolbar.savedRevision.title": "Revis\u00f5es Salvas",
|
"pad.toolbar.savedRevision.title": "Salvar revis\u00e3o",
|
||||||
"pad.toolbar.settings.title": "Configura\u00e7\u00f5es",
|
"pad.toolbar.settings.title": "Configura\u00e7\u00f5es",
|
||||||
"pad.toolbar.embed.title": "Incorporar esta Nota",
|
"pad.toolbar.embed.title": "Incorporar esta Nota",
|
||||||
"pad.toolbar.showusers.title": "Mostrar os usuarios nesta Nota",
|
"pad.toolbar.showusers.title": "Mostrar os usuarios nesta Nota",
|
||||||
|
@ -100,6 +100,8 @@
|
||||||
"timeslider.month.october": "Outubro",
|
"timeslider.month.october": "Outubro",
|
||||||
"timeslider.month.november": "Novembro",
|
"timeslider.month.november": "Novembro",
|
||||||
"timeslider.month.december": "Dezembro",
|
"timeslider.month.december": "Dezembro",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} autor desconhecido",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} autores desconhecidos",
|
||||||
"pad.savedrevs.marked": "Esta revis\u00e3o foi marcada como salva",
|
"pad.savedrevs.marked": "Esta revis\u00e3o foi marcada como salva",
|
||||||
"pad.userlist.entername": "Insira o seu nome",
|
"pad.userlist.entername": "Insira o seu nome",
|
||||||
"pad.userlist.unnamed": "Sem t\u00edtulo",
|
"pad.userlist.unnamed": "Sem t\u00edtulo",
|
||||||
|
|
|
@ -103,6 +103,8 @@
|
||||||
"timeslider.month.october": "\u043e\u043a\u0442\u044f\u0431\u0440\u044c",
|
"timeslider.month.october": "\u043e\u043a\u0442\u044f\u0431\u0440\u044c",
|
||||||
"timeslider.month.november": "\u043d\u043e\u044f\u0431\u0440\u044c",
|
"timeslider.month.november": "\u043d\u043e\u044f\u0431\u0440\u044c",
|
||||||
"timeslider.month.december": "\u0434\u0435\u043a\u0430\u0431\u0440\u044c",
|
"timeslider.month.december": "\u0434\u0435\u043a\u0430\u0431\u0440\u044c",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} \u0431\u0435\u0437\u044b\u043c\u044f\u043d\u043d\u044b\u0439 \u0430\u0432\u0442\u043e\u0440",
|
||||||
|
"timeslider.unnamedauthors": "\u0431\u0435\u0437\u044b\u043c\u044f\u043d\u043d\u044b\u0445 \u0430\u0432\u0442\u043e\u0440\u043e\u0432: {{num}}",
|
||||||
"pad.savedrevs.marked": "\u042d\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u0430 \u043a\u0430\u043a \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u0430\u044f",
|
"pad.savedrevs.marked": "\u042d\u0442\u0430 \u0432\u0435\u0440\u0441\u0438\u044f \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u043c\u0435\u0447\u0435\u043d\u0430 \u043a\u0430\u043a \u0441\u043e\u0445\u0440\u0430\u043d\u0435\u043d\u043d\u0430\u044f",
|
||||||
"pad.userlist.entername": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0432\u0430\u0448\u0435 \u0438\u043c\u044f",
|
"pad.userlist.entername": "\u0412\u0432\u0435\u0434\u0438\u0442\u0435 \u0432\u0430\u0448\u0435 \u0438\u043c\u044f",
|
||||||
"pad.userlist.unnamed": "\u0431\u0435\u0437\u044b\u043c\u044f\u043d\u043d\u044b\u0439",
|
"pad.userlist.unnamed": "\u0431\u0435\u0437\u044b\u043c\u044f\u043d\u043d\u044b\u0439",
|
||||||
|
|
|
@ -100,6 +100,8 @@
|
||||||
"timeslider.month.october": "Oktober",
|
"timeslider.month.october": "Oktober",
|
||||||
"timeslider.month.november": "November",
|
"timeslider.month.november": "November",
|
||||||
"timeslider.month.december": "December",
|
"timeslider.month.december": "December",
|
||||||
|
"timeslider.unnamedauthor": "neimenovani avtor {{num}}",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} neimenovani avtorji",
|
||||||
"pad.savedrevs.marked": "Ta predelava je ozna\u010dena kot shranjena predelava.",
|
"pad.savedrevs.marked": "Ta predelava je ozna\u010dena kot shranjena predelava.",
|
||||||
"pad.userlist.entername": "Vpi\u0161ite ime",
|
"pad.userlist.entername": "Vpi\u0161ite ime",
|
||||||
"pad.userlist.unnamed": "neimenovana oseba",
|
"pad.userlist.unnamed": "neimenovana oseba",
|
||||||
|
|
|
@ -100,6 +100,8 @@
|
||||||
"timeslider.month.october": "oktober",
|
"timeslider.month.october": "oktober",
|
||||||
"timeslider.month.november": "november",
|
"timeslider.month.november": "november",
|
||||||
"timeslider.month.december": "december",
|
"timeslider.month.december": "december",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} namnl\u00f6s f\u00f6rfattare",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} namnl\u00f6sa f\u00f6rfattare",
|
||||||
"pad.savedrevs.marked": "Denna revision \u00e4r nu markerad som en sparad revision",
|
"pad.savedrevs.marked": "Denna revision \u00e4r nu markerad som en sparad revision",
|
||||||
"pad.userlist.entername": "Ange ditt namn",
|
"pad.userlist.entername": "Ange ditt namn",
|
||||||
"pad.userlist.unnamed": "namnl\u00f6s",
|
"pad.userlist.unnamed": "namnl\u00f6s",
|
||||||
|
|
|
@ -38,6 +38,7 @@
|
||||||
"pad.settings.language": "\u0c2d\u0c3e\u0c37",
|
"pad.settings.language": "\u0c2d\u0c3e\u0c37",
|
||||||
"pad.importExport.import_export": "\u0c26\u0c3f\u0c17\u0c41\u0c2e\u0c24\u0c3f\/\u0c0e\u0c17\u0c41\u0c2e\u0c24\u0c3f",
|
"pad.importExport.import_export": "\u0c26\u0c3f\u0c17\u0c41\u0c2e\u0c24\u0c3f\/\u0c0e\u0c17\u0c41\u0c2e\u0c24\u0c3f",
|
||||||
"pad.importExport.import": "\u0c2a\u0c3e\u0c20\u0c2e\u0c41 \u0c26\u0c38\u0c4d\u0c24\u0c4d\u0c30\u0c2e\u0c41 \u0c32\u0c47\u0c26\u0c3e \u0c2a\u0c24\u0c4d\u0c30\u0c2e\u0c41\u0c28\u0c41 \u0c26\u0c3f\u0c17\u0c41\u0c2e\u0c24\u0c3f \u0c1a\u0c47\u0c2f\u0c41\u0c2e\u0c41",
|
"pad.importExport.import": "\u0c2a\u0c3e\u0c20\u0c2e\u0c41 \u0c26\u0c38\u0c4d\u0c24\u0c4d\u0c30\u0c2e\u0c41 \u0c32\u0c47\u0c26\u0c3e \u0c2a\u0c24\u0c4d\u0c30\u0c2e\u0c41\u0c28\u0c41 \u0c26\u0c3f\u0c17\u0c41\u0c2e\u0c24\u0c3f \u0c1a\u0c47\u0c2f\u0c41\u0c2e\u0c41",
|
||||||
|
"pad.importExport.importSuccessful": "\u0c35\u0c3f\u0c1c\u0c2f\u0c35\u0c02\u0c24\u0c02!",
|
||||||
"pad.importExport.export": "\u0c2a\u0c4d\u0c30\u0c38\u0c4d\u0c24\u0c41\u0c24 \u0c2a\u0c32\u0c15\u0c28\u0c3f \u0c08 \u0c35\u0c3f\u0c27\u0c2e\u0c41\u0c17\u0c3e \u0c0e\u0c17\u0c41\u0c2e\u0c24\u0c3f \u0c1a\u0c47\u0c2f\u0c41\u0c2e\u0c41:",
|
"pad.importExport.export": "\u0c2a\u0c4d\u0c30\u0c38\u0c4d\u0c24\u0c41\u0c24 \u0c2a\u0c32\u0c15\u0c28\u0c3f \u0c08 \u0c35\u0c3f\u0c27\u0c2e\u0c41\u0c17\u0c3e \u0c0e\u0c17\u0c41\u0c2e\u0c24\u0c3f \u0c1a\u0c47\u0c2f\u0c41\u0c2e\u0c41:",
|
||||||
"pad.importExport.exporthtml": "\u0c39\u0c46\u0c1a\u0c4d \u0c1f\u0c3f \u0c0e\u0c02 \u0c0e\u0c32\u0c4d",
|
"pad.importExport.exporthtml": "\u0c39\u0c46\u0c1a\u0c4d \u0c1f\u0c3f \u0c0e\u0c02 \u0c0e\u0c32\u0c4d",
|
||||||
"pad.importExport.exportplain": "\u0c38\u0c3e\u0c26\u0c3e \u0c2a\u0c3e\u0c20\u0c4d\u0c2f\u0c02",
|
"pad.importExport.exportplain": "\u0c38\u0c3e\u0c26\u0c3e \u0c2a\u0c3e\u0c20\u0c4d\u0c2f\u0c02",
|
||||||
|
|
|
@ -102,6 +102,8 @@
|
||||||
"timeslider.month.october": "\u0416\u043e\u0432\u0442\u0435\u043d\u044c",
|
"timeslider.month.october": "\u0416\u043e\u0432\u0442\u0435\u043d\u044c",
|
||||||
"timeslider.month.november": "\u041b\u0438\u0441\u0442\u043e\u043f\u0430\u0434",
|
"timeslider.month.november": "\u041b\u0438\u0441\u0442\u043e\u043f\u0430\u0434",
|
||||||
"timeslider.month.december": "\u0413\u0440\u0443\u0434\u0435\u043d\u044c",
|
"timeslider.month.december": "\u0413\u0440\u0443\u0434\u0435\u043d\u044c",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} \u0431\u0435\u0437\u0456\u043c\u0435\u043d\u043d\u0438\u0439 \u0430\u0432\u0442\u043e\u0440",
|
||||||
|
"timeslider.unnamedauthors": "\u0431\u0435\u0437\u0456\u043c\u0435\u043d\u043d\u0438\u0445 \u0430\u0432\u0442\u043e\u0440\u043e\u0432: {{num}}",
|
||||||
"pad.savedrevs.marked": "\u0426\u044e \u0432\u0435\u0440\u0441\u0456\u044e \u043f\u043e\u043c\u0456\u0447\u0435\u043d\u043e \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043e\u044e \u0432\u0435\u0440\u0441\u0456\u0454\u044e",
|
"pad.savedrevs.marked": "\u0426\u044e \u0432\u0435\u0440\u0441\u0456\u044e \u043f\u043e\u043c\u0456\u0447\u0435\u043d\u043e \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043d\u043e\u044e \u0432\u0435\u0440\u0441\u0456\u0454\u044e",
|
||||||
"pad.userlist.entername": "\u0412\u0432\u0435\u0434\u0456\u0442\u044c \u0412\u0430\u0448\u0435 \u0456\u043c'\u044f",
|
"pad.userlist.entername": "\u0412\u0432\u0435\u0434\u0456\u0442\u044c \u0412\u0430\u0448\u0435 \u0456\u043c'\u044f",
|
||||||
"pad.userlist.unnamed": "\u0431\u0435\u0437\u0456\u043c\u0435\u043d\u043d\u0438\u0439",
|
"pad.userlist.unnamed": "\u0431\u0435\u0437\u0456\u043c\u0435\u043d\u043d\u0438\u0439",
|
||||||
|
|
|
@ -3,6 +3,8 @@
|
||||||
"authors": [
|
"authors": [
|
||||||
"Dimension",
|
"Dimension",
|
||||||
"Hydra",
|
"Hydra",
|
||||||
|
"Yfdyh000",
|
||||||
|
"\u4e4c\u62c9\u8de8\u6c2a",
|
||||||
"\u71c3\u7389"
|
"\u71c3\u7389"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
@ -18,8 +20,9 @@
|
||||||
"pad.toolbar.undo.title": "\u64a4\u6d88 (Ctrl-Z)",
|
"pad.toolbar.undo.title": "\u64a4\u6d88 (Ctrl-Z)",
|
||||||
"pad.toolbar.redo.title": "\u91cd\u505a (Ctrl-Y)",
|
"pad.toolbar.redo.title": "\u91cd\u505a (Ctrl-Y)",
|
||||||
"pad.toolbar.clearAuthorship.title": "\u6e05\u9664\u4f5c\u540d\u989c\u8272",
|
"pad.toolbar.clearAuthorship.title": "\u6e05\u9664\u4f5c\u540d\u989c\u8272",
|
||||||
|
"pad.toolbar.import_export.title": "\u4ee5\u5176\u4ed6\u6587\u4ef6\u683c\u5f0f\u5bfc\u5165\/\u5bfc\u51fa",
|
||||||
"pad.toolbar.timeslider.title": "\u65f6\u95f4\u8f74",
|
"pad.toolbar.timeslider.title": "\u65f6\u95f4\u8f74",
|
||||||
"pad.toolbar.savedRevision.title": "\u5df2\u4fdd\u5b58\u7684\u4fee\u8ba2",
|
"pad.toolbar.savedRevision.title": "\u4fdd\u5b58\u4fee\u8ba2",
|
||||||
"pad.toolbar.settings.title": "\u8bbe\u7f6e",
|
"pad.toolbar.settings.title": "\u8bbe\u7f6e",
|
||||||
"pad.toolbar.embed.title": "\u5d4c\u5165\u6b64\u8bb0\u4e8b\u672c",
|
"pad.toolbar.embed.title": "\u5d4c\u5165\u6b64\u8bb0\u4e8b\u672c",
|
||||||
"pad.toolbar.showusers.title": "\u663e\u793a\u6b64\u8bb0\u4e8b\u672c\u7684\u7528\u6237",
|
"pad.toolbar.showusers.title": "\u663e\u793a\u6b64\u8bb0\u4e8b\u672c\u7684\u7528\u6237",
|
||||||
|
@ -30,12 +33,19 @@
|
||||||
"pad.permissionDenied": "\u60a8\u6ca1\u6709\u89c2\u770b\u8fd9\u4e2a\u8bb0\u4e8b\u672c\u7684\u6743\u9650",
|
"pad.permissionDenied": "\u60a8\u6ca1\u6709\u89c2\u770b\u8fd9\u4e2a\u8bb0\u4e8b\u672c\u7684\u6743\u9650",
|
||||||
"pad.wrongPassword": "\u60a8\u7684\u5bc6\u7801\u9519\u4e86",
|
"pad.wrongPassword": "\u60a8\u7684\u5bc6\u7801\u9519\u4e86",
|
||||||
"pad.settings.padSettings": "\u8bb0\u4e8b\u672c\u8bbe\u7f6e",
|
"pad.settings.padSettings": "\u8bb0\u4e8b\u672c\u8bbe\u7f6e",
|
||||||
|
"pad.settings.myView": "\u6211\u7684\u89c6\u7a97",
|
||||||
|
"pad.settings.stickychat": "\u603b\u662f\u5728\u5c4f\u5e55\u4e0a\u663e\u793a\u804a\u5929",
|
||||||
|
"pad.settings.colorcheck": "\u4f5c\u8005\u989c\u8272",
|
||||||
"pad.settings.linenocheck": "\u884c\u53f7",
|
"pad.settings.linenocheck": "\u884c\u53f7",
|
||||||
"pad.settings.fontType": "\u5b57\u4f53\u7c7b\u578b\uff1a",
|
"pad.settings.fontType": "\u5b57\u4f53\u7c7b\u578b\uff1a",
|
||||||
"pad.settings.fontType.normal": "\u6b63\u5e38",
|
"pad.settings.fontType.normal": "\u6b63\u5e38",
|
||||||
|
"pad.settings.fontType.monospaced": "\u7b49\u5bbd\u5b57\u4f53",
|
||||||
|
"pad.settings.globalView": "\u6240\u6709\u4eba\u7684\u89c6\u7a97",
|
||||||
"pad.settings.language": "\u8bed\u8a00\uff1a",
|
"pad.settings.language": "\u8bed\u8a00\uff1a",
|
||||||
"pad.importExport.import_export": "\u5bfc\u5165\/\u5bfc\u51fa",
|
"pad.importExport.import_export": "\u5bfc\u5165\/\u5bfc\u51fa",
|
||||||
|
"pad.importExport.import": "\u4e0a\u8f7d\u4efb\u4f55\u6587\u5b57\u6863\u6216\u6587\u6863",
|
||||||
"pad.importExport.importSuccessful": "\u6210\u529f\uff01",
|
"pad.importExport.importSuccessful": "\u6210\u529f\uff01",
|
||||||
|
"pad.importExport.export": "\u5bfc\u51fa\u76ee\u524d\u7684\u8bb0\u4e8b\u7c3f\u4e3a\uff1a",
|
||||||
"pad.importExport.exporthtml": "HTML",
|
"pad.importExport.exporthtml": "HTML",
|
||||||
"pad.importExport.exportplain": "\u7eaf\u6587\u672c",
|
"pad.importExport.exportplain": "\u7eaf\u6587\u672c",
|
||||||
"pad.importExport.exportword": "Microsoft Word",
|
"pad.importExport.exportword": "Microsoft Word",
|
||||||
|
@ -43,21 +53,36 @@
|
||||||
"pad.importExport.exportopen": "ODF\uff08\u5f00\u653e\u6587\u6863\u683c\u5f0f\uff09",
|
"pad.importExport.exportopen": "ODF\uff08\u5f00\u653e\u6587\u6863\u683c\u5f0f\uff09",
|
||||||
"pad.importExport.exportdokuwiki": "DokuWiki",
|
"pad.importExport.exportdokuwiki": "DokuWiki",
|
||||||
"pad.modals.connected": "\u5df2\u8fde\u63a5\u3002",
|
"pad.modals.connected": "\u5df2\u8fde\u63a5\u3002",
|
||||||
|
"pad.modals.reconnecting": "\u91cd\u65b0\u8fde\u63a5\u5230\u60a8\u7684\u8bb0\u4e8b\u7c3f...",
|
||||||
"pad.modals.forcereconnect": "\u5f3a\u5236\u91cd\u65b0\u8fde\u63a5",
|
"pad.modals.forcereconnect": "\u5f3a\u5236\u91cd\u65b0\u8fde\u63a5",
|
||||||
|
"pad.modals.userdup": "\u5728\u53e6\u4e00\u4e2a\u89c6\u7a97\u4e2d\u6253\u5f00",
|
||||||
|
"pad.modals.userdup.explanation": "\u6b64\u8bb0\u4e8b\u7c3f\u4f3c\u4e4e\u5728\u6b64\u7535\u8111\u4e0a\u5728\u591a\u4e2a\u6d4f\u89c8\u5668\u89c6\u7a97\u4e2d\u6253\u5f00\u3002",
|
||||||
|
"pad.modals.userdup.advice": "\u91cd\u65b0\u8fde\u63a5\u5230\u6b64\u89c6\u7a97\u3002",
|
||||||
"pad.modals.unauth": "\u672a\u6388\u6743",
|
"pad.modals.unauth": "\u672a\u6388\u6743",
|
||||||
"pad.modals.looping": "\u5df2\u79bb\u7ebf\u3002",
|
"pad.modals.looping": "\u5df2\u79bb\u7ebf\u3002",
|
||||||
|
"pad.modals.initsocketfail": "\u65e0\u6cd5\u8bbf\u95ee\u670d\u52a1\u5668\u3002",
|
||||||
|
"pad.modals.initsocketfail.explanation": "\u65e0\u6cd5\u8fde\u63a5\u5230\u540c\u6b65\u670d\u52a1\u5668\u3002",
|
||||||
|
"pad.modals.initsocketfail.cause": "\u8fd9\u53ef\u80fd\u662f\u7531\u4e8e\u60a8\u7684\u6d4f\u89c8\u5668\u6216\u60a8\u7684\u4e92\u8054\u7f51\u8fde\u63a5\u7684\u95ee\u9898\u3002",
|
||||||
"pad.modals.slowcommit": "\u5df2\u79bb\u7ebf\u3002",
|
"pad.modals.slowcommit": "\u5df2\u79bb\u7ebf\u3002",
|
||||||
|
"pad.modals.slowcommit.explanation": "\u670d\u52a1\u5668\u6ca1\u6709\u54cd\u5e94\u3002",
|
||||||
|
"pad.modals.slowcommit.cause": "\u8fd9\u53ef\u80fd\u662f\u7531\u4e8e\u7f51\u7edc\u8fde\u63a5\u95ee\u9898\u3002",
|
||||||
"pad.modals.deleted": "\u5df2\u522a\u9664\u3002",
|
"pad.modals.deleted": "\u5df2\u522a\u9664\u3002",
|
||||||
"pad.modals.deleted.explanation": "\u6b64\u8bb0\u4e8b\u672c\u5df2\u88ab\u79fb\u9664\u3002",
|
"pad.modals.deleted.explanation": "\u6b64\u8bb0\u4e8b\u672c\u5df2\u88ab\u79fb\u9664\u3002",
|
||||||
"pad.modals.disconnected": "\u60a8\u5df2\u88ab\u79bb\u7ebf\u3002",
|
"pad.modals.disconnected": "\u60a8\u5df2\u88ab\u79bb\u7ebf\u3002",
|
||||||
|
"pad.modals.disconnected.explanation": "\u5230\u670d\u52a1\u5668\u7684\u8fde\u63a5\u5df2\u4e22\u5931",
|
||||||
|
"pad.modals.disconnected.cause": "\u670d\u52a1\u5668\u53ef\u80fd\u65e0\u6cd5\u4f7f\u7528\u3002\u82e5\u6b64\u60c5\u51b5\u6301\u7eed\u53d1\u751f\uff0c\u8bf7\u901a\u77e5\u6211\u4eec\u3002",
|
||||||
"pad.share": "\u5206\u4eab\u6b64\u8bb0\u4e8b\u672c",
|
"pad.share": "\u5206\u4eab\u6b64\u8bb0\u4e8b\u672c",
|
||||||
"pad.share.readonly": "\u53ea\u80fd\u8bfb",
|
"pad.share.readonly": "\u53ea\u80fd\u8bfb",
|
||||||
"pad.share.link": "\u94fe\u63a5",
|
"pad.share.link": "\u94fe\u63a5",
|
||||||
"pad.share.emebdcode": "\u5d4c\u5165\u7f51\u5740",
|
"pad.share.emebdcode": "\u5d4c\u5165\u7f51\u5740",
|
||||||
"pad.chat": "\u804a\u5929",
|
"pad.chat": "\u804a\u5929",
|
||||||
|
"pad.chat.title": "\u6253\u5f00\u6b64\u8bb0\u4e8b\u7c3f\u7684\u804a\u5929\u3002",
|
||||||
|
"pad.chat.loadmessages": "\u52a0\u8f7d\u66f4\u591a\u4fe1\u606f",
|
||||||
"timeslider.toolbar.returnbutton": "\u8fd4\u56de\u8bb0\u4e8b\u672c",
|
"timeslider.toolbar.returnbutton": "\u8fd4\u56de\u8bb0\u4e8b\u672c",
|
||||||
"timeslider.toolbar.authors": "\u4f5c\u8005\uff1a",
|
"timeslider.toolbar.authors": "\u4f5c\u8005\uff1a",
|
||||||
"timeslider.toolbar.authorsList": "\u6ca1\u6709\u4f5c\u8005",
|
"timeslider.toolbar.authorsList": "\u6ca1\u6709\u4f5c\u8005",
|
||||||
|
"timeslider.toolbar.exportlink.title": "\u5bfc\u51fa",
|
||||||
|
"timeslider.exportCurrent": "\u5bfc\u51fa\u76ee\u524d\u7248\u672c\u4e3a\uff1a",
|
||||||
"timeslider.version": "\u7b2c {{version}} \u7248\u672c",
|
"timeslider.version": "\u7b2c {{version}} \u7248\u672c",
|
||||||
"timeslider.saved": "\u5728{{year}}\u5e74{{month}}{{day}}\u65e5\u4fdd\u5b58",
|
"timeslider.saved": "\u5728{{year}}\u5e74{{month}}{{day}}\u65e5\u4fdd\u5b58",
|
||||||
"timeslider.month.january": "\u4e00\u6708",
|
"timeslider.month.january": "\u4e00\u6708",
|
||||||
|
@ -72,13 +97,20 @@
|
||||||
"timeslider.month.october": "\u5341\u6708",
|
"timeslider.month.october": "\u5341\u6708",
|
||||||
"timeslider.month.november": "\u5341\u4e00\u6708",
|
"timeslider.month.november": "\u5341\u4e00\u6708",
|
||||||
"timeslider.month.december": "\u5341\u4e8c\u6708",
|
"timeslider.month.december": "\u5341\u4e8c\u6708",
|
||||||
|
"timeslider.unnamedauthor": "{{num}}\u533f\u540d\u4f5c\u8005",
|
||||||
|
"timeslider.unnamedauthors": "{{num}}\u533f\u540d\u4f5c\u8005",
|
||||||
|
"pad.savedrevs.marked": "\u6b64\u4fee\u8ba2\u5df2\u6807\u8bb0\u4e3a\u4fdd\u5b58\u4fee\u8ba2",
|
||||||
"pad.userlist.entername": "\u8f93\u5165\u60a8\u7684\u59d3\u540d",
|
"pad.userlist.entername": "\u8f93\u5165\u60a8\u7684\u59d3\u540d",
|
||||||
"pad.userlist.unnamed": "\u65e0\u540d",
|
"pad.userlist.unnamed": "\u65e0\u540d",
|
||||||
"pad.userlist.guest": "\u8bbf\u5ba2",
|
"pad.userlist.guest": "\u8bbf\u5ba2",
|
||||||
"pad.userlist.deny": "\u62d2\u7edd",
|
"pad.userlist.deny": "\u62d2\u7edd",
|
||||||
"pad.userlist.approve": "\u6279\u51c6",
|
"pad.userlist.approve": "\u6279\u51c6",
|
||||||
|
"pad.editbar.clearcolors": "\u6e05\u9664\u6574\u4e2a\u6587\u6863\u7684\u4f5c\u8005\u989c\u8272\u5417\uff1f",
|
||||||
"pad.impexp.importbutton": "\u73b0\u5728\u5bfc\u5165",
|
"pad.impexp.importbutton": "\u73b0\u5728\u5bfc\u5165",
|
||||||
"pad.impexp.importing": "\u6b63\u5728\u5bfc\u5165...",
|
"pad.impexp.importing": "\u6b63\u5728\u5bfc\u5165...",
|
||||||
|
"pad.impexp.convertFailed": "\u6211\u4eec\u65e0\u6cd5\u5bfc\u5165\u6b64\u6587\u6863\u3002\u8bf7\u4f7f\u7528\u4ed6\u6587\u6863\u683c\u5f0f\u6216\u624b\u52a8\u590d\u5236\u8d34\u4e0a\u3002",
|
||||||
"pad.impexp.uploadFailed": "\u4e0a\u8f7d\u5931\u8d25\uff0c\u8bf7\u91cd\u8bd5",
|
"pad.impexp.uploadFailed": "\u4e0a\u8f7d\u5931\u8d25\uff0c\u8bf7\u91cd\u8bd5",
|
||||||
"pad.impexp.importfailed": "\u5bfc\u5165\u5931\u8d25"
|
"pad.impexp.importfailed": "\u5bfc\u5165\u5931\u8d25",
|
||||||
|
"pad.impexp.copypaste": "\u8bf7\u590d\u5236\u7c98\u8d34",
|
||||||
|
"pad.impexp.exportdisabled": "{{type}} \u683c\u5f0f\u7684\u5bfc\u51fa\u88ab\u7981\u7528\u3002\u6709\u5173\u8be6\u60c5\uff0c\u8bf7\u4e0e\u60a8\u7684\u7cfb\u7edf\u7ba1\u7406\u5458\u8054\u7cfb\u3002"
|
||||||
}
|
}
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"@metadata": {
|
"@metadata": {
|
||||||
"authors": {
|
"authors": {
|
||||||
"1": "Simon Shek"
|
"0": "Shirayuki",
|
||||||
|
"2": "Simon Shek"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"index.newPad": "\u65b0Pad",
|
"index.newPad": "\u65b0Pad",
|
||||||
|
@ -19,7 +20,7 @@
|
||||||
"pad.toolbar.clearAuthorship.title": "\u6e05\u9664\u4f5c\u540d\u984f\u8272",
|
"pad.toolbar.clearAuthorship.title": "\u6e05\u9664\u4f5c\u540d\u984f\u8272",
|
||||||
"pad.toolbar.import_export.title": "\u4ee5\u5176\u4ed6\u6a94\u6848\u683c\u5f0f\u5c0e\u5165\uff0f\u532f\u51fa",
|
"pad.toolbar.import_export.title": "\u4ee5\u5176\u4ed6\u6a94\u6848\u683c\u5f0f\u5c0e\u5165\uff0f\u532f\u51fa",
|
||||||
"pad.toolbar.timeslider.title": "\u6642\u9593\u8ef8",
|
"pad.toolbar.timeslider.title": "\u6642\u9593\u8ef8",
|
||||||
"pad.toolbar.savedRevision.title": "\u5df2\u5132\u5b58\u7684\u4fee\u8a02",
|
"pad.toolbar.savedRevision.title": "\u5132\u5b58\u4fee\u8a02",
|
||||||
"pad.toolbar.settings.title": "\u8a2d\u5b9a",
|
"pad.toolbar.settings.title": "\u8a2d\u5b9a",
|
||||||
"pad.toolbar.embed.title": "\u5d4c\u5165\u6b64pad",
|
"pad.toolbar.embed.title": "\u5d4c\u5165\u6b64pad",
|
||||||
"pad.toolbar.showusers.title": "\u986f\u793a\u6b64pad\u7684\u7528\u6236",
|
"pad.toolbar.showusers.title": "\u986f\u793a\u6b64pad\u7684\u7528\u6236",
|
||||||
|
@ -86,8 +87,8 @@
|
||||||
"timeslider.toolbar.exportlink.title": "\u532f\u51fa",
|
"timeslider.toolbar.exportlink.title": "\u532f\u51fa",
|
||||||
"timeslider.exportCurrent": "\u532f\u51fa\u7576\u524d\u7248\u672c\u70ba\uff1a",
|
"timeslider.exportCurrent": "\u532f\u51fa\u7576\u524d\u7248\u672c\u70ba\uff1a",
|
||||||
"timeslider.version": "\u7248\u672c{{version}}",
|
"timeslider.version": "\u7248\u672c{{version}}",
|
||||||
"timeslider.saved": "{{year}}{{month}}{{day}}\u4fdd\u5b58",
|
"timeslider.saved": "{{year}}\u5e74{{month}}{{day}}\u65e5\u4fdd\u5b58",
|
||||||
"timeslider.dateformat": "{{year}}{{month}}{{day}} {{hours}}:{{minutes}}:{{seconds}}",
|
"timeslider.dateformat": "{{year}}\u5e74{{month}}\u6708{{day}}\u65e5 {{hours}}:{{minutes}}:{{seconds}}",
|
||||||
"timeslider.month.january": "1\u6708",
|
"timeslider.month.january": "1\u6708",
|
||||||
"timeslider.month.february": "2\u6708",
|
"timeslider.month.february": "2\u6708",
|
||||||
"timeslider.month.march": "3\u6708",
|
"timeslider.month.march": "3\u6708",
|
||||||
|
@ -100,6 +101,8 @@
|
||||||
"timeslider.month.october": "10\u6708",
|
"timeslider.month.october": "10\u6708",
|
||||||
"timeslider.month.november": "11\u6708",
|
"timeslider.month.november": "11\u6708",
|
||||||
"timeslider.month.december": "12\u6708",
|
"timeslider.month.december": "12\u6708",
|
||||||
|
"timeslider.unnamedauthor": "{{num}} \u533f\u540d\u4f5c\u8005",
|
||||||
|
"timeslider.unnamedauthors": "{{num}} \u533f\u540d\u4f5c\u8005",
|
||||||
"pad.savedrevs.marked": "\u6b64\u4fee\u8a02\u5df2\u6a19\u8a18\u70ba\u5df2\u4fdd\u5b58\u3002",
|
"pad.savedrevs.marked": "\u6b64\u4fee\u8a02\u5df2\u6a19\u8a18\u70ba\u5df2\u4fdd\u5b58\u3002",
|
||||||
"pad.userlist.entername": "\u8f38\u5165\u60a8\u7684\u59d3\u540d",
|
"pad.userlist.entername": "\u8f38\u5165\u60a8\u7684\u59d3\u540d",
|
||||||
"pad.userlist.unnamed": "\u672a\u547d\u540d",
|
"pad.userlist.unnamed": "\u672a\u547d\u540d",
|
||||||
|
|
|
@ -253,9 +253,7 @@ 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);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -325,17 +323,17 @@ exports.getChatHistory = function(padID, start, end, callback)
|
||||||
if(!start || !end)
|
if(!start || !end)
|
||||||
{
|
{
|
||||||
start = 0;
|
start = 0;
|
||||||
end = pad.chatHead - 1;
|
end = pad.chatHead;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(start >= chatHead)
|
if(start >= chatHead && chatHead > 0)
|
||||||
{
|
{
|
||||||
callback(new customError("start is higher or equal to the current chatHead","apierror"));
|
callback(new customError("start is higher or equal to the current chatHead","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(end >= chatHead)
|
if(end > chatHead)
|
||||||
{
|
{
|
||||||
callback(new customError("end is higher or equal to the current chatHead","apierror"));
|
callback(new customError("end is higher than the current chatHead","apierror"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -151,7 +151,6 @@ exports.getPad = function(id, text, callback)
|
||||||
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);
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/**
|
/**
|
||||||
* The Session Manager provides functions to manage session in the database
|
* The Session Manager provides functions to manage session in the database, it only provides session management for sessions created by the API
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
82
src/node/db/SessionStore.js
Normal file
82
src/node/db/SessionStore.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
/*
|
||||||
|
* Stores session data in the database
|
||||||
|
* Source; https://github.com/edy-b/SciFlowWriter/blob/develop/available_plugins/ep_sciflowwriter/db/DirtyStore.js
|
||||||
|
* This is not used for authors that are created via the API at current
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Store = require('ep_etherpad-lite/node_modules/connect/lib/middleware/session/store'),
|
||||||
|
utils = require('ep_etherpad-lite/node_modules/connect/lib/utils'),
|
||||||
|
Session = require('ep_etherpad-lite/node_modules/connect/lib/middleware/session/session'),
|
||||||
|
db = require('ep_etherpad-lite/node/db/DB').db,
|
||||||
|
log4js = require('ep_etherpad-lite/node_modules/log4js'),
|
||||||
|
messageLogger = log4js.getLogger("SessionStore");
|
||||||
|
|
||||||
|
var SessionStore = module.exports = function SessionStore() {};
|
||||||
|
|
||||||
|
SessionStore.prototype.__proto__ = Store.prototype;
|
||||||
|
|
||||||
|
SessionStore.prototype.get = function(sid, fn){
|
||||||
|
messageLogger.debug('GET ' + sid);
|
||||||
|
var self = this;
|
||||||
|
db.get("sessionstorage:" + sid, function (err, sess)
|
||||||
|
{
|
||||||
|
if (sess) {
|
||||||
|
sess.cookie.expires = 'string' == typeof sess.cookie.expires ? new Date(sess.cookie.expires) : sess.cookie.expires;
|
||||||
|
if (!sess.cookie.expires || new Date() < expires) {
|
||||||
|
fn(null, sess);
|
||||||
|
} else {
|
||||||
|
self.destroy(sid, fn);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fn();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
SessionStore.prototype.set = function(sid, sess, fn){
|
||||||
|
messageLogger.debug('SET ' + sid);
|
||||||
|
db.set("sessionstorage:" + sid, sess);
|
||||||
|
process.nextTick(function(){
|
||||||
|
if(fn) fn();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
SessionStore.prototype.destroy = function(sid, fn){
|
||||||
|
messageLogger.debug('DESTROY ' + sid);
|
||||||
|
db.remove("sessionstorage:" + sid);
|
||||||
|
process.nextTick(function(){
|
||||||
|
if(fn) fn();
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
SessionStore.prototype.all = function(fn){
|
||||||
|
messageLogger.debug('ALL');
|
||||||
|
var sessions = [];
|
||||||
|
db.forEach(function(key, value){
|
||||||
|
if (key.substr(0,15) === "sessionstorage:") {
|
||||||
|
sessions.push(value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fn(null, sessions);
|
||||||
|
};
|
||||||
|
|
||||||
|
SessionStore.prototype.clear = function(fn){
|
||||||
|
messageLogger.debug('CLEAR');
|
||||||
|
db.forEach(function(key, value){
|
||||||
|
if (key.substr(0,15) === "sessionstorage:") {
|
||||||
|
db.db.remove("session:" + key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if(fn) fn();
|
||||||
|
};
|
||||||
|
|
||||||
|
SessionStore.prototype.length = function(fn){
|
||||||
|
messageLogger.debug('LENGTH');
|
||||||
|
var i = 0;
|
||||||
|
db.forEach(function(key, value){
|
||||||
|
if (key.substr(0,15) === "sessionstorage:") {
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
fn(null, i);
|
||||||
|
};
|
|
@ -216,6 +216,9 @@ var version =
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// set the latest available API version here
|
||||||
|
exports.latestApiVersion = '1.2.7';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Handles a HTTP API call
|
* Handles a HTTP API call
|
||||||
* @param functionName the name of the called function
|
* @param functionName the name of the called function
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
|
|
||||||
var ERR = require("async-stacktrace");
|
var ERR = require("async-stacktrace");
|
||||||
var exporthtml = require("../utils/ExportHtml");
|
var exporthtml = require("../utils/ExportHtml");
|
||||||
|
var exporttxt = require("../utils/ExportTxt");
|
||||||
var exportdokuwiki = require("../utils/ExportDokuWiki");
|
var exportdokuwiki = require("../utils/ExportDokuWiki");
|
||||||
var padManager = require("../db/PadManager");
|
var padManager = require("../db/PadManager");
|
||||||
var async = require("async");
|
var async = require("async");
|
||||||
|
@ -48,22 +49,75 @@ exports.doExport = function(req, res, padId, type)
|
||||||
res.attachment(padId + "." + type);
|
res.attachment(padId + "." + type);
|
||||||
|
|
||||||
//if this is a plain text export, we can do this directly
|
//if this is a plain text export, we can do this directly
|
||||||
|
// We have to over engineer this because tabs are stored as attributes and not plain text
|
||||||
|
|
||||||
if(type == "txt")
|
if(type == "txt")
|
||||||
{
|
{
|
||||||
padManager.getPad(padId, function(err, pad)
|
var txt;
|
||||||
|
var randNum;
|
||||||
|
var srcFile, destFile;
|
||||||
|
|
||||||
|
async.series([
|
||||||
|
//render the txt document
|
||||||
|
function(callback)
|
||||||
{
|
{
|
||||||
ERR(err);
|
exporttxt.getPadTXTDocument(padId, req.params.rev, false, function(err, _txt)
|
||||||
if(req.params.rev){
|
|
||||||
pad.getInternalRevisionAText(req.params.rev, function(junk, text)
|
|
||||||
{
|
{
|
||||||
res.send(text.text ? text.text : null);
|
if(ERR(err, callback)) return;
|
||||||
|
txt = _txt;
|
||||||
|
callback();
|
||||||
});
|
});
|
||||||
|
},
|
||||||
|
//decide what to do with the txt export
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
//if this is a txt export, we can send this from here directly
|
||||||
|
res.send(txt);
|
||||||
|
callback("stop");
|
||||||
|
},
|
||||||
|
//send the convert job to abiword
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
//ensure html can be collected by the garbage collector
|
||||||
|
txt = null;
|
||||||
|
|
||||||
|
destFile = tempDirectory + "/eplite_export_" + randNum + "." + type;
|
||||||
|
abiword.convertFile(srcFile, destFile, type, callback);
|
||||||
|
},
|
||||||
|
//send the file
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
res.sendfile(destFile, null, callback);
|
||||||
|
},
|
||||||
|
//clean up temporary files
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
async.parallel([
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
fs.unlink(srcFile, callback);
|
||||||
|
},
|
||||||
|
function(callback)
|
||||||
|
{
|
||||||
|
//100ms delay to accomidate for slow windows fs
|
||||||
|
if(os.type().indexOf("Windows") > -1)
|
||||||
|
{
|
||||||
|
setTimeout(function()
|
||||||
|
{
|
||||||
|
fs.unlink(destFile, callback);
|
||||||
|
}, 100);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
res.send(pad.text());
|
fs.unlink(destFile, callback);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
], callback);
|
||||||
|
}
|
||||||
|
], function(err)
|
||||||
|
{
|
||||||
|
if(err && err != "stop") ERR(err);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
else if(type == 'dokuwiki')
|
else if(type == 'dokuwiki')
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,14 +32,10 @@ var securityManager = require("../db/SecurityManager");
|
||||||
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins.js");
|
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins.js");
|
||||||
var log4js = require('log4js');
|
var log4js = require('log4js');
|
||||||
var messageLogger = log4js.getLogger("message");
|
var messageLogger = log4js.getLogger("message");
|
||||||
|
var accessLogger = log4js.getLogger("access");
|
||||||
var _ = require('underscore');
|
var _ = require('underscore');
|
||||||
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks.js");
|
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks.js");
|
||||||
|
|
||||||
/**
|
|
||||||
* A associative array that saves which sessions belong to a pad
|
|
||||||
*/
|
|
||||||
var pad2sessions = {};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A associative array that saves informations about a session
|
* A associative array that saves informations about a session
|
||||||
* key = sessionId
|
* key = sessionId
|
||||||
|
@ -83,14 +79,11 @@ exports.handleConnect = function(client)
|
||||||
exports.kickSessionsFromPad = function(padID)
|
exports.kickSessionsFromPad = function(padID)
|
||||||
{
|
{
|
||||||
//skip if there is nobody on this pad
|
//skip if there is nobody on this pad
|
||||||
if(!pad2sessions[padID])
|
if(socketio.sockets.clients(padID).length == 0)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//disconnect everyone from this pad
|
//disconnect everyone from this pad
|
||||||
for(var i in pad2sessions[padID])
|
socketio.sockets.in(padID).json.send({disconnect:"deleted"});
|
||||||
{
|
|
||||||
socketio.sockets.sockets[pad2sessions[padID][i]].json.send({disconnect:"deleted"});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -100,15 +93,13 @@ exports.kickSessionsFromPad = function(padID)
|
||||||
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 session = sessioninfos[client.id];
|
||||||
|
|
||||||
//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(session && session.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(session.author, function(err, color)
|
||||||
{
|
{
|
||||||
ERR(err);
|
ERR(err);
|
||||||
|
|
||||||
|
@ -121,32 +112,19 @@ exports.handleDisconnect = function(client)
|
||||||
"ip": "127.0.0.1",
|
"ip": "127.0.0.1",
|
||||||
"colorId": color,
|
"colorId": color,
|
||||||
"userAgent": "Anonymous",
|
"userAgent": "Anonymous",
|
||||||
"userId": author
|
"userId": session.author
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//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])
|
client.broadcast.to(session.padId).json.send(messageToTheOtherUsers);
|
||||||
{
|
|
||||||
var socket = socketio.sockets.sockets[pad2sessions[sessionPad][i]];
|
|
||||||
if(socket !== undefined){
|
|
||||||
socket.json.send(messageToTheOtherUsers);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Go trough all sessions of this pad, search and destroy the entry of this client
|
client.get('remoteAddress', function(er, ip) {
|
||||||
for(i in pad2sessions[sessionPad])
|
accessLogger.info('[LEAVE] Pad "'+session.padId+'": Author "'+session.author+'" on client '+client.id+' with IP "'+ip+'" left the pad')
|
||||||
{
|
})
|
||||||
if(pad2sessions[sessionPad][i] == client.id)
|
|
||||||
{
|
|
||||||
pad2sessions[sessionPad].splice(i, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Delete the sessioninfos entrys of this session
|
//Delete the sessioninfos entrys of this session
|
||||||
delete sessioninfos[client.id];
|
delete sessioninfos[client.id];
|
||||||
|
@ -228,11 +206,10 @@ exports.handleMessage = function(client, message)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
|
|
||||||
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();
|
if(!message.padId)
|
||||||
return;
|
return callback();
|
||||||
}
|
|
||||||
// Note: message.sessionID is an entirely different kind of
|
// Note: message.sessionID is an entirely different kind of
|
||||||
// session from the sessions we use here! Beware! FIXME: Call
|
// session from the sessions we use here! Beware! FIXME: Call
|
||||||
// our "sessions" "connections".
|
// our "sessions" "connections".
|
||||||
|
@ -292,9 +269,7 @@ exports.handleCustomMessage = function (padID, msg, cb) {
|
||||||
time: time
|
time: time
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
for (var i in pad2sessions[padID]) {
|
socketio.sockets.in(padID).json.send(msg);
|
||||||
socketio.sockets.sockets[pad2sessions[padID][i]].json.send(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
cb(null, {});
|
cb(null, {});
|
||||||
}
|
}
|
||||||
|
@ -352,10 +327,7 @@ function handleChatMessage(client, message)
|
||||||
};
|
};
|
||||||
|
|
||||||
//broadcast the chat message to everyone on the pad
|
//broadcast the chat message to everyone on the pad
|
||||||
for(var i in pad2sessions[padId])
|
socketio.sockets.in(padId).json.send(msg);
|
||||||
{
|
|
||||||
socketio.sockets.sockets[pad2sessions[padId][i]].json.send(msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
callback();
|
callback();
|
||||||
}
|
}
|
||||||
|
@ -422,14 +394,7 @@ function handleGetChatMessages(client, message)
|
||||||
};
|
};
|
||||||
|
|
||||||
// send the messages back to the client
|
// send the messages back to the client
|
||||||
for(var i in pad2sessions[padId])
|
client.json.send(infoMsg);
|
||||||
{
|
|
||||||
if(pad2sessions[padId][i] == client.id)
|
|
||||||
{
|
|
||||||
socketio.sockets.sockets[pad2sessions[padId][i]].json.send(infoMsg);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}]);
|
}]);
|
||||||
}
|
}
|
||||||
|
@ -453,14 +418,14 @@ function handleSuggestUserName(client, message)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var padId = sessioninfos[client.id].padId;
|
var padId = sessioninfos[client.id].padId,
|
||||||
|
clients = socketio.sockets.clients(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 = 0; i < clients.length; i++) {
|
||||||
{
|
var session = sessioninfos[clients[i].id];
|
||||||
if(sessioninfos[pad2sessions[padId][i]].author == message.data.payload.unnamedId)
|
if(session && session.author == message.data.payload.unnamedId) {
|
||||||
{
|
clients[i].json.send(message);
|
||||||
socketio.sockets.sockets[pad2sessions[padId][i]].send(message);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -501,7 +466,8 @@ function handleUserInfoUpdate(client, message)
|
||||||
type: "USER_NEWINFO",
|
type: "USER_NEWINFO",
|
||||||
userInfo: {
|
userInfo: {
|
||||||
userId: author,
|
userId: author,
|
||||||
name: message.data.userInfo.name,
|
//set a null name, when there is no name set. cause the client wants it null
|
||||||
|
name: message.data.userInfo.name || null,
|
||||||
colorId: message.data.userInfo.colorId,
|
colorId: message.data.userInfo.colorId,
|
||||||
userAgent: "Anonymous",
|
userAgent: "Anonymous",
|
||||||
ip: "127.0.0.1",
|
ip: "127.0.0.1",
|
||||||
|
@ -509,20 +475,8 @@ function handleUserInfoUpdate(client, message)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//set a null name, when there is no name set. cause the client wants it null
|
|
||||||
if(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])
|
client.broadcast.to(padId).json.send(infoMsg);
|
||||||
{
|
|
||||||
if(pad2sessions[padId][i] != client.id)
|
|
||||||
{
|
|
||||||
socketio.sockets.sockets[pad2sessions[padId][i]].json.send(infoMsg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -632,7 +586,14 @@ function handleUserChanges(client, message)
|
||||||
// client) are relative to revision r - 1. The follow function
|
// client) are relative to revision r - 1. The follow function
|
||||||
// rebases "changeset" so that it is relative to revision r
|
// rebases "changeset" so that it is relative to revision r
|
||||||
// and can be applied after "c".
|
// and can be applied after "c".
|
||||||
|
try
|
||||||
|
{
|
||||||
changeset = Changeset.follow(c, changeset, false, apool);
|
changeset = Changeset.follow(c, changeset, false, apool);
|
||||||
|
}catch(e){
|
||||||
|
console.warn("Can't apply USER_CHANGES "+changeset+", possibly because of mismatched follow error");
|
||||||
|
client.json.send({disconnect:"badChangeset"});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((r - baseRev) % 200 == 0) { // don't let the stack get too deep
|
if ((r - baseRev) % 200 == 0) { // don't let the stack get too deep
|
||||||
async.nextTick(callback);
|
async.nextTick(callback);
|
||||||
|
@ -682,65 +643,53 @@ 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])
|
var roomClients = socketio.sockets.clients(pad.id);
|
||||||
{
|
if(roomClients.length==0)
|
||||||
callback();
|
return callback();
|
||||||
return;
|
|
||||||
}
|
// since all clients usually get the same set of changesets, store them in local cache
|
||||||
|
// to remove unnecessary roundtrip to the datalayer
|
||||||
|
// TODO: in REAL world, if we're working without datalayer cache, all requests to revisions will be fired
|
||||||
|
// BEFORE first result will be landed to our cache object. The solution is to replace parallel processing
|
||||||
|
// via async.forEach with sequential for() loop. There is no real benefits of running this in parallel,
|
||||||
|
// but benefit of reusing cached revision object is HUGE
|
||||||
|
var revCache = {};
|
||||||
|
|
||||||
//go trough all sessions on this pad
|
//go trough all sessions on this pad
|
||||||
async.forEach(pad2sessions[pad.id], function(session, callback)
|
async.forEach(roomClients, function(client, callback)
|
||||||
{
|
{
|
||||||
|
var sid = client.id;
|
||||||
|
|
||||||
//https://github.com/caolan/async#whilst
|
//https://github.com/caolan/async#whilst
|
||||||
//send them all new changesets
|
//send them all new changesets
|
||||||
async.whilst(
|
async.whilst(
|
||||||
function (){ return sessioninfos[session] && sessioninfos[session].rev < pad.getHeadRevisionNumber()},
|
function (){ return sessioninfos[sid] && sessioninfos[sid].rev < pad.getHeadRevisionNumber()},
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
var author, revChangeset, currentTime;
|
var r = sessioninfos[sid].rev + 1;
|
||||||
var r = sessioninfos[session].rev + 1;
|
|
||||||
|
|
||||||
async.parallel([
|
async.waterfall([
|
||||||
function (callback)
|
function(callback) {
|
||||||
{
|
if(revCache[r])
|
||||||
pad.getRevisionAuthor(r, function(err, value)
|
callback(null, revCache[r]);
|
||||||
{
|
else
|
||||||
if(ERR(err, callback)) return;
|
pad.getRevision(r, callback);
|
||||||
author = value;
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
function (callback)
|
function(revision, callback)
|
||||||
{
|
{
|
||||||
pad.getRevisionChangeset(r, function(err, value)
|
revCache[r] = revision;
|
||||||
{
|
|
||||||
if(ERR(err, callback)) return;
|
var author = revision.meta.author,
|
||||||
revChangeset = value;
|
revChangeset = revision.changeset,
|
||||||
callback();
|
currentTime = revision.meta.timestamp;
|
||||||
});
|
|
||||||
},
|
|
||||||
function (callback)
|
|
||||||
{
|
|
||||||
pad.getRevisionDate(r, function(err, date)
|
|
||||||
{
|
|
||||||
if(ERR(err, callback)) return;
|
|
||||||
currentTime = date;
|
|
||||||
callback();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
], function(err)
|
|
||||||
{
|
|
||||||
if(ERR(err, callback)) return;
|
|
||||||
// next if session has not been deleted
|
// next if session has not been deleted
|
||||||
if(sessioninfos[session] == null)
|
if(sessioninfos[sid] == null)
|
||||||
|
return callback(null);
|
||||||
|
|
||||||
|
if(author == sessioninfos[sid].author)
|
||||||
{
|
{
|
||||||
callback(null);
|
client.json.send({"type":"COLLABROOM","data":{type:"ACCEPT_COMMIT", newRev:r}});
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(author == sessioninfos[session].author)
|
|
||||||
{
|
|
||||||
socketio.sockets.sockets[session].json.send({"type":"COLLABROOM","data":{type:"ACCEPT_COMMIT", newRev:r}});
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -752,20 +701,18 @@ exports.updatePadClients = function(pad, callback)
|
||||||
apool: forWire.pool,
|
apool: forWire.pool,
|
||||||
author: author,
|
author: author,
|
||||||
currentTime: currentTime,
|
currentTime: currentTime,
|
||||||
timeDelta: currentTime - sessioninfos[session].time
|
timeDelta: currentTime - sessioninfos[sid].time
|
||||||
}};
|
}};
|
||||||
|
|
||||||
socketio.sockets.sockets[session].json.send(wireMsg);
|
client.json.send(wireMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sessioninfos[session] != null)
|
sessioninfos[sid].time = currentTime;
|
||||||
{
|
sessioninfos[sid].rev = r;
|
||||||
sessioninfos[session].time = currentTime;
|
|
||||||
sessioninfos[session].rev = r;
|
|
||||||
}
|
|
||||||
|
|
||||||
callback(null);
|
callback(null);
|
||||||
});
|
}
|
||||||
|
], callback);
|
||||||
},
|
},
|
||||||
callback
|
callback
|
||||||
);
|
);
|
||||||
|
@ -895,23 +842,14 @@ function handleClientReady(client, message)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
async.parallel([
|
async.parallel([
|
||||||
//get colorId
|
//get colorId and name
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
authorManager.getAuthorColorId(author, function(err, value)
|
authorManager.getAuthor(author, function(err, value)
|
||||||
{
|
{
|
||||||
if(ERR(err, callback)) return;
|
if(ERR(err, callback)) return;
|
||||||
authorColorId = value;
|
authorColorId = value.colorId;
|
||||||
callback();
|
authorName = value.name;
|
||||||
});
|
|
||||||
},
|
|
||||||
//get author name
|
|
||||||
function(callback)
|
|
||||||
{
|
|
||||||
authorManager.getAuthorName(author, function(err, value)
|
|
||||||
{
|
|
||||||
if(ERR(err, callback)) return;
|
|
||||||
authorName = value;
|
|
||||||
callback();
|
callback();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -965,21 +903,17 @@ function handleClientReady(client, message)
|
||||||
{
|
{
|
||||||
//Check that the client is still here. It might have disconnected between callbacks.
|
//Check that the client is still here. It might have disconnected between callbacks.
|
||||||
if(sessioninfos[client.id] === undefined)
|
if(sessioninfos[client.id] === undefined)
|
||||||
{
|
return callback();
|
||||||
callback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check if this author is already on the pad, if yes, kick the other sessions!
|
//Check if this author is already on the pad, if yes, kick the other sessions!
|
||||||
if(pad2sessions[padIds.padId])
|
var roomClients = socketio.sockets.clients(padIds.padId);
|
||||||
{
|
for(var i = 0; i < roomClients.length; i++) {
|
||||||
for(var i in pad2sessions[padIds.padId])
|
var sinfo = sessioninfos[roomClients[i].id];
|
||||||
{
|
if(sinfo && sinfo.author == author) {
|
||||||
if(sessioninfos[pad2sessions[padIds.padId][i]] && sessioninfos[pad2sessions[padIds.padId][i]].author == author)
|
// fix user's counter, works on page refresh or if user closes browser window and then rejoins
|
||||||
{
|
sessioninfos[roomClients[i].id] = {};
|
||||||
var socket = socketio.sockets.sockets[pad2sessions[padIds.padId][i]];
|
roomClients[i].leave(padIds.padId);
|
||||||
if(socket) socket.json.send({disconnect:"userdup"});
|
roomClients[i].json.send({disconnect:"userdup"});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -988,18 +922,21 @@ function handleClientReady(client, message)
|
||||||
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
|
//Log creation/(re-)entering of a pad
|
||||||
if(!pad2sessions[padIds.padId])
|
client.get('remoteAddress', function(er, ip) {
|
||||||
{
|
if(pad.head > 0) {
|
||||||
pad2sessions[padIds.padId] = [];
|
accessLogger.info('[ENTER] Pad "'+padIds.padId+'": Client '+client.id+' with IP "'+ip+'" entered the pad');
|
||||||
}
|
}
|
||||||
|
else if(pad.head == 0) {
|
||||||
//Saves in pad2sessions that this session belongs to this pad
|
accessLogger.info('[CREATE] Pad "'+padIds.padId+'": Client '+client.id+' with IP "'+ip+'" created the pad');
|
||||||
pad2sessions[padIds.padId].push(client.id);
|
}
|
||||||
|
})
|
||||||
|
|
||||||
//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)
|
||||||
{
|
{
|
||||||
|
//Join the pad and start receiving updates
|
||||||
|
client.join(padIds.padId);
|
||||||
//Save the revision in sessioninfos, we take the revision from the info the client send to us
|
//Save the revision in sessioninfos, we take the revision from the info the client send to us
|
||||||
sessioninfos[client.id].rev = message.client_rev;
|
sessioninfos[client.id].rev = message.client_rev;
|
||||||
}
|
}
|
||||||
|
@ -1044,17 +981,12 @@ function handleClientReady(client, message)
|
||||||
// tell the client the number of the latest chat-message, which will be
|
// tell the client the number of the latest chat-message, which will be
|
||||||
// used to request the latest 100 chat-messages later (GET_CHAT_MESSAGES)
|
// used to request the latest 100 chat-messages later (GET_CHAT_MESSAGES)
|
||||||
"chatHead": pad.chatHead,
|
"chatHead": pad.chatHead,
|
||||||
"numConnectedUsers": pad2sessions[padIds.padId].length,
|
"numConnectedUsers": roomClients.length,
|
||||||
"isProPad": false,
|
|
||||||
"readOnlyId": padIds.readOnlyPadId,
|
"readOnlyId": padIds.readOnlyPadId,
|
||||||
"readonly": padIds.readonly,
|
"readonly": padIds.readonly,
|
||||||
"serverTimestamp": new Date().getTime(),
|
"serverTimestamp": new Date().getTime(),
|
||||||
"globalPadId": message.padId,
|
"globalPadId": message.padId,
|
||||||
"userId": author,
|
"userId": author,
|
||||||
"cookiePrefsToSet": {
|
|
||||||
"fullWidth": false,
|
|
||||||
"hideSidebar": false
|
|
||||||
},
|
|
||||||
"abiwordAvailable": settings.abiwordAvailable(),
|
"abiwordAvailable": settings.abiwordAvailable(),
|
||||||
"plugins": {
|
"plugins": {
|
||||||
"plugins": plugins.plugins,
|
"plugins": plugins.plugins,
|
||||||
|
@ -1080,6 +1012,8 @@ function handleClientReady(client, message)
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Join the pad and start receiving updates
|
||||||
|
client.join(padIds.padId);
|
||||||
//Send the clientVars to the Client
|
//Send the clientVars to the Client
|
||||||
client.json.send({type: "CLIENT_VARS", data: clientVars});
|
client.json.send({type: "CLIENT_VARS", data: clientVars});
|
||||||
//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
|
||||||
|
@ -1109,71 +1043,53 @@ function handleClientReady(client, message)
|
||||||
messageToTheOtherUsers.data.userInfo.name = authorName;
|
messageToTheOtherUsers.data.userInfo.name = authorName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// notify all existing users about new user
|
||||||
|
client.broadcast.to(padIds.padId).json.send(messageToTheOtherUsers);
|
||||||
|
|
||||||
//Run trough all sessions of this pad
|
//Run trough all sessions of this pad
|
||||||
async.forEach(pad2sessions[padIds.padId], function(sessionID, callback)
|
async.forEach(socketio.sockets.clients(padIds.padId), function(roomClient, callback)
|
||||||
{
|
{
|
||||||
var author, socket, sessionAuthorName, sessionAuthorColorId;
|
var author;
|
||||||
|
|
||||||
|
//Jump over, if this session is the connection session
|
||||||
|
if(roomClient.id == client.id)
|
||||||
|
return callback();
|
||||||
|
|
||||||
|
|
||||||
//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[roomClient.id] !== undefined)
|
||||||
socketio.sockets.sockets[sessionID] !== undefined){
|
author = sessioninfos[roomClient.id].author;
|
||||||
author = sessioninfos[sessionID].author;
|
else // If the client id is not valid, callback();
|
||||||
socket = socketio.sockets.sockets[sessionID];
|
return callback();
|
||||||
}else {
|
|
||||||
// If the sessionID is not valid, callback();
|
async.waterfall([
|
||||||
callback();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
async.series([
|
|
||||||
//get the authorname & colorId
|
//get the authorname & colorId
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
async.parallel([
|
// reuse previously created cache of author's data
|
||||||
function(callback)
|
if(historicalAuthorData[author])
|
||||||
{
|
callback(null, historicalAuthorData[author]);
|
||||||
authorManager.getAuthorColorId(author, function(err, value)
|
else
|
||||||
{
|
authorManager.getAuthor(author, callback);
|
||||||
if(ERR(err, callback)) return;
|
|
||||||
sessionAuthorColorId = value;
|
|
||||||
callback();
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
function(callback)
|
function (authorInfo, callback)
|
||||||
{
|
{
|
||||||
authorManager.getAuthorName(author, function(err, value)
|
|
||||||
{
|
|
||||||
if(ERR(err, callback)) return;
|
|
||||||
sessionAuthorName = value;
|
|
||||||
callback();
|
|
||||||
})
|
|
||||||
}
|
|
||||||
],callback);
|
|
||||||
},
|
|
||||||
function (callback)
|
|
||||||
{
|
|
||||||
//Jump over, if this session is the connection session
|
|
||||||
if(sessionID != client.id)
|
|
||||||
{
|
|
||||||
//Send this Session the Notification about the new user
|
|
||||||
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 msg = {
|
||||||
"type": "COLLABROOM",
|
"type": "COLLABROOM",
|
||||||
"data": {
|
"data": {
|
||||||
type: "USER_NEWINFO",
|
type: "USER_NEWINFO",
|
||||||
userInfo: {
|
userInfo: {
|
||||||
"ip": "127.0.0.1",
|
"ip": "127.0.0.1",
|
||||||
"colorId": sessionAuthorColorId,
|
"colorId": authorInfo.colorId,
|
||||||
"name": sessionAuthorName,
|
"name": authorInfo.name,
|
||||||
"userAgent": "Anonymous",
|
"userAgent": "Anonymous",
|
||||||
"userId": author
|
"userId": author
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
client.json.send(messageToNotifyTheClientAboutTheOthers);
|
client.json.send(msg);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
], callback);
|
], callback);
|
||||||
}, callback);
|
}, callback);
|
||||||
|
@ -1521,33 +1437,30 @@ function composePadChangesets(padId, startNum, endNum, callback)
|
||||||
* Get the number of users in a pad
|
* Get the number of users in a pad
|
||||||
*/
|
*/
|
||||||
exports.padUsersCount = function (padID, callback) {
|
exports.padUsersCount = function (padID, callback) {
|
||||||
if (!pad2sessions[padID] || typeof pad2sessions[padID] != typeof []) {
|
callback(null, {
|
||||||
callback(null, {padUsersCount: 0});
|
padUsersCount: socketio.sockets.clients(padID).length
|
||||||
} else {
|
});
|
||||||
callback(null, {padUsersCount: pad2sessions[padID].length});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the list of users in a pad
|
* Get the list of users in a pad
|
||||||
*/
|
*/
|
||||||
exports.padUsers = function (padID, callback) {
|
exports.padUsers = function (padID, callback) {
|
||||||
if (!pad2sessions[padID] || typeof pad2sessions[padID] != typeof []) {
|
var result = [];
|
||||||
callback(null, {padUsers: []});
|
|
||||||
} else {
|
async.forEach(socketio.sockets.clients(padId), function(roomClient, callback) {
|
||||||
var authors = [];
|
var s = sessioninfos[roomClient.id];
|
||||||
for ( var ix in sessioninfos ) {
|
if(s) {
|
||||||
if ( sessioninfos[ix].padId !== padID ) {
|
authorManager.getAuthor(s.author, function(err, author) {
|
||||||
continue;
|
if(ERR(err, callback)) return;
|
||||||
}
|
|
||||||
var aid = sessioninfos[ix].author;
|
author.id = s.author;
|
||||||
authorManager.getAuthor( aid, function ( err, author ) {
|
result.push(author);
|
||||||
author.id = aid;
|
});
|
||||||
authors.push( author );
|
|
||||||
if ( authors.length === pad2sessions[padID].length ) {
|
|
||||||
callback(null, {padUsers: authors});
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}, function(err) {
|
||||||
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
|
callback(null, {padUsers: result});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -55,13 +55,14 @@ exports.setSocketIO = function(_socket)
|
||||||
|
|
||||||
socket.sockets.on('connection', function(client)
|
socket.sockets.on('connection', function(client)
|
||||||
{
|
{
|
||||||
|
client.set('remoteAddress', client.handshake.address.address);
|
||||||
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)
|
||||||
{
|
{
|
||||||
messageLogger.info("to " + client.id + ": " + stringifyWithoutPassword(message));
|
messageLogger.debug("to " + client.id + ": " + stringifyWithoutPassword(message));
|
||||||
client._send(message);
|
client._send(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +80,7 @@ exports.setSocketIO = function(_socket)
|
||||||
//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.debug("from " + client.id + ": " + stringifyWithoutPassword(message));
|
||||||
components[message.component].handleMessage(client, message);
|
components[message.component].handleMessage(client, message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -57,4 +57,9 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
res.end("OK");
|
res.end("OK");
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
//Provide a possibility to query the latest available API version
|
||||||
|
args.app.get('/api', function (req, res) {
|
||||||
|
res.json({"currentVersion" : apiHandler.latestApiVersion});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,26 @@
|
||||||
var path = require("path")
|
var path = require("path")
|
||||||
, npm = require("npm")
|
, npm = require("npm")
|
||||||
, fs = require("fs");
|
, fs = require("fs")
|
||||||
|
, async = require("async");
|
||||||
|
|
||||||
exports.expressCreateServer = function (hook_name, args, cb) {
|
exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
args.app.get('/tests/frontend/specs_list.js', function(req, res){
|
args.app.get('/tests/frontend/specs_list.js', function(req, res){
|
||||||
fs.readdir('tests/frontend/specs', function(err, files){
|
|
||||||
if(err){ return res.send(500); }
|
|
||||||
|
|
||||||
|
async.parallel({
|
||||||
|
coreSpecs: function(callback){
|
||||||
|
exports.getCoreTests(callback);
|
||||||
|
},
|
||||||
|
pluginSpecs: function(callback){
|
||||||
|
exports.getPluginTests(callback);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
function(err, results){
|
||||||
|
var files = results.coreSpecs; // push the core specs to a file object
|
||||||
|
files = files.concat(results.pluginSpecs); // add the plugin Specs to the core specs
|
||||||
|
console.debug("Sent browser the following test specs:", files.sort());
|
||||||
res.send("var specs_list = " + JSON.stringify(files.sort()) + ";\n");
|
res.send("var specs_list = " + JSON.stringify(files.sort()) + ";\n");
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var url2FilePath = function(url){
|
var url2FilePath = function(url){
|
||||||
|
@ -45,3 +57,28 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
res.redirect('/tests/frontend/');
|
res.redirect('/tests/frontend/');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
exports.getPluginTests = function(callback){
|
||||||
|
var pluginSpecs = [];
|
||||||
|
var plugins = fs.readdirSync('node_modules');
|
||||||
|
plugins.forEach(function(plugin){
|
||||||
|
if(fs.existsSync("node_modules/"+plugin+"/static/tests/frontend/specs")){ // if plugins exists
|
||||||
|
var specFiles = fs.readdirSync("node_modules/"+plugin+"/static/tests/frontend/specs/");
|
||||||
|
async.forEach(specFiles, function(spec){ // for each specFile push it to pluginSpecs
|
||||||
|
pluginSpecs.push("/static/plugins/"+plugin+"/static/tests/frontend/specs/" + spec);
|
||||||
|
},
|
||||||
|
function(err){
|
||||||
|
// blow up if something bad happens!
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
callback(null, pluginSpecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getCoreTests = function(callback){
|
||||||
|
fs.readdir('tests/frontend/specs', function(err, coreSpecs){ // get the core test specs
|
||||||
|
if(err){ return res.send(500); }
|
||||||
|
callback(null, coreSpecs);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ var httpLogger = log4js.getLogger("http");
|
||||||
var settings = require('../../utils/Settings');
|
var settings = require('../../utils/Settings');
|
||||||
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||||
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||||
|
var ueberStore = require('../../db/SessionStore');
|
||||||
|
|
||||||
//checks for basic http auth
|
//checks for basic http auth
|
||||||
exports.basicAuth = function (req, res, next) {
|
exports.basicAuth = function (req, res, next) {
|
||||||
|
@ -102,15 +102,14 @@ exports.expressConfigure = function (hook_name, args, cb) {
|
||||||
* handling it cleaner :) */
|
* handling it cleaner :) */
|
||||||
|
|
||||||
if (!exports.sessionStore) {
|
if (!exports.sessionStore) {
|
||||||
exports.sessionStore = new express.session.MemoryStore();
|
exports.sessionStore = new ueberStore();
|
||||||
exports.secret = randomString(32);
|
exports.secret = settings.sessionKey; // Isn't this being reset each time the server spawns?
|
||||||
}
|
}
|
||||||
|
|
||||||
args.app.use(express.cookieParser(exports.secret));
|
args.app.use(express.cookieParser(exports.secret));
|
||||||
|
|
||||||
args.app.sessionStore = exports.sessionStore;
|
args.app.sessionStore = exports.sessionStore;
|
||||||
args.app.use(express.session({store: args.app.sessionStore,
|
args.app.use(express.session({secret: exports.secret, store: args.app.sessionStore, key: 'express_sid' }));
|
||||||
key: 'express_sid' }));
|
|
||||||
|
|
||||||
args.app.use(exports.basicAuth);
|
args.app.use(exports.basicAuth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
87
src/node/utils/ExportHelper.js
Normal file
87
src/node/utils/ExportHelper.js
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
/**
|
||||||
|
* Helpers for export requests
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var async = require("async");
|
||||||
|
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||||
|
var padManager = require("../db/PadManager");
|
||||||
|
var ERR = require("async-stacktrace");
|
||||||
|
var Security = require('ep_etherpad-lite/static/js/security');
|
||||||
|
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||||
|
|
||||||
|
exports.getPadPlainText = function(pad, revNum){
|
||||||
|
var atext = ((revNum !== undefined) ? pad.getInternalRevisionAText(revNum) : pad.atext());
|
||||||
|
var textLines = atext.text.slice(0, -1).split('\n');
|
||||||
|
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
|
||||||
|
var apool = pad.pool();
|
||||||
|
|
||||||
|
var pieces = [];
|
||||||
|
for (var i = 0; i < textLines.length; i++){
|
||||||
|
var line = _analyzeLine(textLines[i], attribLines[i], apool);
|
||||||
|
if (line.listLevel){
|
||||||
|
var numSpaces = line.listLevel * 2 - 1;
|
||||||
|
var bullet = '*';
|
||||||
|
pieces.push(new Array(numSpaces + 1).join(' '), bullet, ' ', line.text, '\n');
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
pieces.push(line.text, '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pieces.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exports._analyzeLine = function(text, aline, apool){
|
||||||
|
var line = {};
|
||||||
|
|
||||||
|
// identify list
|
||||||
|
var lineMarker = 0;
|
||||||
|
line.listLevel = 0;
|
||||||
|
if (aline){
|
||||||
|
var opIter = Changeset.opIterator(aline);
|
||||||
|
if (opIter.hasNext()){
|
||||||
|
var listType = Changeset.opAttributeValue(opIter.next(), 'list', apool);
|
||||||
|
if (listType){
|
||||||
|
lineMarker = 1;
|
||||||
|
listType = /([a-z]+)([12345678])/.exec(listType);
|
||||||
|
if (listType){
|
||||||
|
line.listTypeName = listType[1];
|
||||||
|
line.listLevel = Number(listType[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (lineMarker){
|
||||||
|
line.text = text.substring(1);
|
||||||
|
line.aline = Changeset.subattribution(aline, 1);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
line.text = text;
|
||||||
|
line.aline = aline;
|
||||||
|
}
|
||||||
|
return line;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
exports._encodeWhitespace = function(s){
|
||||||
|
return s.replace(/[^\x21-\x7E\s\t\n\r]/g, function(c){
|
||||||
|
return "&#" +c.charCodeAt(0) + ";"
|
||||||
|
});
|
||||||
|
}
|
|
@ -21,31 +21,9 @@ var padManager = require("../db/PadManager");
|
||||||
var ERR = require("async-stacktrace");
|
var ERR = require("async-stacktrace");
|
||||||
var Security = require('ep_etherpad-lite/static/js/security');
|
var Security = require('ep_etherpad-lite/static/js/security');
|
||||||
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||||
function getPadPlainText(pad, revNum)
|
var getPadPlainText = require('./ExportHelper').getPadPlainText
|
||||||
{
|
var _analyzeLine = require('./ExportHelper')._analyzeLine;
|
||||||
var atext = ((revNum !== undefined) ? pad.getInternalRevisionAText(revNum) : pad.atext());
|
var _encodeWhitespace = require('./ExportHelper')._encodeWhitespace;
|
||||||
var textLines = atext.text.slice(0, -1).split('\n');
|
|
||||||
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
|
|
||||||
var apool = pad.pool();
|
|
||||||
|
|
||||||
var pieces = [];
|
|
||||||
for (var i = 0; i < textLines.length; i++)
|
|
||||||
{
|
|
||||||
var line = _analyzeLine(textLines[i], attribLines[i], apool);
|
|
||||||
if (line.listLevel)
|
|
||||||
{
|
|
||||||
var numSpaces = line.listLevel * 2 - 1;
|
|
||||||
var bullet = '*';
|
|
||||||
pieces.push(new Array(numSpaces + 1).join(' '), bullet, ' ', line.text, '\n');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
pieces.push(line.text, '\n');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pieces.join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
function getPadHTML(pad, revNum, callback)
|
function getPadHTML(pad, revNum, callback)
|
||||||
{
|
{
|
||||||
|
@ -503,45 +481,6 @@ function getHTMLFromAtext(pad, atext, authorColors)
|
||||||
return pieces.join('');
|
return pieces.join('');
|
||||||
}
|
}
|
||||||
|
|
||||||
function _analyzeLine(text, aline, apool)
|
|
||||||
{
|
|
||||||
var line = {};
|
|
||||||
|
|
||||||
// identify list
|
|
||||||
var lineMarker = 0;
|
|
||||||
line.listLevel = 0;
|
|
||||||
if (aline)
|
|
||||||
{
|
|
||||||
var opIter = Changeset.opIterator(aline);
|
|
||||||
if (opIter.hasNext())
|
|
||||||
{
|
|
||||||
var listType = Changeset.opAttributeValue(opIter.next(), 'list', apool);
|
|
||||||
if (listType)
|
|
||||||
{
|
|
||||||
lineMarker = 1;
|
|
||||||
listType = /([a-z]+)([12345678])/.exec(listType);
|
|
||||||
if (listType)
|
|
||||||
{
|
|
||||||
line.listTypeName = listType[1];
|
|
||||||
line.listLevel = Number(listType[2]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (lineMarker)
|
|
||||||
{
|
|
||||||
line.text = text.substring(1);
|
|
||||||
line.aline = Changeset.subattribution(aline, 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
line.text = text;
|
|
||||||
line.aline = aline;
|
|
||||||
}
|
|
||||||
|
|
||||||
return line;
|
|
||||||
}
|
|
||||||
|
|
||||||
exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
|
exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
|
||||||
{
|
{
|
||||||
padManager.getPad(padId, function (err, pad)
|
padManager.getPad(padId, function (err, pad)
|
||||||
|
@ -578,79 +517,6 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function _encodeWhitespace(s) {
|
|
||||||
return s.replace(/[^\x21-\x7E\s\t\n\r]/g, function(c)
|
|
||||||
{
|
|
||||||
return "&#" +c.charCodeAt(0) + ";"
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// copied from ACE
|
|
||||||
|
|
||||||
|
|
||||||
function _processSpaces(s)
|
|
||||||
{
|
|
||||||
var doesWrap = true;
|
|
||||||
if (s.indexOf("<") < 0 && !doesWrap)
|
|
||||||
{
|
|
||||||
// short-cut
|
|
||||||
return s.replace(/ /g, ' ');
|
|
||||||
}
|
|
||||||
var parts = [];
|
|
||||||
s.replace(/<[^>]*>?| |[^ <]+/g, function (m)
|
|
||||||
{
|
|
||||||
parts.push(m);
|
|
||||||
});
|
|
||||||
if (doesWrap)
|
|
||||||
{
|
|
||||||
var endOfLine = true;
|
|
||||||
var beforeSpace = false;
|
|
||||||
// last space in a run is normal, others are nbsp,
|
|
||||||
// end of line is nbsp
|
|
||||||
for (var i = parts.length - 1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
var p = parts[i];
|
|
||||||
if (p == " ")
|
|
||||||
{
|
|
||||||
if (endOfLine || beforeSpace) parts[i] = ' ';
|
|
||||||
endOfLine = false;
|
|
||||||
beforeSpace = true;
|
|
||||||
}
|
|
||||||
else if (p.charAt(0) != "<")
|
|
||||||
{
|
|
||||||
endOfLine = false;
|
|
||||||
beforeSpace = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// beginning of line is nbsp
|
|
||||||
for (var i = 0; i < parts.length; i++)
|
|
||||||
{
|
|
||||||
var p = parts[i];
|
|
||||||
if (p == " ")
|
|
||||||
{
|
|
||||||
parts[i] = ' ';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else if (p.charAt(0) != "<")
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (var i = 0; i < parts.length; i++)
|
|
||||||
{
|
|
||||||
var p = parts[i];
|
|
||||||
if (p == " ")
|
|
||||||
{
|
|
||||||
parts[i] = ' ';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return parts.join('');
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// copied from ACE
|
// copied from ACE
|
||||||
var _REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/;
|
var _REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/;
|
||||||
|
@ -676,3 +542,57 @@ function _findURLs(text)
|
||||||
|
|
||||||
return urls;
|
return urls;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// copied from ACE
|
||||||
|
function _processSpaces(s){
|
||||||
|
var doesWrap = true;
|
||||||
|
if (s.indexOf("<") < 0 && !doesWrap){
|
||||||
|
// short-cut
|
||||||
|
return s.replace(/ /g, ' ');
|
||||||
|
}
|
||||||
|
var parts = [];
|
||||||
|
s.replace(/<[^>]*>?| |[^ <]+/g, function (m){
|
||||||
|
parts.push(m);
|
||||||
|
});
|
||||||
|
if (doesWrap){
|
||||||
|
var endOfLine = true;
|
||||||
|
var beforeSpace = false;
|
||||||
|
// last space in a run is normal, others are nbsp,
|
||||||
|
// end of line is nbsp
|
||||||
|
for (var i = parts.length - 1; i >= 0; i--){
|
||||||
|
var p = parts[i];
|
||||||
|
if (p == " "){
|
||||||
|
if (endOfLine || beforeSpace) parts[i] = ' ';
|
||||||
|
endOfLine = false;
|
||||||
|
beforeSpace = true;
|
||||||
|
}
|
||||||
|
else if (p.charAt(0) != "<"){
|
||||||
|
endOfLine = false;
|
||||||
|
beforeSpace = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// beginning of line is nbsp
|
||||||
|
for (var i = 0; i < parts.length; i++){
|
||||||
|
var p = parts[i];
|
||||||
|
if (p == " "){
|
||||||
|
parts[i] = ' ';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (p.charAt(0) != "<"){
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (var i = 0; i < parts.length; i++){
|
||||||
|
var p = parts[i];
|
||||||
|
if (p == " "){
|
||||||
|
parts[i] = ' ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return parts.join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
|
293
src/node/utils/ExportTxt.js
Normal file
293
src/node/utils/ExportTxt.js
Normal file
|
@ -0,0 +1,293 @@
|
||||||
|
/**
|
||||||
|
* TXT export
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 2013 John McLear
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var async = require("async");
|
||||||
|
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||||
|
var padManager = require("../db/PadManager");
|
||||||
|
var ERR = require("async-stacktrace");
|
||||||
|
var Security = require('ep_etherpad-lite/static/js/security');
|
||||||
|
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||||
|
var getPadPlainText = require('./ExportHelper').getPadPlainText;
|
||||||
|
var _analyzeLine = require('./ExportHelper')._analyzeLine;
|
||||||
|
|
||||||
|
// This is slightly different than the HTML method as it passes the output to getTXTFromAText
|
||||||
|
function getPadTXT(pad, revNum, callback)
|
||||||
|
{
|
||||||
|
var atext = pad.atext;
|
||||||
|
var html;
|
||||||
|
async.waterfall([
|
||||||
|
// fetch revision atext
|
||||||
|
|
||||||
|
|
||||||
|
function (callback)
|
||||||
|
{
|
||||||
|
if (revNum != undefined)
|
||||||
|
{
|
||||||
|
pad.getInternalRevisionAText(revNum, function (err, revisionAtext)
|
||||||
|
{
|
||||||
|
if(ERR(err, callback)) return;
|
||||||
|
atext = revisionAtext;
|
||||||
|
callback();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
callback(null);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// convert atext to html
|
||||||
|
|
||||||
|
|
||||||
|
function (callback)
|
||||||
|
{
|
||||||
|
html = getTXTFromAtext(pad, atext); // only this line is different to the HTML function
|
||||||
|
callback(null);
|
||||||
|
}],
|
||||||
|
// run final callback
|
||||||
|
|
||||||
|
|
||||||
|
function (err)
|
||||||
|
{
|
||||||
|
if(ERR(err, callback)) return;
|
||||||
|
callback(null, html);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.getPadTXT = getPadTXT;
|
||||||
|
|
||||||
|
|
||||||
|
// This is different than the functionality provided in ExportHtml as it provides formatting
|
||||||
|
// functionality that is designed specifically for TXT exports
|
||||||
|
function getTXTFromAtext(pad, atext, authorColors)
|
||||||
|
{
|
||||||
|
var apool = pad.apool();
|
||||||
|
var textLines = atext.text.slice(0, -1).split('\n');
|
||||||
|
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
|
||||||
|
|
||||||
|
var tags = ['h1', 'h2', 'strong', 'em', 'u', 's'];
|
||||||
|
var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough'];
|
||||||
|
var anumMap = {};
|
||||||
|
var css = "";
|
||||||
|
|
||||||
|
props.forEach(function (propName, i)
|
||||||
|
{
|
||||||
|
var propTrueNum = apool.putAttrib([propName, true], true);
|
||||||
|
if (propTrueNum >= 0)
|
||||||
|
{
|
||||||
|
anumMap[propTrueNum] = i;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function getLineTXT(text, attribs)
|
||||||
|
{
|
||||||
|
var propVals = [false, false, false];
|
||||||
|
var ENTER = 1;
|
||||||
|
var STAY = 2;
|
||||||
|
var LEAVE = 0;
|
||||||
|
|
||||||
|
// Use order of tags (b/i/u) as order of nesting, for simplicity
|
||||||
|
// and decent nesting. For example,
|
||||||
|
// <b>Just bold<b> <b><i>Bold and italics</i></b> <i>Just italics</i>
|
||||||
|
// becomes
|
||||||
|
// <b>Just bold <i>Bold and italics</i></b> <i>Just italics</i>
|
||||||
|
var taker = Changeset.stringIterator(text);
|
||||||
|
var assem = Changeset.stringAssembler();
|
||||||
|
var openTags = [];
|
||||||
|
|
||||||
|
var idx = 0;
|
||||||
|
|
||||||
|
function processNextChars(numChars)
|
||||||
|
{
|
||||||
|
if (numChars <= 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var iter = Changeset.opIterator(Changeset.subattribution(attribs, idx, idx + numChars));
|
||||||
|
idx += numChars;
|
||||||
|
|
||||||
|
while (iter.hasNext())
|
||||||
|
{
|
||||||
|
var o = iter.next();
|
||||||
|
var propChanged = false;
|
||||||
|
Changeset.eachAttribNumber(o.attribs, function (a)
|
||||||
|
{
|
||||||
|
if (a in anumMap)
|
||||||
|
{
|
||||||
|
var i = anumMap[a]; // i = 0 => bold, etc.
|
||||||
|
if (!propVals[i])
|
||||||
|
{
|
||||||
|
propVals[i] = ENTER;
|
||||||
|
propChanged = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
propVals[i] = STAY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
for (var i = 0; i < propVals.length; i++)
|
||||||
|
{
|
||||||
|
if (propVals[i] === true)
|
||||||
|
{
|
||||||
|
propVals[i] = LEAVE;
|
||||||
|
propChanged = true;
|
||||||
|
}
|
||||||
|
else if (propVals[i] === STAY)
|
||||||
|
{
|
||||||
|
propVals[i] = true; // set it back
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// now each member of propVal is in {false,LEAVE,ENTER,true}
|
||||||
|
// according to what happens at start of span
|
||||||
|
if (propChanged)
|
||||||
|
{
|
||||||
|
// leaving bold (e.g.) also leaves italics, etc.
|
||||||
|
var left = false;
|
||||||
|
for (var i = 0; i < propVals.length; i++)
|
||||||
|
{
|
||||||
|
var v = propVals[i];
|
||||||
|
if (!left)
|
||||||
|
{
|
||||||
|
if (v === LEAVE)
|
||||||
|
{
|
||||||
|
left = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (v === true)
|
||||||
|
{
|
||||||
|
propVals[i] = STAY; // tag will be closed and re-opened
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var tags2close = [];
|
||||||
|
|
||||||
|
for (var i = propVals.length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (propVals[i] === LEAVE)
|
||||||
|
{
|
||||||
|
//emitCloseTag(i);
|
||||||
|
tags2close.push(i);
|
||||||
|
propVals[i] = false;
|
||||||
|
}
|
||||||
|
else if (propVals[i] === STAY)
|
||||||
|
{
|
||||||
|
//emitCloseTag(i);
|
||||||
|
tags2close.push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < propVals.length; i++)
|
||||||
|
{
|
||||||
|
if (propVals[i] === ENTER || propVals[i] === STAY)
|
||||||
|
{
|
||||||
|
propVals[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// propVals is now all {true,false} again
|
||||||
|
} // end if (propChanged)
|
||||||
|
|
||||||
|
var chars = o.chars;
|
||||||
|
if (o.lines)
|
||||||
|
{
|
||||||
|
chars--; // exclude newline at end of line, if present
|
||||||
|
}
|
||||||
|
|
||||||
|
var s = taker.take(chars);
|
||||||
|
|
||||||
|
// removes the characters with the code 12. Don't know where they come
|
||||||
|
// from but they break the abiword parser and are completly useless
|
||||||
|
// s = s.replace(String.fromCharCode(12), "");
|
||||||
|
|
||||||
|
// remove * from s, it's just not needed on a blank line.. This stops
|
||||||
|
// plugins from being able to display * at the beginning of a line
|
||||||
|
// s = s.replace("*", ""); // Then remove it
|
||||||
|
|
||||||
|
assem.append(s);
|
||||||
|
} // end iteration over spans in line
|
||||||
|
|
||||||
|
var tags2close = [];
|
||||||
|
for (var i = propVals.length - 1; i >= 0; i--)
|
||||||
|
{
|
||||||
|
if (propVals[i])
|
||||||
|
{
|
||||||
|
tags2close.push(i);
|
||||||
|
propVals[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // end processNextChars
|
||||||
|
processNextChars(text.length - idx);
|
||||||
|
return(assem.toString());
|
||||||
|
} // end getLineHTML
|
||||||
|
var pieces = [css];
|
||||||
|
|
||||||
|
// Need to deal with constraints imposed on HTML lists; can
|
||||||
|
// only gain one level of nesting at once, can't change type
|
||||||
|
// mid-list, etc.
|
||||||
|
// People might use weird indenting, e.g. skip a level,
|
||||||
|
// so we want to do something reasonable there. We also
|
||||||
|
// want to deal gracefully with blank lines.
|
||||||
|
// => keeps track of the parents level of indentation
|
||||||
|
var lists = []; // e.g. [[1,'bullet'], [3,'bullet'], ...]
|
||||||
|
for (var i = 0; i < textLines.length; i++)
|
||||||
|
{
|
||||||
|
var line = _analyzeLine(textLines[i], attribLines[i], apool);
|
||||||
|
var lineContent = getLineTXT(line.text, line.aline);
|
||||||
|
if(line.listTypeName == "bullet"){
|
||||||
|
lineContent = "* " + lineContent; // add a bullet
|
||||||
|
}
|
||||||
|
if(line.listLevel > 0){
|
||||||
|
for (var j = line.listLevel - 1; j >= 0; j--){
|
||||||
|
pieces.push('\t');
|
||||||
|
}
|
||||||
|
if(line.listTypeName == "number"){
|
||||||
|
pieces.push(line.listLevel + ". ");
|
||||||
|
// This is bad because it doesn't truly reflect what the user
|
||||||
|
// sees because browsers do magic on nested <ol><li>s
|
||||||
|
}
|
||||||
|
pieces.push(lineContent, '\n');
|
||||||
|
}else{
|
||||||
|
pieces.push(lineContent, '\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pieces.join('');
|
||||||
|
}
|
||||||
|
exports.getTXTFromAtext = getTXTFromAtext;
|
||||||
|
|
||||||
|
exports.getPadTXTDocument = function (padId, revNum, noDocType, callback)
|
||||||
|
{
|
||||||
|
padManager.getPad(padId, function (err, pad)
|
||||||
|
{
|
||||||
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
|
getPadTXT(pad, revNum, function (err, html)
|
||||||
|
{
|
||||||
|
if(ERR(err, callback)) return;
|
||||||
|
callback(null, html);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -26,6 +26,8 @@ var argv = require('./Cli').argv;
|
||||||
var npm = require("npm/lib/npm.js");
|
var npm = require("npm/lib/npm.js");
|
||||||
var vm = require('vm');
|
var vm = require('vm');
|
||||||
var log4js = require("log4js");
|
var log4js = require("log4js");
|
||||||
|
var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString;
|
||||||
|
|
||||||
|
|
||||||
/* Root path of the installation */
|
/* Root path of the installation */
|
||||||
exports.root = path.normalize(path.join(npm.dir, ".."));
|
exports.root = path.normalize(path.join(npm.dir, ".."));
|
||||||
|
@ -112,6 +114,11 @@ exports.loglevel = "INFO";
|
||||||
*/
|
*/
|
||||||
exports.logconfig = { appenders: [{ type: "console" }]};
|
exports.logconfig = { appenders: [{ type: "console" }]};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Session Key, do not sure this.
|
||||||
|
*/
|
||||||
|
exports.sessionKey = false;
|
||||||
|
|
||||||
/* This setting is used if you need authentication and/or
|
/* This setting is used if you need authentication and/or
|
||||||
* authorization. Note: /admin always requires authentication, and
|
* authorization. Note: /admin always requires authentication, and
|
||||||
* either authorization by a module, or a user with is_admin set */
|
* either authorization by a module, or a user with is_admin set */
|
||||||
|
@ -132,8 +139,6 @@ exports.abiwordAvailable = function()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
exports.reloadSettings = function reloadSettings() {
|
exports.reloadSettings = function reloadSettings() {
|
||||||
// Discover where the settings file lives
|
// Discover where the settings file lives
|
||||||
var settingsFilename = argv.settings || "settings.json";
|
var settingsFilename = argv.settings || "settings.json";
|
||||||
|
@ -152,6 +157,7 @@ exports.reloadSettings = function reloadSettings() {
|
||||||
try {
|
try {
|
||||||
if(settingsStr) {
|
if(settingsStr) {
|
||||||
settings = vm.runInContext('exports = '+settingsStr, vm.createContext(), "settings.json");
|
settings = vm.runInContext('exports = '+settingsStr, vm.createContext(), "settings.json");
|
||||||
|
settings = JSON.parse(JSON.stringify(settings)) // fix objects having constructors of other vm.context
|
||||||
}
|
}
|
||||||
}catch(e){
|
}catch(e){
|
||||||
console.error('There was an error processing your settings.json file: '+e.message);
|
console.error('There was an error processing your settings.json file: '+e.message);
|
||||||
|
@ -184,6 +190,11 @@ exports.reloadSettings = function reloadSettings() {
|
||||||
log4js.setGlobalLogLevel(exports.loglevel);//set loglevel
|
log4js.setGlobalLogLevel(exports.loglevel);//set loglevel
|
||||||
log4js.replaceConsole();
|
log4js.replaceConsole();
|
||||||
|
|
||||||
|
if(!exports.sessionKey){ // If the secretKey isn't set we also create yet another unique value here
|
||||||
|
exports.sessionKey = randomString(32);
|
||||||
|
console.warn("You need to set a sessionKey value in settings.json, this will allow your users to reconnect to your Etherpad Instance if your instance restarts");
|
||||||
|
}
|
||||||
|
|
||||||
if(exports.dbType === "dirty"){
|
if(exports.dbType === "dirty"){
|
||||||
console.warn("DirtyDB is used. This is fine for testing but not recommended for production.")
|
console.warn("DirtyDB is used. This is fine for testing but not recommended for production.")
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@
|
||||||
"require-kernel" : "1.0.5",
|
"require-kernel" : "1.0.5",
|
||||||
"resolve" : "0.2.x",
|
"resolve" : "0.2.x",
|
||||||
"socket.io" : "0.9.x",
|
"socket.io" : "0.9.x",
|
||||||
"ueberDB" : "0.1.9",
|
"ueberDB" : "0.1.94",
|
||||||
"async" : "0.1.x",
|
"async" : "0.1.x",
|
||||||
"express" : "3.x",
|
"express" : "3.x",
|
||||||
"connect" : "2.4.x",
|
"connect" : "2.4.x",
|
||||||
|
@ -40,11 +40,10 @@
|
||||||
},
|
},
|
||||||
"bin": { "etherpad-lite": "./node/server.js" },
|
"bin": { "etherpad-lite": "./node/server.js" },
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"jshint" : "*",
|
"wd" : "0.0.31"
|
||||||
"wd" : "0.0.26"
|
|
||||||
},
|
},
|
||||||
"engines" : { "node" : ">=0.6.0",
|
"engines" : { "node" : ">=0.6.3",
|
||||||
"npm" : ">=1.0"
|
"npm" : ">=1.0"
|
||||||
},
|
},
|
||||||
"version" : "1.2.7"
|
"version" : "1.2.8"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,65 +1,59 @@
|
||||||
|
html, body {
|
||||||
|
height: 100%;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
color: #333;
|
color: #333;
|
||||||
font: 14px helvetica, sans-serif;
|
font: 14px helvetica, sans-serif;
|
||||||
background: #ddd;
|
background: #eee;
|
||||||
background: -webkit-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: -o-radial-gradient(circle,#aaa,#eee 60%) center fixed;
|
|
||||||
}
|
|
||||||
|
|
||||||
#topborder {
|
|
||||||
border-top: 8px solid rgba(51, 51, 51, 0.8);
|
|
||||||
position: fixed;
|
|
||||||
top: 0px;
|
|
||||||
width: 100%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
div.menu {
|
div.menu {
|
||||||
background: none repeat scroll 0% 0% rgba(255, 255, 255, 0.75);
|
|
||||||
box-shadow: 0px -4px 4px rgba(0, 0, 0, 0.3);
|
|
||||||
display: block;
|
|
||||||
float: left;
|
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
position: fixed;
|
|
||||||
width: 220px;
|
width: 220px;
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
position: fixed;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.menu ul {
|
||||||
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.menu li {
|
div.menu li {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
margin-left: 3px;
|
margin-left: 3px;
|
||||||
line-height: 1.6
|
line-height: 3;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.menu li:last-child {
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
}
|
}
|
||||||
|
|
||||||
div.innerwrapper {
|
div.innerwrapper {
|
||||||
display: block;
|
|
||||||
float: right;
|
|
||||||
opacity: 0.9;
|
|
||||||
padding: 15px;
|
padding: 15px;
|
||||||
max-width: 860px;
|
padding-left: 265px;
|
||||||
border-radius: 0 0 7px 7px;
|
|
||||||
margin-left:250px;
|
|
||||||
min-width:400px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#wrapper {
|
#wrapper {
|
||||||
background: none repeat scroll 0px 0px #FFFFFF;
|
background: none repeat scroll 0px 0px #FFFFFF;
|
||||||
box-shadow: 0px 1px 8px rgba(0, 0, 0, 0.3);
|
box-shadow: 0px 1px 10px rgba(0, 0, 0, 0.2);
|
||||||
margin: auto;
|
margin: auto;
|
||||||
max-width: 1150px;
|
max-width: 1150px;
|
||||||
min-height: 100%;
|
min-height: 100%;
|
||||||
overflow: auto;
|
|
||||||
padding-left: 15px;
|
|
||||||
opacity: .9;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -69,37 +63,45 @@ h2 {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
table input[type="button"] {
|
table input[type="button"] {
|
||||||
float: right;
|
float: right;
|
||||||
width: 100px;
|
width: 100px;
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
||||||
|
@ -107,34 +109,112 @@ table {
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
#progress {
|
#progress {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 50px;
|
bottom: 50px;
|
||||||
}
|
}
|
||||||
.settings {
|
|
||||||
margin-top:10px;
|
#progress img {
|
||||||
width:100%;
|
vertical-align: top;
|
||||||
min-height:600px;
|
|
||||||
}
|
}
|
||||||
#response{
|
|
||||||
display:inline;
|
.settings {
|
||||||
|
outline: none;
|
||||||
|
width: 100%;
|
||||||
|
min-height: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#response {
|
||||||
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
a:link, a:visited, a:hover, a:focus {
|
a:link, a:visited, a:hover, a:focus {
|
||||||
color: #333333;
|
color: #333333;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
border-bottom: #333333 1px dotted;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
a:focus, a:hover {
|
a:focus, a:hover {
|
||||||
border-bottom: #333333 1px solid;
|
border-bottom: #333333 1px solid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
white-space: pre-wrap;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 720px) {
|
||||||
|
div.innerwrapper {
|
||||||
|
padding: 0 15px 15px 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.menu {
|
||||||
|
padding: 1px 15px 0 15px;
|
||||||
|
position: static;
|
||||||
|
height: auto;
|
||||||
|
border-right: none;
|
||||||
|
width: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table, thead, tbody, td, tr {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
thead tr {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
tr {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
td {
|
||||||
|
border: none;
|
||||||
|
border-bottom: 1px solid #eee;
|
||||||
|
position: relative;
|
||||||
|
padding-left: 50%;
|
||||||
|
white-space: normal;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.name {
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
|
||||||
|
td:before {
|
||||||
|
position: absolute;
|
||||||
|
top: 6px;
|
||||||
|
left: 6px;
|
||||||
|
text-align: left;
|
||||||
|
padding-right: 10px;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-weight: bold;
|
||||||
|
content: attr(data-label);
|
||||||
|
}
|
||||||
|
|
||||||
|
td:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
table input[type="button"] {
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
}
|
|
@ -176,3 +176,11 @@ p {
|
||||||
}
|
}
|
||||||
|
|
||||||
#overlaysdiv { position: absolute; left: -1000px; top: -1000px; }
|
#overlaysdiv { position: absolute; left: -1000px; top: -1000px; }
|
||||||
|
|
||||||
|
/* Stops super long lines without being spaces such as aaaaaaaaaaaaaa*100 breaking the editor
|
||||||
|
Commented out because it stops IE from being able to render the document, crazy IE bug is crazy. */
|
||||||
|
/*
|
||||||
|
.ace-line{
|
||||||
|
overflow:hidden;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
|
@ -33,19 +33,6 @@ function object(o)
|
||||||
f.prototype = o;
|
f.prototype = o;
|
||||||
return new f();
|
return new f();
|
||||||
}
|
}
|
||||||
var userAgent = (((function () {return this;})().navigator || {}).userAgent || 'node-js').toLowerCase();
|
|
||||||
|
|
||||||
// Figure out what browser is being used (stolen from jquery 1.2.1)
|
|
||||||
var browser = {
|
|
||||||
version: (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
|
|
||||||
safari: /webkit/.test(userAgent),
|
|
||||||
opera: /opera/.test(userAgent),
|
|
||||||
msie: /msie/.test(userAgent) && !/opera/.test(userAgent),
|
|
||||||
mozilla: /mozilla/.test(userAgent) && !/(compatible|webkit)/.test(userAgent),
|
|
||||||
windows: /windows/.test(userAgent),
|
|
||||||
mobile: /mobile/.test(userAgent) || /android/.test(userAgent)
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
function getAssoc(obj, name)
|
function getAssoc(obj, name)
|
||||||
{
|
{
|
||||||
|
@ -97,7 +84,6 @@ var noop = function(){};
|
||||||
|
|
||||||
exports.isNodeText = isNodeText;
|
exports.isNodeText = isNodeText;
|
||||||
exports.object = object;
|
exports.object = object;
|
||||||
exports.browser = browser;
|
|
||||||
exports.getAssoc = getAssoc;
|
exports.getAssoc = getAssoc;
|
||||||
exports.setAssoc = setAssoc;
|
exports.setAssoc = setAssoc;
|
||||||
exports.binarySearch = binarySearch;
|
exports.binarySearch = binarySearch;
|
||||||
|
|
|
@ -28,7 +28,7 @@ $ = jQuery = require('./rjquery').$;
|
||||||
_ = require("./underscore");
|
_ = require("./underscore");
|
||||||
|
|
||||||
var isNodeText = Ace2Common.isNodeText,
|
var isNodeText = Ace2Common.isNodeText,
|
||||||
browser = Ace2Common.browser,
|
browser = $.browser,
|
||||||
getAssoc = Ace2Common.getAssoc,
|
getAssoc = Ace2Common.getAssoc,
|
||||||
setAssoc = Ace2Common.setAssoc,
|
setAssoc = Ace2Common.setAssoc,
|
||||||
isTextNode = Ace2Common.isTextNode,
|
isTextNode = Ace2Common.isTextNode,
|
||||||
|
@ -154,7 +154,8 @@ function Ace2Inner(){
|
||||||
var dmesg = noop;
|
var dmesg = noop;
|
||||||
window.dmesg = noop;
|
window.dmesg = noop;
|
||||||
|
|
||||||
var scheduler = parent;
|
|
||||||
|
var scheduler = parent; // hack for opera required
|
||||||
|
|
||||||
var textFace = 'monospace';
|
var textFace = 'monospace';
|
||||||
var textSize = 12;
|
var textSize = 12;
|
||||||
|
@ -1621,9 +1622,17 @@ function Ace2Inner(){
|
||||||
lines = ccData.lines;
|
lines = ccData.lines;
|
||||||
var lineAttribs = ccData.lineAttribs;
|
var lineAttribs = ccData.lineAttribs;
|
||||||
var linesWrapped = ccData.linesWrapped;
|
var linesWrapped = ccData.linesWrapped;
|
||||||
|
var scrollToTheLeftNeeded = false;
|
||||||
|
|
||||||
if (linesWrapped > 0)
|
if (linesWrapped > 0)
|
||||||
{
|
{
|
||||||
|
if(!browser.ie){
|
||||||
|
// chrome decides in it's infinite wisdom that its okay to put the browsers visisble window in the middle of the span
|
||||||
|
// an outcome of this is that the first chars of the string are no longer visible to the user.. Yay chrome..
|
||||||
|
// Move the browsers visible area to the left hand side of the span
|
||||||
|
// Firefox isn't quite so bad, but it's still pretty quirky.
|
||||||
|
var scrollToTheLeftNeeded = true;
|
||||||
|
}
|
||||||
// console.log("Editor warning: " + linesWrapped + " long line" + (linesWrapped == 1 ? " was" : "s were") + " hard-wrapped into " + ccData.numLinesAfter + " lines.");
|
// console.log("Editor warning: " + linesWrapped + " long line" + (linesWrapped == 1 ? " was" : "s were") + " hard-wrapped into " + ccData.numLinesAfter + " lines.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1691,6 +1700,10 @@ function Ace2Inner(){
|
||||||
//console.log("removed: "+id);
|
//console.log("removed: "+id);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if(scrollToTheLeftNeeded){ // needed to stop chrome from breaking the ui when long strings without spaces are pasted
|
||||||
|
$("#innerdocbody").scrollLeft(0);
|
||||||
|
}
|
||||||
|
|
||||||
p.mark("findsel");
|
p.mark("findsel");
|
||||||
// if the nodes that define the selection weren't encountered during
|
// if the nodes that define the selection weren't encountered during
|
||||||
// content collection, figure out where those nodes are now.
|
// content collection, figure out where those nodes are now.
|
||||||
|
@ -1896,7 +1909,7 @@ function Ace2Inner(){
|
||||||
var prevLine = rep.lines.prev(thisLine);
|
var prevLine = rep.lines.prev(thisLine);
|
||||||
var prevLineText = prevLine.text;
|
var prevLineText = prevLine.text;
|
||||||
var theIndent = /^ *(?:)/.exec(prevLineText)[0];
|
var theIndent = /^ *(?:)/.exec(prevLineText)[0];
|
||||||
if (/[\[\(\{]\s*$/.exec(prevLineText)) theIndent += THE_TAB;
|
if (/[\[\(\:\{]\s*$/.exec(prevLineText)) theIndent += THE_TAB;
|
||||||
var cs = Changeset.builder(rep.lines.totalWidth()).keep(
|
var cs = Changeset.builder(rep.lines.totalWidth()).keep(
|
||||||
rep.lines.offsetOfIndex(lineNum), lineNum).insert(
|
rep.lines.offsetOfIndex(lineNum), lineNum).insert(
|
||||||
theIndent, [
|
theIndent, [
|
||||||
|
@ -2817,7 +2830,6 @@ function Ace2Inner(){
|
||||||
rep.selStart = selectStart;
|
rep.selStart = selectStart;
|
||||||
rep.selEnd = selectEnd;
|
rep.selEnd = selectEnd;
|
||||||
rep.selFocusAtStart = newSelFocusAtStart;
|
rep.selFocusAtStart = newSelFocusAtStart;
|
||||||
if (mozillaFakeArrows) mozillaFakeArrows.notifySelectionChanged();
|
|
||||||
currentCallStack.repChanged = true;
|
currentCallStack.repChanged = true;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -3317,8 +3329,10 @@ function Ace2Inner(){
|
||||||
|
|
||||||
function doIndentOutdent(isOut)
|
function doIndentOutdent(isOut)
|
||||||
{
|
{
|
||||||
if (!(rep.selStart && rep.selEnd) ||
|
if (!((rep.selStart && rep.selEnd) ||
|
||||||
((rep.selStart[0] == rep.selEnd[0]) && (rep.selStart[1] == rep.selEnd[1]) && rep.selEnd[1] > 1))
|
((rep.selStart[0] == rep.selEnd[0]) && (rep.selStart[1] == rep.selEnd[1]) && rep.selEnd[1] > 1)) &&
|
||||||
|
(isOut != true)
|
||||||
|
)
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -3326,7 +3340,6 @@ function Ace2Inner(){
|
||||||
var firstLine, lastLine;
|
var firstLine, lastLine;
|
||||||
firstLine = rep.selStart[0];
|
firstLine = rep.selStart[0];
|
||||||
lastLine = Math.max(firstLine, rep.selEnd[0] - ((rep.selEnd[1] === 0) ? 1 : 0));
|
lastLine = Math.max(firstLine, rep.selEnd[0] - ((rep.selEnd[1] === 0) ? 1 : 0));
|
||||||
|
|
||||||
var mods = [];
|
var mods = [];
|
||||||
for (var n = firstLine; n <= lastLine; n++)
|
for (var n = firstLine; n <= lastLine; n++)
|
||||||
{
|
{
|
||||||
|
@ -3539,7 +3552,6 @@ function Ace2Inner(){
|
||||||
{
|
{
|
||||||
// if (DEBUG && window.DONT_INCORP) return;
|
// if (DEBUG && window.DONT_INCORP) return;
|
||||||
if (!isEditable) return;
|
if (!isEditable) return;
|
||||||
|
|
||||||
var type = evt.type;
|
var type = evt.type;
|
||||||
var charCode = evt.charCode;
|
var charCode = evt.charCode;
|
||||||
var keyCode = evt.keyCode;
|
var keyCode = evt.keyCode;
|
||||||
|
@ -3561,6 +3573,11 @@ function Ace2Inner(){
|
||||||
var isModKey = ((!charCode) && ((type == "keyup") || (type == "keydown")) && (keyCode == 16 || keyCode == 17 || keyCode == 18 || keyCode == 20 || keyCode == 224 || keyCode == 91));
|
var isModKey = ((!charCode) && ((type == "keyup") || (type == "keydown")) && (keyCode == 16 || keyCode == 17 || keyCode == 18 || keyCode == 20 || keyCode == 224 || keyCode == 91));
|
||||||
if (isModKey) return;
|
if (isModKey) return;
|
||||||
|
|
||||||
|
// If the key is a keypress and the browser is opera and the key is enter, do nothign at all as this fires twice.
|
||||||
|
if (keyCode == 13 && browser.opera && (type == "keypress")){
|
||||||
|
return; // This stops double enters in Opera but double Tabs still show on single tab keypress, adding keyCode == 9 to this doesn't help as the event is fired twice
|
||||||
|
}
|
||||||
|
|
||||||
var specialHandled = false;
|
var specialHandled = false;
|
||||||
var isTypeForSpecialKey = ((browser.msie || browser.safari) ? (type == "keydown") : (type == "keypress"));
|
var isTypeForSpecialKey = ((browser.msie || browser.safari) ? (type == "keydown") : (type == "keypress"));
|
||||||
var isTypeForCmdKey = ((browser.msie || browser.safari) ? (type == "keydown") : (type == "keypress"));
|
var isTypeForCmdKey = ((browser.msie || browser.safari) ? (type == "keydown") : (type == "keypress"));
|
||||||
|
@ -3690,12 +3707,73 @@ function Ace2Inner(){
|
||||||
doDeleteKey();
|
doDeleteKey();
|
||||||
specialHandled = true;
|
specialHandled = true;
|
||||||
}
|
}
|
||||||
|
if((evt.which == 33 || evt.which == 34) && type == 'keydown'){
|
||||||
if (mozillaFakeArrows && mozillaFakeArrows.handleKeyEvent(evt))
|
var oldVisibleLineRange = getVisibleLineRange();
|
||||||
{
|
var topOffset = rep.selStart[0] - oldVisibleLineRange[0];
|
||||||
evt.preventDefault();
|
if(topOffset < 0 ){
|
||||||
specialHandled = true;
|
topOffset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var isPageDown = evt.which === 34;
|
||||||
|
var isPageUp = evt.which === 33;
|
||||||
|
|
||||||
|
scheduler.setTimeout(function(){
|
||||||
|
var newVisibleLineRange = getVisibleLineRange();
|
||||||
|
var linesCount = rep.lines.length();
|
||||||
|
|
||||||
|
var newCaretRow = rep.selStart[0];
|
||||||
|
if(isPageUp){
|
||||||
|
newCaretRow = oldVisibleLineRange[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(isPageDown){
|
||||||
|
newCaretRow = newVisibleLineRange[0] + topOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
//ensure min and max
|
||||||
|
if(newCaretRow < 0){
|
||||||
|
newCaretRow = 0;
|
||||||
|
}
|
||||||
|
if(newCaretRow >= linesCount){
|
||||||
|
newCaretRow = linesCount-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
rep.selStart[0] = newCaretRow;
|
||||||
|
rep.selEnd[0] = newCaretRow;
|
||||||
|
updateBrowserSelectionFromRep();
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Attempt to apply some sanity to cursor handling in Chrome after a copy / paste event
|
||||||
|
We have to do this the way we do because rep. doesn't hold the value for keyheld events IE if the user
|
||||||
|
presses and holds the arrow key */
|
||||||
|
if((evt.which == 37 || evt.which == 38 || evt.which == 39 || evt.which == 40) && $.browser.chrome){
|
||||||
|
|
||||||
|
var newVisibleLineRange = getVisibleLineRange(); // get the current visible range -- This works great.
|
||||||
|
var lineHeight = textLineHeight(); // what Is the height of each line?
|
||||||
|
var myselection = document.getSelection(); // get the current caret selection, can't use rep. here because that only gives us the start position not the current
|
||||||
|
var caretOffsetTop = myselection.focusNode.parentNode.offsetTop; // get the carets selection offset in px IE 214
|
||||||
|
|
||||||
|
if(caretOffsetTop){ // sometimes caretOffsetTop bugs out and returns 0, not sure why, possible Chrome bug? Either way if it does we don't wanna mess with it
|
||||||
|
var lineNum = Math.round(caretOffsetTop / lineHeight) ; // Get the current Line Number IE 84
|
||||||
|
newVisibleLineRange[1] = newVisibleLineRange[1]-1;
|
||||||
|
var caretIsVisible = (lineNum > newVisibleLineRange[0] && lineNum < newVisibleLineRange[1]); // Is the cursor in the visible Range IE ie 84 > 14 and 84 < 90?
|
||||||
|
|
||||||
|
if(!caretIsVisible){ // is the cursor no longer visible to the user?
|
||||||
|
// Oh boy the caret is out of the visible area, I need to scroll the browser window to lineNum.
|
||||||
|
// Get the new Y by getting the line number and multiplying by the height of each line.
|
||||||
|
if(evt.which == 37 || evt.which == 38){ // If left or up
|
||||||
|
var newY = lineHeight * (lineNum -1); // -1 to go to the line above
|
||||||
|
}else if(evt.which == 39 || evt.which == 40){ // if down or right
|
||||||
|
var newY = getScrollY() + (lineHeight*3); // the offset and one additional line
|
||||||
|
}
|
||||||
|
setScrollY(newY); // set the scroll height of the browser
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type == "keydown")
|
if (type == "keydown")
|
||||||
|
@ -3801,7 +3879,6 @@ function Ace2Inner(){
|
||||||
selection.endPoint = getPointForLineAndChar(se);
|
selection.endPoint = getPointForLineAndChar(se);
|
||||||
|
|
||||||
selection.focusAtStart = !! rep.selFocusAtStart;
|
selection.focusAtStart = !! rep.selFocusAtStart;
|
||||||
|
|
||||||
setSelection(selection);
|
setSelection(selection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4119,6 +4196,11 @@ function Ace2Inner(){
|
||||||
selection.startPoint = pointFromRangeBound(range.startContainer, range.startOffset);
|
selection.startPoint = pointFromRangeBound(range.startContainer, range.startOffset);
|
||||||
selection.endPoint = pointFromRangeBound(range.endContainer, range.endOffset);
|
selection.endPoint = pointFromRangeBound(range.endContainer, range.endOffset);
|
||||||
selection.focusAtStart = (((range.startContainer != range.endContainer) || (range.startOffset != range.endOffset)) && browserSelection.anchorNode && (browserSelection.anchorNode == range.endContainer) && (browserSelection.anchorOffset == range.endOffset));
|
selection.focusAtStart = (((range.startContainer != range.endContainer) || (range.startOffset != range.endOffset)) && browserSelection.anchorNode && (browserSelection.anchorNode == range.endContainer) && (browserSelection.anchorOffset == range.endOffset));
|
||||||
|
|
||||||
|
if(selection.startPoint.node.ownerDocument !== window.document){
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return selection;
|
return selection;
|
||||||
}
|
}
|
||||||
else return null;
|
else return null;
|
||||||
|
@ -5033,331 +5115,6 @@ function Ace2Inner(){
|
||||||
editorInfo.ace_doInsertUnorderedList = doInsertUnorderedList;
|
editorInfo.ace_doInsertUnorderedList = doInsertUnorderedList;
|
||||||
editorInfo.ace_doInsertOrderedList = doInsertOrderedList;
|
editorInfo.ace_doInsertOrderedList = doInsertOrderedList;
|
||||||
|
|
||||||
var mozillaFakeArrows = (browser.mozilla && (function()
|
|
||||||
{
|
|
||||||
// In Firefox 2, arrow keys are unstable while DOM-manipulating
|
|
||||||
// operations are going on. Specifically, if an operation
|
|
||||||
// (computation that ties up the event queue) is going on (in the
|
|
||||||
// call-stack of some event, like a timeout) that at some point
|
|
||||||
// mutates nodes involved in the selection, then the arrow
|
|
||||||
// keypress may (randomly) move the caret to the beginning or end
|
|
||||||
// of the document. If the operation also mutates the selection
|
|
||||||
// range, the old selection or the new selection may be used, or
|
|
||||||
// neither.
|
|
||||||
// As long as the arrow is pressed during the busy operation, it
|
|
||||||
// doesn't seem to matter that the keydown and keypress events
|
|
||||||
// aren't generated until afterwards, or that the arrow movement
|
|
||||||
// can still be stopped (meaning it hasn't been performed yet);
|
|
||||||
// Firefox must be preserving some old information about the
|
|
||||||
// selection or the DOM from when the key was initially pressed.
|
|
||||||
// However, it also doesn't seem to matter when the key was
|
|
||||||
// actually pressed relative to the time of the mutation within
|
|
||||||
// the prolonged operation. Also, even in very controlled tests
|
|
||||||
// (like a mutation followed by a long period of busyWaiting), the
|
|
||||||
// problem shows up often but not every time, with no discernable
|
|
||||||
// pattern. Who knows, it could have something to do with the
|
|
||||||
// caret-blinking timer, or DOM changes not being applied
|
|
||||||
// immediately.
|
|
||||||
// This problem, mercifully, does not show up at all in IE or
|
|
||||||
// Safari. My solution is to have my own, full-featured arrow-key
|
|
||||||
// implementation for Firefox.
|
|
||||||
// Note that the problem addressed here is potentially very subtle,
|
|
||||||
// especially if the operation is quick and is timed to usually happen
|
|
||||||
// when the user is idle.
|
|
||||||
// features:
|
|
||||||
// - 'up' and 'down' arrows preserve column when passing through shorter lines
|
|
||||||
// - shift-arrows extend the "focus" point, which may be start or end of range
|
|
||||||
// - the focus point is kept horizontally and vertically scrolled into view
|
|
||||||
// - arrows without shift cause caret to move to beginning or end of selection (left,right)
|
|
||||||
// or move focus point up or down a line (up,down)
|
|
||||||
// - command-(left,right,up,down) on Mac acts like (line-start, line-end, doc-start, doc-end)
|
|
||||||
// - takes wrapping into account when doesWrap is true, i.e. up-arrow and down-arrow move
|
|
||||||
// between the virtual lines within a wrapped line; this was difficult, and unfortunately
|
|
||||||
// requires mutating the DOM to get the necessary information
|
|
||||||
var savedFocusColumn = 0; // a value of 0 has no effect
|
|
||||||
var updatingSelectionNow = false;
|
|
||||||
|
|
||||||
function getVirtualLineView(lineNum)
|
|
||||||
{
|
|
||||||
var lineNode = rep.lines.atIndex(lineNum).lineNode;
|
|
||||||
while (lineNode.firstChild && isBlockElement(lineNode.firstChild))
|
|
||||||
{
|
|
||||||
lineNode = lineNode.firstChild;
|
|
||||||
}
|
|
||||||
return makeVirtualLineView(lineNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
function markerlessLineAndChar(line, chr)
|
|
||||||
{
|
|
||||||
return [line, chr - rep.lines.atIndex(line).lineMarker];
|
|
||||||
}
|
|
||||||
|
|
||||||
function markerfulLineAndChar(line, chr)
|
|
||||||
{
|
|
||||||
return [line, chr + rep.lines.atIndex(line).lineMarker];
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
notifySelectionChanged: function()
|
|
||||||
{
|
|
||||||
if (!updatingSelectionNow)
|
|
||||||
{
|
|
||||||
savedFocusColumn = 0;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
handleKeyEvent: function(evt)
|
|
||||||
{
|
|
||||||
// returns "true" if handled
|
|
||||||
if (evt.type != "keypress") return false;
|
|
||||||
var keyCode = evt.keyCode;
|
|
||||||
if (keyCode < 37 || keyCode > 40) return false;
|
|
||||||
incorporateUserChanges();
|
|
||||||
|
|
||||||
if (!(rep.selStart && rep.selEnd)) return true;
|
|
||||||
|
|
||||||
// {byWord,toEnd,normal}
|
|
||||||
var moveMode = (evt.altKey ? "byWord" : (evt.ctrlKey ? "byWord" : (evt.metaKey ? "toEnd" : "normal")));
|
|
||||||
|
|
||||||
var anchorCaret = markerlessLineAndChar(rep.selStart[0], rep.selStart[1]);
|
|
||||||
var focusCaret = markerlessLineAndChar(rep.selEnd[0], rep.selEnd[1]);
|
|
||||||
var wasCaret = isCaret();
|
|
||||||
if (rep.selFocusAtStart)
|
|
||||||
{
|
|
||||||
var tmp = anchorCaret;
|
|
||||||
anchorCaret = focusCaret;
|
|
||||||
focusCaret = tmp;
|
|
||||||
}
|
|
||||||
var K_UP = 38,
|
|
||||||
K_DOWN = 40,
|
|
||||||
K_LEFT = 37,
|
|
||||||
K_RIGHT = 39;
|
|
||||||
var dontMove = false;
|
|
||||||
if (wasCaret && !evt.shiftKey)
|
|
||||||
{
|
|
||||||
// collapse, will mutate both together
|
|
||||||
anchorCaret = focusCaret;
|
|
||||||
}
|
|
||||||
else if ((!wasCaret) && (!evt.shiftKey))
|
|
||||||
{
|
|
||||||
if (keyCode == K_LEFT)
|
|
||||||
{
|
|
||||||
// place caret at beginning
|
|
||||||
if (rep.selFocusAtStart) anchorCaret = focusCaret;
|
|
||||||
else focusCaret = anchorCaret;
|
|
||||||
if (moveMode == "normal") dontMove = true;
|
|
||||||
}
|
|
||||||
else if (keyCode == K_RIGHT)
|
|
||||||
{
|
|
||||||
// place caret at end
|
|
||||||
if (rep.selFocusAtStart) focusCaret = anchorCaret;
|
|
||||||
else anchorCaret = focusCaret;
|
|
||||||
if (moveMode == "normal") dontMove = true;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// collapse, will mutate both together
|
|
||||||
anchorCaret = focusCaret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!dontMove)
|
|
||||||
{
|
|
||||||
function lineLength(i)
|
|
||||||
{
|
|
||||||
var entry = rep.lines.atIndex(i);
|
|
||||||
return entry.text.length - entry.lineMarker;
|
|
||||||
}
|
|
||||||
|
|
||||||
function lineText(i)
|
|
||||||
{
|
|
||||||
var entry = rep.lines.atIndex(i);
|
|
||||||
return entry.text.substring(entry.lineMarker);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (keyCode == K_UP || keyCode == K_DOWN)
|
|
||||||
{
|
|
||||||
var up = (keyCode == K_UP);
|
|
||||||
var canChangeLines = ((up && focusCaret[0]) || ((!up) && focusCaret[0] < rep.lines.length() - 1));
|
|
||||||
var virtualLineView, virtualLineSpot, canChangeVirtualLines = false;
|
|
||||||
if (doesWrap)
|
|
||||||
{
|
|
||||||
virtualLineView = getVirtualLineView(focusCaret[0]);
|
|
||||||
virtualLineSpot = virtualLineView.getVLineAndOffsetForChar(focusCaret[1]);
|
|
||||||
canChangeVirtualLines = ((up && virtualLineSpot.vline > 0) || ((!up) && virtualLineSpot.vline < (
|
|
||||||
virtualLineView.getNumVirtualLines() - 1)));
|
|
||||||
}
|
|
||||||
var newColByVirtualLineChange;
|
|
||||||
if (moveMode == "toEnd")
|
|
||||||
{
|
|
||||||
if (up)
|
|
||||||
{
|
|
||||||
focusCaret[0] = 0;
|
|
||||||
focusCaret[1] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
focusCaret[0] = rep.lines.length() - 1;
|
|
||||||
focusCaret[1] = lineLength(focusCaret[0]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (moveMode == "byWord")
|
|
||||||
{
|
|
||||||
// move by "paragraph", a feature that Firefox lacks but IE and Safari both have
|
|
||||||
if (up)
|
|
||||||
{
|
|
||||||
if (focusCaret[1] === 0 && canChangeLines)
|
|
||||||
{
|
|
||||||
focusCaret[0]--;
|
|
||||||
focusCaret[1] = 0;
|
|
||||||
}
|
|
||||||
else focusCaret[1] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var lineLen = lineLength(focusCaret[0]);
|
|
||||||
if (browser.windows)
|
|
||||||
{
|
|
||||||
if (canChangeLines)
|
|
||||||
{
|
|
||||||
focusCaret[0]++;
|
|
||||||
focusCaret[1] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
focusCaret[1] = lineLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (focusCaret[1] == lineLen && canChangeLines)
|
|
||||||
{
|
|
||||||
focusCaret[0]++;
|
|
||||||
focusCaret[1] = lineLength(focusCaret[0]);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
focusCaret[1] = lineLen;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
savedFocusColumn = 0;
|
|
||||||
}
|
|
||||||
else if (canChangeVirtualLines)
|
|
||||||
{
|
|
||||||
var vline = virtualLineSpot.vline;
|
|
||||||
var offset = virtualLineSpot.offset;
|
|
||||||
if (up) vline--;
|
|
||||||
else vline++;
|
|
||||||
if (savedFocusColumn > offset) offset = savedFocusColumn;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
savedFocusColumn = offset;
|
|
||||||
}
|
|
||||||
var newSpot = virtualLineView.getCharForVLineAndOffset(vline, offset);
|
|
||||||
focusCaret[1] = newSpot.lineChar;
|
|
||||||
}
|
|
||||||
else if (canChangeLines)
|
|
||||||
{
|
|
||||||
if (up) focusCaret[0]--;
|
|
||||||
else focusCaret[0]++;
|
|
||||||
var offset = focusCaret[1];
|
|
||||||
if (doesWrap)
|
|
||||||
{
|
|
||||||
offset = virtualLineSpot.offset;
|
|
||||||
}
|
|
||||||
if (savedFocusColumn > offset) offset = savedFocusColumn;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
savedFocusColumn = offset;
|
|
||||||
}
|
|
||||||
if (doesWrap)
|
|
||||||
{
|
|
||||||
var newLineView = getVirtualLineView(focusCaret[0]);
|
|
||||||
var vline = (up ? newLineView.getNumVirtualLines() - 1 : 0);
|
|
||||||
var newSpot = newLineView.getCharForVLineAndOffset(vline, offset);
|
|
||||||
focusCaret[1] = newSpot.lineChar;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var lineLen = lineLength(focusCaret[0]);
|
|
||||||
if (offset > lineLen) offset = lineLen;
|
|
||||||
focusCaret[1] = offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (up) focusCaret[1] = 0;
|
|
||||||
else focusCaret[1] = lineLength(focusCaret[0]);
|
|
||||||
savedFocusColumn = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (keyCode == K_LEFT || keyCode == K_RIGHT)
|
|
||||||
{
|
|
||||||
var left = (keyCode == K_LEFT);
|
|
||||||
if (left)
|
|
||||||
{
|
|
||||||
if (moveMode == "toEnd") focusCaret[1] = 0;
|
|
||||||
else if (focusCaret[1] > 0)
|
|
||||||
{
|
|
||||||
if (moveMode == "byWord")
|
|
||||||
{
|
|
||||||
focusCaret[1] = moveByWordInLine(lineText(focusCaret[0]), focusCaret[1], false);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
focusCaret[1]--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (focusCaret[0] > 0)
|
|
||||||
{
|
|
||||||
focusCaret[0]--;
|
|
||||||
focusCaret[1] = lineLength(focusCaret[0]);
|
|
||||||
if (moveMode == "byWord")
|
|
||||||
{
|
|
||||||
focusCaret[1] = moveByWordInLine(lineText(focusCaret[0]), focusCaret[1], false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
var lineLen = lineLength(focusCaret[0]);
|
|
||||||
if (moveMode == "toEnd") focusCaret[1] = lineLen;
|
|
||||||
else if (focusCaret[1] < lineLen)
|
|
||||||
{
|
|
||||||
if (moveMode == "byWord")
|
|
||||||
{
|
|
||||||
focusCaret[1] = moveByWordInLine(lineText(focusCaret[0]), focusCaret[1], true);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
focusCaret[1]++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (focusCaret[0] < rep.lines.length() - 1)
|
|
||||||
{
|
|
||||||
focusCaret[0]++;
|
|
||||||
focusCaret[1] = 0;
|
|
||||||
if (moveMode == "byWord")
|
|
||||||
{
|
|
||||||
focusCaret[1] = moveByWordInLine(lineText(focusCaret[0]), focusCaret[1], true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
savedFocusColumn = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var newSelFocusAtStart = ((focusCaret[0] < anchorCaret[0]) || (focusCaret[0] == anchorCaret[0] && focusCaret[1] < anchorCaret[1]));
|
|
||||||
var newSelStart = (newSelFocusAtStart ? focusCaret : anchorCaret);
|
|
||||||
var newSelEnd = (newSelFocusAtStart ? anchorCaret : focusCaret);
|
|
||||||
updatingSelectionNow = true;
|
|
||||||
performSelectionChange(markerfulLineAndChar(newSelStart[0], newSelStart[1]), markerfulLineAndChar(newSelEnd[0], newSelEnd[1]), newSelFocusAtStart);
|
|
||||||
updatingSelectionNow = false;
|
|
||||||
currentCallStack.userChangedSelection = true;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
})());
|
|
||||||
|
|
||||||
var lineNumbersShown;
|
var lineNumbersShown;
|
||||||
var sideDivInner;
|
var sideDivInner;
|
||||||
|
|
||||||
|
|
|
@ -107,12 +107,16 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
{
|
{
|
||||||
newpos = Number(newpos);
|
newpos = Number(newpos);
|
||||||
if (newpos < 0 || newpos > sliderLength) return;
|
if (newpos < 0 || newpos > sliderLength) return;
|
||||||
|
if(!newpos){
|
||||||
|
newpos = 0; // stops it from displaying NaN if newpos isn't set
|
||||||
|
}
|
||||||
window.location.hash = "#" + newpos;
|
window.location.hash = "#" + newpos;
|
||||||
$("#ui-slider-handle").css('left', newpos * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0));
|
$("#ui-slider-handle").css('left', newpos * ($("#ui-slider-bar").width() - 2) / (sliderLength * 1.0));
|
||||||
$("a.tlink").map(function()
|
$("a.tlink").map(function()
|
||||||
{
|
{
|
||||||
$(this).attr('href', $(this).attr('thref').replace("%revision%", newpos));
|
$(this).attr('href', $(this).attr('thref').replace("%revision%", newpos));
|
||||||
});
|
});
|
||||||
|
|
||||||
$("#revision_label").html(html10n.get("timeslider.version", { "version": newpos}));
|
$("#revision_label").html(html10n.get("timeslider.version", { "version": newpos}));
|
||||||
|
|
||||||
if (newpos == 0)
|
if (newpos == 0)
|
||||||
|
@ -456,31 +460,6 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded)
|
||||||
|
|
||||||
if (clientVars)
|
if (clientVars)
|
||||||
{
|
{
|
||||||
if (clientVars.fullWidth)
|
|
||||||
{
|
|
||||||
$("#padpage").css('width', '100%');
|
|
||||||
$("#revision").css('position', "absolute")
|
|
||||||
$("#revision").css('right', "20px")
|
|
||||||
$("#revision").css('top', "20px")
|
|
||||||
$("#padmain").css('left', '0px');
|
|
||||||
$("#padmain").css('right', '197px');
|
|
||||||
$("#padmain").css('width', 'auto');
|
|
||||||
$("#rightbars").css('right', '7px');
|
|
||||||
$("#rightbars").css('margin-right', '0px');
|
|
||||||
$("#timeslider").css('width', 'auto');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (clientVars.disableRightBar)
|
|
||||||
{
|
|
||||||
$("#rightbars").css('display', 'none');
|
|
||||||
$('#padmain').css('width', 'auto');
|
|
||||||
if (clientVars.fullWidth) $("#padmain").css('right', '7px');
|
|
||||||
else $("#padmain").css('width', '860px');
|
|
||||||
$("#revision").css('position', "absolute");
|
|
||||||
$("#revision").css('right', "20px");
|
|
||||||
$("#revision").css('top', "20px");
|
|
||||||
}
|
|
||||||
|
|
||||||
$("#timeslider").show();
|
$("#timeslider").show();
|
||||||
|
|
||||||
var startPos = clientVars.collab_client_vars.rev;
|
var startPos = clientVars.collab_client_vars.rev;
|
||||||
|
|
|
@ -294,8 +294,8 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
|
|
||||||
if (newRev != (oldRev + 1))
|
if (newRev != (oldRev + 1))
|
||||||
{
|
{
|
||||||
dmesg("bad message revision on NEW_CHANGES: " + newRev + " not " + (oldRev + 1));
|
top.console.warn("bad message revision on NEW_CHANGES: " + newRev + " not " + (oldRev + 1));
|
||||||
setChannelState("DISCONNECTED", "badmessage_newchanges");
|
// setChannelState("DISCONNECTED", "badmessage_newchanges");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
msgQueue.push(msg);
|
msgQueue.push(msg);
|
||||||
|
@ -304,8 +304,8 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
|
|
||||||
if (newRev != (rev + 1))
|
if (newRev != (rev + 1))
|
||||||
{
|
{
|
||||||
dmesg("bad message revision on NEW_CHANGES: " + newRev + " not " + (rev + 1));
|
top.console.warn("bad message revision on NEW_CHANGES: " + newRev + " not " + (rev + 1));
|
||||||
setChannelState("DISCONNECTED", "badmessage_newchanges");
|
// setChannelState("DISCONNECTED", "badmessage_newchanges");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rev = newRev;
|
rev = newRev;
|
||||||
|
@ -318,8 +318,8 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
{
|
{
|
||||||
if (newRev != (msgQueue[msgQueue.length - 1].newRev + 1))
|
if (newRev != (msgQueue[msgQueue.length - 1].newRev + 1))
|
||||||
{
|
{
|
||||||
dmesg("bad message revision on ACCEPT_COMMIT: " + newRev + " not " + (msgQueue[msgQueue.length - 1][0] + 1));
|
top.console.warn("bad message revision on ACCEPT_COMMIT: " + newRev + " not " + (msgQueue[msgQueue.length - 1][0] + 1));
|
||||||
setChannelState("DISCONNECTED", "badmessage_acceptcommit");
|
// setChannelState("DISCONNECTED", "badmessage_acceptcommit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
msgQueue.push(msg);
|
msgQueue.push(msg);
|
||||||
|
@ -328,8 +328,8 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad)
|
||||||
|
|
||||||
if (newRev != (rev + 1))
|
if (newRev != (rev + 1))
|
||||||
{
|
{
|
||||||
dmesg("bad message revision on ACCEPT_COMMIT: " + newRev + " not " + (rev + 1));
|
top.console.warn("bad message revision on ACCEPT_COMMIT: " + newRev + " not " + (rev + 1));
|
||||||
setChannelState("DISCONNECTED", "badmessage_acceptcommit");
|
// setChannelState("DISCONNECTED", "badmessage_acceptcommit");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rev = newRev;
|
rev = newRev;
|
||||||
|
|
|
@ -30,8 +30,7 @@ var Security = require('./security');
|
||||||
var hooks = require('./pluginfw/hooks');
|
var hooks = require('./pluginfw/hooks');
|
||||||
var _ = require('./underscore');
|
var _ = require('./underscore');
|
||||||
var lineAttributeMarker = require('./linestylefilter').lineAttributeMarker;
|
var lineAttributeMarker = require('./linestylefilter').lineAttributeMarker;
|
||||||
var Ace2Common = require('./ace2_common');
|
var noop = function(){};
|
||||||
var noop = Ace2Common.noop;
|
|
||||||
|
|
||||||
|
|
||||||
var domline = {};
|
var domline = {};
|
||||||
|
|
|
@ -23,27 +23,27 @@
|
||||||
window.html10n = (function(window, document, undefined) {
|
window.html10n = (function(window, document, undefined) {
|
||||||
|
|
||||||
// fix console
|
// fix console
|
||||||
var console = window.console
|
var console = window.console;
|
||||||
function interceptConsole(method){
|
function interceptConsole(method){
|
||||||
if (!console) return function() {}
|
if (!console) return function() {};
|
||||||
|
|
||||||
var original = console[method]
|
var original = console[method];
|
||||||
|
|
||||||
// do sneaky stuff
|
// do sneaky stuff
|
||||||
if (original.bind){
|
if (original.bind){
|
||||||
// Do this for normal browsers
|
// Do this for normal browsers
|
||||||
return original.bind(console)
|
return original.bind(console);
|
||||||
}else{
|
}else{
|
||||||
return function() {
|
return function() {
|
||||||
// Do this for IE
|
// Do this for IE
|
||||||
var message = Array.prototype.slice.apply(arguments).join(' ')
|
var message = Array.prototype.slice.apply(arguments).join(' ');
|
||||||
original(message)
|
original(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var consoleLog = interceptConsole('log')
|
var consoleLog = interceptConsole('log')
|
||||||
, consoleWarn = interceptConsole('warn')
|
, consoleWarn = interceptConsole('warn')
|
||||||
, consoleError = interceptConsole('warn')
|
, consoleError = interceptConsole('warn');
|
||||||
|
|
||||||
|
|
||||||
// fix Array.prototype.instanceOf in, guess what, IE! <3
|
// fix Array.prototype.instanceOf in, guess what, IE! <3
|
||||||
|
@ -100,7 +100,7 @@ window.html10n = (function(window, document, undefined) {
|
||||||
this._events = this._events || {};
|
this._events = this._events || {};
|
||||||
if( event in this._events === false ) return;
|
if( event in this._events === false ) return;
|
||||||
for(var i = 0; i < this._events[event].length; i++){
|
for(var i = 0; i < this._events[event].length; i++){
|
||||||
this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1))
|
this._events[event][i].apply(this, Array.prototype.slice.call(arguments, 1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -122,50 +122,50 @@ window.html10n = (function(window, document, undefined) {
|
||||||
* and caching all necessary resources
|
* and caching all necessary resources
|
||||||
*/
|
*/
|
||||||
function Loader(resources) {
|
function Loader(resources) {
|
||||||
this.resources = resources
|
this.resources = resources;
|
||||||
this.cache = {} // file => contents
|
this.cache = {}; // file => contents
|
||||||
this.langs = {} // lang => strings
|
this.langs = {}; // lang => strings
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader.prototype.load = function(lang, cb) {
|
Loader.prototype.load = function(lang, cb) {
|
||||||
if(this.langs[lang]) return cb()
|
if(this.langs[lang]) return cb();
|
||||||
|
|
||||||
if (this.resources.length > 0) {
|
if (this.resources.length > 0) {
|
||||||
var reqs = 0;
|
var reqs = 0;
|
||||||
for (var i=0, n=this.resources.length; i < n; i++) {
|
for (var i=0, n=this.resources.length; i < n; i++) {
|
||||||
this.fetch(this.resources[i], lang, function(e) {
|
this.fetch(this.resources[i], lang, function(e) {
|
||||||
reqs++;
|
reqs++;
|
||||||
if(e) return setTimeout(function(){ throw e }, 0)
|
if(e) return setTimeout(function(){ throw e }, 0);
|
||||||
|
|
||||||
if (reqs < n) return;// Call back once all reqs are completed
|
if (reqs < n) return;// Call back once all reqs are completed
|
||||||
cb && cb()
|
cb && cb();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Loader.prototype.fetch = function(href, lang, cb) {
|
Loader.prototype.fetch = function(href, lang, cb) {
|
||||||
var that = this
|
var that = this;
|
||||||
|
|
||||||
if (this.cache[href]) {
|
if (this.cache[href]) {
|
||||||
this.parse(lang, href, this.cache[href], cb)
|
this.parse(lang, href, this.cache[href], cb)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var xhr = new XMLHttpRequest()
|
var xhr = new XMLHttpRequest();
|
||||||
xhr.open('GET', href, /*async: */true)
|
xhr.open('GET', href, /*async: */true);
|
||||||
if (xhr.overrideMimeType) {
|
if (xhr.overrideMimeType) {
|
||||||
xhr.overrideMimeType('application/json; charset=utf-8');
|
xhr.overrideMimeType('application/json; charset=utf-8');
|
||||||
}
|
}
|
||||||
xhr.onreadystatechange = function() {
|
xhr.onreadystatechange = function() {
|
||||||
if (xhr.readyState == 4) {
|
if (xhr.readyState == 4) {
|
||||||
if (xhr.status == 200 || xhr.status === 0) {
|
if (xhr.status == 200 || xhr.status === 0) {
|
||||||
var data = JSON.parse(xhr.responseText)
|
var data = JSON.parse(xhr.responseText);
|
||||||
that.cache[href] = data
|
that.cache[href] = data;
|
||||||
// Pass on the contents for parsing
|
// Pass on the contents for parsing
|
||||||
that.parse(lang, href, data, cb)
|
that.parse(lang, href, data, cb);
|
||||||
} else {
|
} else {
|
||||||
cb(new Error('Failed to load '+href))
|
cb(new Error('Failed to load '+href));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -174,39 +174,39 @@ window.html10n = (function(window, document, undefined) {
|
||||||
|
|
||||||
Loader.prototype.parse = function(lang, currHref, data, cb) {
|
Loader.prototype.parse = function(lang, currHref, data, cb) {
|
||||||
if ('object' != typeof data) {
|
if ('object' != typeof data) {
|
||||||
cb(new Error('A file couldn\'t be parsed as json.'))
|
cb(new Error('A file couldn\'t be parsed as json.'));
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!data[lang]) lang = lang.substr(0, lang.indexOf('-') == -1? lang.length : lang.indexOf('-'))
|
if (!data[lang]) lang = lang.substr(0, lang.indexOf('-') == -1? lang.length : lang.indexOf('-'));
|
||||||
if (!data[lang]) {
|
if (!data[lang]) {
|
||||||
cb(new Error('Couldn\'t find translations for '+lang))
|
cb(new Error('Couldn\'t find translations for '+lang));
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('string' == typeof data[lang]) {
|
if ('string' == typeof data[lang]) {
|
||||||
// Import rule
|
// Import rule
|
||||||
|
|
||||||
// absolute path
|
// absolute path
|
||||||
var importUrl = data[lang]
|
var importUrl = data[lang];
|
||||||
|
|
||||||
// relative path
|
// relative path
|
||||||
if(data[lang].indexOf("http") != 0 && data[lang].indexOf("/") != 0) {
|
if(data[lang].indexOf("http") != 0 && data[lang].indexOf("/") != 0) {
|
||||||
importUrl = currHref+"/../"+data[lang]
|
importUrl = currHref+"/../"+data[lang];
|
||||||
}
|
}
|
||||||
|
|
||||||
this.fetch(importUrl, lang, cb)
|
this.fetch(importUrl, lang, cb);
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ('object' != typeof data[lang]) {
|
if ('object' != typeof data[lang]) {
|
||||||
cb(new Error('Translations should be specified as JSON objects!'))
|
cb(new Error('Translations should be specified as JSON objects!'));
|
||||||
return
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.langs[lang] = data[lang]
|
this.langs[lang] = data[lang];
|
||||||
// TODO: Also store accompanying langs
|
// TODO: Also store accompanying langs
|
||||||
cb()
|
cb();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -216,11 +216,11 @@ window.html10n = (function(window, document, undefined) {
|
||||||
var html10n =
|
var html10n =
|
||||||
{ language : null
|
{ language : null
|
||||||
}
|
}
|
||||||
MicroEvent.mixin(html10n)
|
MicroEvent.mixin(html10n);
|
||||||
|
|
||||||
html10n.macros = {}
|
html10n.macros = {};
|
||||||
|
|
||||||
html10n.rtl = ["ar","dv","fa","ha","he","ks","ku","ps","ur","yi"]
|
html10n.rtl = ["ar","dv","fa","ha","he","ks","ku","ps","ur","yi"];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get rules for plural forms (shared with JetPack), see:
|
* Get rules for plural forms (shared with JetPack), see:
|
||||||
|
@ -664,14 +664,14 @@ window.html10n = (function(window, document, undefined) {
|
||||||
* @param langs An array of lang codes defining fallbacks
|
* @param langs An array of lang codes defining fallbacks
|
||||||
*/
|
*/
|
||||||
html10n.localize = function(langs) {
|
html10n.localize = function(langs) {
|
||||||
var that = this
|
var that = this;
|
||||||
// if only one string => create an array
|
// if only one string => create an array
|
||||||
if ('string' == typeof langs) langs = [langs]
|
if ('string' == typeof langs) langs = [langs];
|
||||||
|
|
||||||
this.build(langs, function(er, translations) {
|
this.build(langs, function(er, translations) {
|
||||||
html10n.translations = translations
|
html10n.translations = translations;
|
||||||
html10n.translateElement(translations)
|
html10n.translateElement(translations);
|
||||||
that.trigger('localized')
|
that.trigger('localized');
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -682,78 +682,78 @@ window.html10n = (function(window, document, undefined) {
|
||||||
* @param element A DOM element, if omitted, the document element will be used
|
* @param element A DOM element, if omitted, the document element will be used
|
||||||
*/
|
*/
|
||||||
html10n.translateElement = function(translations, element) {
|
html10n.translateElement = function(translations, element) {
|
||||||
element = element || document.documentElement
|
element = element || document.documentElement;
|
||||||
|
|
||||||
var children = element? getTranslatableChildren(element) : document.childNodes;
|
var children = element? getTranslatableChildren(element) : document.childNodes;
|
||||||
for (var i=0, n=children.length; i < n; i++) {
|
for (var i=0, n=children.length; i < n; i++) {
|
||||||
this.translateNode(translations, children[i])
|
this.translateNode(translations, children[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// translate element itself if necessary
|
// translate element itself if necessary
|
||||||
this.translateNode(translations, element)
|
this.translateNode(translations, element);
|
||||||
}
|
}
|
||||||
|
|
||||||
function asyncForEach(list, iterator, cb) {
|
function asyncForEach(list, iterator, cb) {
|
||||||
var i = 0
|
var i = 0
|
||||||
, n = list.length
|
, n = list.length;
|
||||||
iterator(list[i], i, function each(err) {
|
iterator(list[i], i, function each(err) {
|
||||||
if(err) consoleLog(err)
|
if(err) consoleLog(err);
|
||||||
i++
|
i++;
|
||||||
if (i < n) return iterator(list[i],i, each);
|
if (i < n) return iterator(list[i],i, each);
|
||||||
cb()
|
cb();
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTranslatableChildren(element) {
|
function getTranslatableChildren(element) {
|
||||||
if(!document.querySelectorAll) {
|
if(!document.querySelectorAll) {
|
||||||
if (!element) return []
|
if (!element) return [];
|
||||||
var nodes = element.getElementsByTagName('*')
|
var nodes = element.getElementsByTagName('*')
|
||||||
, l10nElements = []
|
, l10nElements = [];
|
||||||
for (var i=0, n=nodes.length; i < n; i++) {
|
for (var i=0, n=nodes.length; i < n; i++) {
|
||||||
if (nodes[i].getAttribute('data-l10n-id'))
|
if (nodes[i].getAttribute('data-l10n-id'))
|
||||||
l10nElements.push(nodes[i]);
|
l10nElements.push(nodes[i]);
|
||||||
}
|
}
|
||||||
return l10nElements
|
return l10nElements;
|
||||||
}
|
}
|
||||||
return element.querySelectorAll('*[data-l10n-id]')
|
return element.querySelectorAll('*[data-l10n-id]');
|
||||||
}
|
}
|
||||||
|
|
||||||
html10n.get = function(id, args) {
|
html10n.get = function(id, args) {
|
||||||
var translations = html10n.translations
|
var translations = html10n.translations;
|
||||||
if(!translations) return consoleWarn('No translations available (yet)')
|
if(!translations) return consoleWarn('No translations available (yet)');
|
||||||
if(!translations[id]) return consoleWarn('Could not find string '+id)
|
if(!translations[id]) return consoleWarn('Could not find string '+id);
|
||||||
|
|
||||||
// apply args
|
// apply args
|
||||||
var str = substArguments(translations[id], args)
|
var str = substArguments(translations[id], args);
|
||||||
|
|
||||||
// apply macros
|
// apply macros
|
||||||
return substMacros(id, str, args)
|
return substMacros(id, str, args);
|
||||||
|
|
||||||
// replace {{arguments}} with their values or the
|
// replace {{arguments}} with their values or the
|
||||||
// associated translation string (based on its key)
|
// associated translation string (based on its key)
|
||||||
function substArguments(str, args) {
|
function substArguments(str, args) {
|
||||||
var reArgs = /\{\{\s*([a-zA-Z\.]+)\s*\}\}/
|
var reArgs = /\{\{\s*([a-zA-Z\.]+)\s*\}\}/
|
||||||
, match
|
, match;
|
||||||
|
|
||||||
while (match = reArgs.exec(str)) {
|
while (match = reArgs.exec(str)) {
|
||||||
if (!match || match.length < 2)
|
if (!match || match.length < 2)
|
||||||
return str // argument key not found
|
return str; // argument key not found
|
||||||
|
|
||||||
var arg = match[1]
|
var arg = match[1]
|
||||||
, sub = ''
|
, sub = '';
|
||||||
if (arg in args) {
|
if (arg in args) {
|
||||||
sub = args[arg]
|
sub = args[arg];
|
||||||
} else if (arg in translations) {
|
} else if (arg in translations) {
|
||||||
sub = translations[arg]
|
sub = translations[arg];
|
||||||
} else {
|
} else {
|
||||||
consoleWarn('Could not find argument {{' + arg + '}}')
|
consoleWarn('Could not find argument {{' + arg + '}}');
|
||||||
return str
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
str = str.substring(0, match.index) + sub + str.substr(match.index + match[0].length)
|
str = str.substring(0, match.index) + sub + str.substr(match.index + match[0].length);
|
||||||
}
|
}
|
||||||
|
|
||||||
return str
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
// replace {[macros]} with their values
|
// replace {[macros]} with their values
|
||||||
|
@ -766,21 +766,21 @@ window.html10n = (function(window, document, undefined) {
|
||||||
// a macro has been found
|
// a macro has been found
|
||||||
// Note: at the moment, only one parameter is supported
|
// Note: at the moment, only one parameter is supported
|
||||||
var macroName = reMatch[1]
|
var macroName = reMatch[1]
|
||||||
, paramName = reMatch[2]
|
, paramName = reMatch[2];
|
||||||
|
|
||||||
if (!(macroName in gMacros)) return str
|
if (!(macroName in gMacros)) return str;
|
||||||
|
|
||||||
var param
|
var param;
|
||||||
if (args && paramName in args) {
|
if (args && paramName in args) {
|
||||||
param = args[paramName]
|
param = args[paramName];
|
||||||
} else if (paramName in translations) {
|
} else if (paramName in translations) {
|
||||||
param = translations[paramName]
|
param = translations[paramName];
|
||||||
}
|
}
|
||||||
|
|
||||||
// there's no macro parser yet: it has to be defined in gMacros
|
// there's no macro parser yet: it has to be defined in gMacros
|
||||||
var macro = html10n.macros[macroName]
|
var macro = html10n.macros[macroName];
|
||||||
str = macro(translations, key, str, param)
|
str = macro(translations, key, str, param);
|
||||||
return str
|
return str;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -788,26 +788,26 @@ window.html10n = (function(window, document, undefined) {
|
||||||
* Applies translations to a DOM node (recursive)
|
* Applies translations to a DOM node (recursive)
|
||||||
*/
|
*/
|
||||||
html10n.translateNode = function(translations, node) {
|
html10n.translateNode = function(translations, node) {
|
||||||
var str = {}
|
var str = {};
|
||||||
|
|
||||||
// get id
|
// get id
|
||||||
str.id = node.getAttribute('data-l10n-id')
|
str.id = node.getAttribute('data-l10n-id');
|
||||||
if (!str.id) return
|
if (!str.id) return;
|
||||||
|
|
||||||
if(!translations[str.id]) return consoleWarn('Couldn\'t find translation key '+str.id)
|
if(!translations[str.id]) return consoleWarn('Couldn\'t find translation key '+str.id);
|
||||||
|
|
||||||
// get args
|
// get args
|
||||||
if(window.JSON) {
|
if(window.JSON) {
|
||||||
str.args = JSON.parse(node.getAttribute('data-l10n-args'))
|
str.args = JSON.parse(node.getAttribute('data-l10n-args'));
|
||||||
}else{
|
}else{
|
||||||
try{
|
try{
|
||||||
str.args = eval(node.getAttribute('data-l10n-args'))
|
str.args = eval(node.getAttribute('data-l10n-args'));
|
||||||
}catch(e) {
|
}catch(e) {
|
||||||
consoleWarn('Couldn\'t parse args for '+str.id)
|
consoleWarn('Couldn\'t parse args for '+str.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
str.str = html10n.get(str.id, str.args)
|
str.str = html10n.get(str.id, str.args);
|
||||||
|
|
||||||
// get attribute name to apply str to
|
// get attribute name to apply str to
|
||||||
var prop
|
var prop
|
||||||
|
@ -817,31 +817,31 @@ window.html10n = (function(window, document, undefined) {
|
||||||
, "innerHTML": 1
|
, "innerHTML": 1
|
||||||
, "alt": 1
|
, "alt": 1
|
||||||
, "textContent": 1
|
, "textContent": 1
|
||||||
}
|
};
|
||||||
if (index > 0 && str.id.substr(index + 1) in attrList) { // an attribute has been specified
|
if (index > 0 && str.id.substr(index + 1) in attrList) { // an attribute has been specified
|
||||||
prop = str.id.substr(index + 1)
|
prop = str.id.substr(index + 1);
|
||||||
} else { // no attribute: assuming text content by default
|
} else { // no attribute: assuming text content by default
|
||||||
prop = document.body.textContent ? 'textContent' : 'innerText'
|
prop = document.body.textContent ? 'textContent' : 'innerText';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apply translation
|
// Apply translation
|
||||||
if (node.children.length === 0 || prop != 'textContent') {
|
if (node.children.length === 0 || prop != 'textContent') {
|
||||||
node[prop] = str.str
|
node[prop] = str.str;
|
||||||
} else {
|
} else {
|
||||||
var children = node.childNodes,
|
var children = node.childNodes,
|
||||||
found = false
|
found = false;
|
||||||
for (var i=0, n=children.length; i < n; i++) {
|
for (var i=0, n=children.length; i < n; i++) {
|
||||||
if (children[i].nodeType === 3 && /\S/.test(children[i].textContent)) {
|
if (children[i].nodeType === 3 && /\S/.test(children[i].textContent)) {
|
||||||
if (!found) {
|
if (!found) {
|
||||||
children[i].nodeValue = str.str
|
children[i].nodeValue = str.str;
|
||||||
found = true
|
found = true;
|
||||||
} else {
|
} else {
|
||||||
children[i].nodeValue = ''
|
children[i].nodeValue = '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
consoleWarn('Unexpected error: could not translate element content for key '+str.id, node)
|
consoleWarn('Unexpected error: could not translate element content for key '+str.id, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -852,32 +852,32 @@ window.html10n = (function(window, document, undefined) {
|
||||||
*/
|
*/
|
||||||
html10n.build = function(langs, cb) {
|
html10n.build = function(langs, cb) {
|
||||||
var that = this
|
var that = this
|
||||||
, build = {}
|
, build = {};
|
||||||
|
|
||||||
asyncForEach(langs, function (lang, i, next) {
|
asyncForEach(langs, function (lang, i, next) {
|
||||||
if(!lang) return next();
|
if(!lang) return next();
|
||||||
that.loader.load(lang, next)
|
that.loader.load(lang, next);
|
||||||
}, function() {
|
}, function() {
|
||||||
var lang
|
var lang;
|
||||||
langs.reverse()
|
langs.reverse();
|
||||||
|
|
||||||
// loop through priority array...
|
// loop through priority array...
|
||||||
for (var i=0, n=langs.length; i < n; i++) {
|
for (var i=0, n=langs.length; i < n; i++) {
|
||||||
lang = langs[i]
|
lang = langs[i];
|
||||||
|
|
||||||
if(!lang || !(lang in that.loader.langs)) continue;
|
if(!lang || !(lang in that.loader.langs)) continue;
|
||||||
|
|
||||||
// ... and apply all strings of the current lang in the list
|
// ... and apply all strings of the current lang in the list
|
||||||
// to our build object
|
// to our build object
|
||||||
for (var string in that.loader.langs[lang]) {
|
for (var string in that.loader.langs[lang]) {
|
||||||
build[string] = that.loader.langs[lang][string]
|
build[string] = that.loader.langs[lang][string];
|
||||||
}
|
}
|
||||||
|
|
||||||
// the last applied lang will be exposed as the
|
// the last applied lang will be exposed as the
|
||||||
// lang the page was translated to
|
// lang the page was translated to
|
||||||
that.language = lang
|
that.language = lang;
|
||||||
}
|
}
|
||||||
cb(null, build)
|
cb(null, build);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -893,8 +893,8 @@ window.html10n = (function(window, document, undefined) {
|
||||||
* Returns the direction of the language returned be html10n#getLanguage
|
* Returns the direction of the language returned be html10n#getLanguage
|
||||||
*/
|
*/
|
||||||
html10n.getDirection = function() {
|
html10n.getDirection = function() {
|
||||||
var langCode = this.language.indexOf('-') == -1? this.language : this.language.substr(0, this.language.indexOf('-'))
|
var langCode = this.language.indexOf('-') == -1? this.language : this.language.substr(0, this.language.indexOf('-'));
|
||||||
return html10n.rtl.indexOf(langCode) == -1? 'ltr' : 'rtl'
|
return html10n.rtl.indexOf(langCode) == -1? 'ltr' : 'rtl';
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -903,28 +903,28 @@ window.html10n = (function(window, document, undefined) {
|
||||||
html10n.index = function () {
|
html10n.index = function () {
|
||||||
// Find all <link>s
|
// Find all <link>s
|
||||||
var links = document.getElementsByTagName('link')
|
var links = document.getElementsByTagName('link')
|
||||||
, resources = []
|
, resources = [];
|
||||||
for (var i=0, n=links.length; i < n; i++) {
|
for (var i=0, n=links.length; i < n; i++) {
|
||||||
if (links[i].type != 'application/l10n+json')
|
if (links[i].type != 'application/l10n+json')
|
||||||
continue;
|
continue;
|
||||||
resources.push(links[i].href)
|
resources.push(links[i].href);
|
||||||
}
|
}
|
||||||
this.loader = new Loader(resources)
|
this.loader = new Loader(resources);
|
||||||
this.trigger('indexed')
|
this.trigger('indexed');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (document.addEventListener) // modern browsers and IE9+
|
if (document.addEventListener) // modern browsers and IE9+
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
html10n.index()
|
html10n.index();
|
||||||
}, false)
|
}, false);
|
||||||
else if (window.attachEvent)
|
else if (window.attachEvent)
|
||||||
window.attachEvent('onload', function() {
|
window.attachEvent('onload', function() {
|
||||||
html10n.index()
|
html10n.index();
|
||||||
}, false)
|
}, false);
|
||||||
|
|
||||||
// gettext-like shortcut
|
// gettext-like shortcut
|
||||||
if (window._ === undefined)
|
if (window._ === undefined)
|
||||||
window._ = html10n.get;
|
window._ = html10n.get;
|
||||||
|
|
||||||
return html10n
|
return html10n;
|
||||||
})(window, document)
|
})(window, document);
|
||||||
|
|
10143
src/static/js/jquery.js
vendored
10143
src/static/js/jquery.js
vendored
File diff suppressed because it is too large
Load diff
50
src/static/js/jquery_browser.js
vendored
Normal file
50
src/static/js/jquery_browser.js
vendored
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
/*
|
||||||
|
Copied from jQuery 1.8, the last jquery version with browser recognition support
|
||||||
|
*/
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
// Use of jQuery.browser is frowned upon.
|
||||||
|
// More details: http://api.jquery.com/jQuery.browser
|
||||||
|
// jQuery.uaMatch maintained for back-compat
|
||||||
|
var uaMatch = function( ua ) {
|
||||||
|
ua = ua.toLowerCase();
|
||||||
|
|
||||||
|
var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) ||
|
||||||
|
/(webkit)[ \/]([\w.]+)/.exec( ua ) ||
|
||||||
|
/(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) ||
|
||||||
|
/(msie) ([\w.]+)/.exec( ua ) ||
|
||||||
|
ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) ||
|
||||||
|
[];
|
||||||
|
|
||||||
|
return {
|
||||||
|
browser: match[ 1 ] || "",
|
||||||
|
version: match[ 2 ] || "0"
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
var userAgent = navigator.userAgent;
|
||||||
|
var matched = uaMatch(userAgent);
|
||||||
|
var browser = {};
|
||||||
|
|
||||||
|
if ( matched.browser ) {
|
||||||
|
browser[ matched.browser ] = true;
|
||||||
|
browser.version = matched.version;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chrome is Webkit, but Webkit is also Safari.
|
||||||
|
if ( browser.chrome ) {
|
||||||
|
browser.webkit = true;
|
||||||
|
} else if ( browser.webkit ) {
|
||||||
|
browser.safari = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//custom extensions, the original jquery didn't have these
|
||||||
|
browser.windows = /windows/i.test(userAgent);
|
||||||
|
browser.mobile = /mobile/i.test(userAgent) || /android/i.test(userAgent);
|
||||||
|
|
||||||
|
if(typeof exports !== 'undefined'){
|
||||||
|
exports.browser = browser;
|
||||||
|
} else{
|
||||||
|
$.browser = browser;
|
||||||
|
}
|
||||||
|
})();
|
|
@ -1,6 +1,6 @@
|
||||||
(function(document) {
|
(function(document) {
|
||||||
// Set language for l10n
|
// Set language for l10n
|
||||||
var language = document.cookie.match(/language=((\w{2,3})(-w+)?)/);
|
var language = document.cookie.match(/language=((\w{2,3})(-\w+)?)/);
|
||||||
if(language) language = language[1];
|
if(language) language = language[1];
|
||||||
|
|
||||||
html10n.bind('indexed', function() {
|
html10n.bind('indexed', function() {
|
||||||
|
|
|
@ -35,7 +35,6 @@ var chat = require('./chat').chat;
|
||||||
var getCollabClient = require('./collab_client').getCollabClient;
|
var getCollabClient = require('./collab_client').getCollabClient;
|
||||||
var padconnectionstatus = require('./pad_connectionstatus').padconnectionstatus;
|
var padconnectionstatus = require('./pad_connectionstatus').padconnectionstatus;
|
||||||
var padcookie = require('./pad_cookie').padcookie;
|
var padcookie = require('./pad_cookie').padcookie;
|
||||||
var paddocbar = require('./pad_docbar').paddocbar;
|
|
||||||
var padeditbar = require('./pad_editbar').padeditbar;
|
var padeditbar = require('./pad_editbar').padeditbar;
|
||||||
var padeditor = require('./pad_editor').padeditor;
|
var padeditor = require('./pad_editor').padeditor;
|
||||||
var padimpexp = require('./pad_impexp').padimpexp;
|
var padimpexp = require('./pad_impexp').padimpexp;
|
||||||
|
@ -391,10 +390,6 @@ var pad = {
|
||||||
{
|
{
|
||||||
return clientVars.clientIp;
|
return clientVars.clientIp;
|
||||||
},
|
},
|
||||||
getIsProPad: function()
|
|
||||||
{
|
|
||||||
return clientVars.isProPad;
|
|
||||||
},
|
|
||||||
getColorPalette: function()
|
getColorPalette: function()
|
||||||
{
|
{
|
||||||
return clientVars.colorPalette;
|
return clientVars.colorPalette;
|
||||||
|
@ -467,11 +462,6 @@ var pad = {
|
||||||
}
|
}
|
||||||
|
|
||||||
// order of inits is important here:
|
// order of inits is important here:
|
||||||
padcookie.init(clientVars.cookiePrefsToSet, this);
|
|
||||||
|
|
||||||
$("#widthprefcheck").click(pad.toggleWidthPref);
|
|
||||||
// $("#sidebarcheck").click(pad.togglewSidebar);
|
|
||||||
|
|
||||||
pad.myUserInfo = {
|
pad.myUserInfo = {
|
||||||
userId: clientVars.userId,
|
userId: clientVars.userId,
|
||||||
name: clientVars.userName,
|
name: clientVars.userName,
|
||||||
|
@ -488,20 +478,12 @@ var pad = {
|
||||||
$("#specialkeyarea").html("mode: " + String(clientVars.specialKeyTranslation).toUpperCase());
|
$("#specialkeyarea").html("mode: " + String(clientVars.specialKeyTranslation).toUpperCase());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
paddocbar.init(
|
|
||||||
{
|
|
||||||
isTitleEditable: pad.getIsProPad(),
|
|
||||||
initialTitle: clientVars.initialTitle,
|
|
||||||
initialPassword: clientVars.initialPassword,
|
|
||||||
guestPolicy: pad.padOptions.guestPolicy
|
|
||||||
}, this);
|
|
||||||
padimpexp.init(this);
|
padimpexp.init(this);
|
||||||
padsavedrevs.init(this);
|
padsavedrevs.init(this);
|
||||||
|
|
||||||
padeditor.init(postAceInit, pad.padOptions.view || {}, this);
|
padeditor.init(postAceInit, pad.padOptions.view || {}, this);
|
||||||
|
|
||||||
paduserlist.init(pad.myUserInfo, this);
|
paduserlist.init(pad.myUserInfo, this);
|
||||||
// padchat.init(clientVars.chatHistory, pad.myUserInfo);
|
|
||||||
padconnectionstatus.init();
|
padconnectionstatus.init();
|
||||||
padmodals.init(this);
|
padmodals.init(this);
|
||||||
|
|
||||||
|
@ -553,31 +535,11 @@ var pad = {
|
||||||
{
|
{
|
||||||
pad.myUserInfo.name = newName;
|
pad.myUserInfo.name = newName;
|
||||||
pad.collabClient.updateUserInfo(pad.myUserInfo);
|
pad.collabClient.updateUserInfo(pad.myUserInfo);
|
||||||
//padchat.handleUserJoinOrUpdate(pad.myUserInfo);
|
|
||||||
},
|
},
|
||||||
notifyChangeColor: function(newColorId)
|
notifyChangeColor: function(newColorId)
|
||||||
{
|
{
|
||||||
pad.myUserInfo.colorId = newColorId;
|
pad.myUserInfo.colorId = newColorId;
|
||||||
pad.collabClient.updateUserInfo(pad.myUserInfo);
|
pad.collabClient.updateUserInfo(pad.myUserInfo);
|
||||||
//padchat.handleUserJoinOrUpdate(pad.myUserInfo);
|
|
||||||
},
|
|
||||||
notifyChangeTitle: function(newTitle)
|
|
||||||
{
|
|
||||||
pad.collabClient.sendClientMessage(
|
|
||||||
{
|
|
||||||
type: 'padtitle',
|
|
||||||
title: newTitle,
|
|
||||||
changedBy: pad.myUserInfo.name || "unnamed"
|
|
||||||
});
|
|
||||||
},
|
|
||||||
notifyChangePassword: function(newPass)
|
|
||||||
{
|
|
||||||
pad.collabClient.sendClientMessage(
|
|
||||||
{
|
|
||||||
type: 'padpassword',
|
|
||||||
password: newPass,
|
|
||||||
changedBy: pad.myUserInfo.name || "unnamed"
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
changePadOption: function(key, value)
|
changePadOption: function(key, value)
|
||||||
{
|
{
|
||||||
|
@ -619,7 +581,6 @@ var pad = {
|
||||||
{
|
{
|
||||||
// order important here
|
// order important here
|
||||||
pad.padOptions.guestPolicy = opts.guestPolicy;
|
pad.padOptions.guestPolicy = opts.guestPolicy;
|
||||||
paddocbar.setGuestPolicy(opts.guestPolicy);
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getPadOptions: function()
|
getPadOptions: function()
|
||||||
|
@ -629,7 +590,7 @@ var pad = {
|
||||||
},
|
},
|
||||||
isPadPublic: function()
|
isPadPublic: function()
|
||||||
{
|
{
|
||||||
return (!pad.getIsProPad()) || (pad.getPadOptions().guestPolicy == 'allow');
|
return pad.getPadOptions().guestPolicy == 'allow';
|
||||||
},
|
},
|
||||||
suggestUserName: function(userId, name)
|
suggestUserName: function(userId, name)
|
||||||
{
|
{
|
||||||
|
@ -643,17 +604,14 @@ var pad = {
|
||||||
handleUserJoin: function(userInfo)
|
handleUserJoin: function(userInfo)
|
||||||
{
|
{
|
||||||
paduserlist.userJoinOrUpdate(userInfo);
|
paduserlist.userJoinOrUpdate(userInfo);
|
||||||
//padchat.handleUserJoinOrUpdate(userInfo);
|
|
||||||
},
|
},
|
||||||
handleUserUpdate: function(userInfo)
|
handleUserUpdate: function(userInfo)
|
||||||
{
|
{
|
||||||
paduserlist.userJoinOrUpdate(userInfo);
|
paduserlist.userJoinOrUpdate(userInfo);
|
||||||
//padchat.handleUserJoinOrUpdate(userInfo);
|
|
||||||
},
|
},
|
||||||
handleUserLeave: function(userInfo)
|
handleUserLeave: function(userInfo)
|
||||||
{
|
{
|
||||||
paduserlist.userLeave(userInfo);
|
paduserlist.userLeave(userInfo);
|
||||||
//padchat.handleUserLeave(userInfo);
|
|
||||||
},
|
},
|
||||||
handleClientMessage: function(msg)
|
handleClientMessage: function(msg)
|
||||||
{
|
{
|
||||||
|
@ -665,18 +623,6 @@ var pad = {
|
||||||
paduserlist.setMyUserInfo(pad.myUserInfo);
|
paduserlist.setMyUserInfo(pad.myUserInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (msg.type == 'chat')
|
|
||||||
{
|
|
||||||
//padchat.receiveChat(msg);
|
|
||||||
}
|
|
||||||
else if (msg.type == 'padtitle')
|
|
||||||
{
|
|
||||||
paddocbar.changeTitle(msg.title);
|
|
||||||
}
|
|
||||||
else if (msg.type == 'padpassword')
|
|
||||||
{
|
|
||||||
paddocbar.changePassword(msg.password);
|
|
||||||
}
|
|
||||||
else if (msg.type == 'newRevisionList')
|
else if (msg.type == 'newRevisionList')
|
||||||
{
|
{
|
||||||
padsavedrevs.newRevisionList(msg.revisionList);
|
padsavedrevs.newRevisionList(msg.revisionList);
|
||||||
|
@ -769,7 +715,6 @@ var pad = {
|
||||||
}
|
}
|
||||||
padeditor.disable();
|
padeditor.disable();
|
||||||
padeditbar.disable();
|
padeditbar.disable();
|
||||||
paddocbar.disable();
|
|
||||||
padimpexp.disable();
|
padimpexp.disable();
|
||||||
|
|
||||||
padconnectionstatus.disconnected(message);
|
padconnectionstatus.disconnected(message);
|
||||||
|
@ -796,28 +741,10 @@ var pad = {
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
// pad.determineSidebarVisibility(isConnected && !isInitialConnect);
|
|
||||||
pad.determineChatVisibility(isConnected && !isInitialConnect);
|
pad.determineChatVisibility(isConnected && !isInitialConnect);
|
||||||
pad.determineAuthorshipColorsVisibility();
|
pad.determineAuthorshipColorsVisibility();
|
||||||
|
|
||||||
},
|
},
|
||||||
/* determineSidebarVisibility: function(asNowConnectedFeedback)
|
|
||||||
{
|
|
||||||
if (pad.isFullyConnected())
|
|
||||||
{
|
|
||||||
var setSidebarVisibility = padutils.getCancellableAction("set-sidebar-visibility", function()
|
|
||||||
{
|
|
||||||
// $("body").toggleClass('hidesidebar', !! padcookie.getPref('hideSidebar'));
|
|
||||||
});
|
|
||||||
window.setTimeout(setSidebarVisibility, asNowConnectedFeedback ? 3000 : 0);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
padutils.cancelActions("set-sidebar-visibility");
|
|
||||||
$("body").removeClass('hidesidebar');
|
|
||||||
}
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
determineChatVisibility: function(asNowConnectedFeedback){
|
determineChatVisibility: function(asNowConnectedFeedback){
|
||||||
var chatVisCookie = padcookie.getPref('chatAlwaysVisible');
|
var chatVisCookie = padcookie.getPref('chatAlwaysVisible');
|
||||||
if(chatVisCookie){ // if the cookie is set for chat always visible
|
if(chatVisCookie){ // if the cookie is set for chat always visible
|
||||||
|
@ -879,37 +806,6 @@ var pad = {
|
||||||
$('form#reconnectform input.missedChanges').val(JSON.stringify(pad.collabClient.getMissedChanges()));
|
$('form#reconnectform input.missedChanges').val(JSON.stringify(pad.collabClient.getMissedChanges()));
|
||||||
$('form#reconnectform').submit();
|
$('form#reconnectform').submit();
|
||||||
},
|
},
|
||||||
toggleWidthPref: function()
|
|
||||||
{
|
|
||||||
var newValue = !padcookie.getPref('fullWidth');
|
|
||||||
padcookie.setPref('fullWidth', newValue);
|
|
||||||
$("#widthprefcheck").toggleClass('widthprefchecked', !! newValue).toggleClass('widthprefunchecked', !newValue);
|
|
||||||
pad.handleWidthChange();
|
|
||||||
},
|
|
||||||
/*
|
|
||||||
toggleSidebar: function()
|
|
||||||
{
|
|
||||||
var newValue = !padcookie.getPref('hideSidebar');
|
|
||||||
padcookie.setPref('hideSidebar', newValue);
|
|
||||||
$("#sidebarcheck").toggleClass('sidebarchecked', !newValue).toggleClass('sidebarunchecked', !! newValue);
|
|
||||||
pad.determineSidebarVisibility();
|
|
||||||
},
|
|
||||||
*/
|
|
||||||
handleWidthChange: function()
|
|
||||||
{
|
|
||||||
var isFullWidth = padcookie.getPref('fullWidth');
|
|
||||||
if (isFullWidth)
|
|
||||||
{
|
|
||||||
$("body").addClass('fullwidth').removeClass('limwidth').removeClass('squish1width').removeClass('squish2width');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$("body").addClass('limwidth').removeClass('fullwidth');
|
|
||||||
|
|
||||||
var pageWidth = $(window).width();
|
|
||||||
$("body").toggleClass('squish1width', (pageWidth < 912 && pageWidth > 812)).toggleClass('squish2width', (pageWidth <= 812));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
// this is called from code put into a frame from the server:
|
// this is called from code put into a frame from the server:
|
||||||
handleImportExportFrameCall: function(callName, varargs)
|
handleImportExportFrameCall: function(callName, varargs)
|
||||||
{
|
{
|
||||||
|
|
|
@ -43,9 +43,8 @@ var padconnectionstatus = (function()
|
||||||
status = {
|
status = {
|
||||||
what: 'connected'
|
what: 'connected'
|
||||||
};
|
};
|
||||||
|
|
||||||
padmodals.showModal('connected');
|
padmodals.showModal('connected');
|
||||||
padmodals.hideOverlay(500);
|
padmodals.hideOverlay();
|
||||||
},
|
},
|
||||||
reconnecting: function()
|
reconnecting: function()
|
||||||
{
|
{
|
||||||
|
@ -54,7 +53,7 @@ var padconnectionstatus = (function()
|
||||||
};
|
};
|
||||||
|
|
||||||
padmodals.showModal('reconnecting');
|
padmodals.showModal('reconnecting');
|
||||||
padmodals.showOverlay(500);
|
padmodals.showOverlay();
|
||||||
},
|
},
|
||||||
disconnected: function(msg)
|
disconnected: function(msg)
|
||||||
{
|
{
|
||||||
|
@ -73,10 +72,11 @@ var padconnectionstatus = (function()
|
||||||
}
|
}
|
||||||
|
|
||||||
padmodals.showModal(k);
|
padmodals.showModal(k);
|
||||||
padmodals.showOverlay(500);
|
padmodals.showOverlay();
|
||||||
},
|
},
|
||||||
isFullyConnected: function()
|
isFullyConnected: function()
|
||||||
{
|
{
|
||||||
|
padmodals.hideOverlay();
|
||||||
return status.what == 'connected';
|
return status.what == 'connected';
|
||||||
},
|
},
|
||||||
getStatus: function()
|
getStatus: function()
|
||||||
|
|
|
@ -73,7 +73,7 @@ var padcookie = (function()
|
||||||
}
|
}
|
||||||
setRawCookie(stringifyCookie(cookieData));
|
setRawCookie(stringifyCookie(cookieData));
|
||||||
|
|
||||||
if (pad.getIsProPad() && (!getRawCookie()) && (!alreadyWarnedAboutNoCookies))
|
if ((!getRawCookie()) && (!alreadyWarnedAboutNoCookies))
|
||||||
{
|
{
|
||||||
alert("Warning: it appears that your browser does not have cookies enabled." + " EtherPad uses cookies to keep track of unique users for the purpose" + " of putting a quota on the number of active users. Using EtherPad without " + " cookies may fill up your server's user quota faster than expected.");
|
alert("Warning: it appears that your browser does not have cookies enabled." + " EtherPad uses cookies to keep track of unique users for the purpose" + " of putting a quota on the number of active users. Using EtherPad without " + " cookies may fill up your server's user quota faster than expected.");
|
||||||
alreadyWarnedAboutNoCookies = true;
|
alreadyWarnedAboutNoCookies = true;
|
||||||
|
|
|
@ -1,466 +0,0 @@
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
* TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copyright 2009 Google Inc.
|
|
||||||
*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
var padutils = require('./pad_utils').padutils;
|
|
||||||
|
|
||||||
var paddocbar = (function()
|
|
||||||
{
|
|
||||||
var isTitleEditable = false;
|
|
||||||
var isEditingTitle = false;
|
|
||||||
var isEditingPassword = false;
|
|
||||||
var enabled = false;
|
|
||||||
|
|
||||||
function getPanelOpenCloseAnimator(panelName, panelHeight)
|
|
||||||
{
|
|
||||||
var wrapper = $("#" + panelName + "-wrapper");
|
|
||||||
var openingClass = "docbar" + panelName + "-opening";
|
|
||||||
var openClass = "docbar" + panelName + "-open";
|
|
||||||
var closingClass = "docbar" + panelName + "-closing";
|
|
||||||
|
|
||||||
function setPanelState(action)
|
|
||||||
{
|
|
||||||
$("#docbar").removeClass(openingClass).removeClass(openClass).
|
|
||||||
removeClass(closingClass);
|
|
||||||
if (action != "closed")
|
|
||||||
{
|
|
||||||
$("#docbar").addClass("docbar" + panelName + "-" + action);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function openCloseAnimate(state)
|
|
||||||
{
|
|
||||||
function pow(x)
|
|
||||||
{
|
|
||||||
x = 1 - x;
|
|
||||||
x *= x * x;
|
|
||||||
return 1 - x;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (state == -1)
|
|
||||||
{
|
|
||||||
// startng to open
|
|
||||||
setPanelState("opening");
|
|
||||||
wrapper.css('height', '0');
|
|
||||||
}
|
|
||||||
else if (state < 0)
|
|
||||||
{
|
|
||||||
// opening
|
|
||||||
var height = Math.round(pow(state + 1) * (panelHeight - 1)) + 'px';
|
|
||||||
wrapper.css('height', height);
|
|
||||||
}
|
|
||||||
else if (state == 0)
|
|
||||||
{
|
|
||||||
// open
|
|
||||||
setPanelState("open");
|
|
||||||
wrapper.css('height', panelHeight - 1);
|
|
||||||
}
|
|
||||||
else if (state < 1)
|
|
||||||
{
|
|
||||||
// closing
|
|
||||||
setPanelState("closing");
|
|
||||||
var height = Math.round((1 - pow(state)) * (panelHeight - 1)) + 'px';
|
|
||||||
wrapper.css('height', height);
|
|
||||||
}
|
|
||||||
else if (state == 1)
|
|
||||||
{
|
|
||||||
// closed
|
|
||||||
setPanelState("closed");
|
|
||||||
wrapper.css('height', '0');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return padutils.makeShowHideAnimator(openCloseAnimate, false, 25, 500);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var currentPanel = null;
|
|
||||||
|
|
||||||
function setCurrentPanel(newCurrentPanel)
|
|
||||||
{
|
|
||||||
if (currentPanel != newCurrentPanel)
|
|
||||||
{
|
|
||||||
currentPanel = newCurrentPanel;
|
|
||||||
padutils.cancelActions("hide-docbar-panel");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var panels;
|
|
||||||
|
|
||||||
function changePassword(newPass)
|
|
||||||
{
|
|
||||||
if ((newPass || null) != (self.password || null))
|
|
||||||
{
|
|
||||||
self.password = (newPass || null);
|
|
||||||
pad.notifyChangePassword(newPass);
|
|
||||||
}
|
|
||||||
self.renderPassword();
|
|
||||||
}
|
|
||||||
|
|
||||||
var pad = undefined;
|
|
||||||
var self = {
|
|
||||||
title: null,
|
|
||||||
password: null,
|
|
||||||
init: function(opts, _pad)
|
|
||||||
{
|
|
||||||
pad = _pad;
|
|
||||||
|
|
||||||
panels = {
|
|
||||||
impexp: {
|
|
||||||
animator: getPanelOpenCloseAnimator("impexp", 160)
|
|
||||||
},
|
|
||||||
savedrevs: {
|
|
||||||
animator: getPanelOpenCloseAnimator("savedrevs", 79)
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
animator: getPanelOpenCloseAnimator("options", 114)
|
|
||||||
},
|
|
||||||
security: {
|
|
||||||
animator: getPanelOpenCloseAnimator("security", 130)
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
isTitleEditable = opts.isTitleEditable;
|
|
||||||
self.title = opts.initialTitle;
|
|
||||||
self.password = opts.initialPassword;
|
|
||||||
|
|
||||||
$("#docbarimpexp").click(function()
|
|
||||||
{
|
|
||||||
self.togglePanel("impexp");
|
|
||||||
});
|
|
||||||
$("#docbarsavedrevs").click(function()
|
|
||||||
{
|
|
||||||
self.togglePanel("savedrevs");
|
|
||||||
});
|
|
||||||
$("#docbaroptions").click(function()
|
|
||||||
{
|
|
||||||
self.togglePanel("options");
|
|
||||||
});
|
|
||||||
$("#docbarsecurity").click(function()
|
|
||||||
{
|
|
||||||
self.togglePanel("security");
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#docbarrenamelink").click(self.editTitle);
|
|
||||||
$("#padtitlesave").click(function()
|
|
||||||
{
|
|
||||||
self.closeTitleEdit(true);
|
|
||||||
});
|
|
||||||
$("#padtitlecancel").click(function()
|
|
||||||
{
|
|
||||||
self.closeTitleEdit(false);
|
|
||||||
});
|
|
||||||
padutils.bindEnterAndEscape($("#padtitleedit"), function()
|
|
||||||
{
|
|
||||||
$("#padtitlesave").trigger('click');
|
|
||||||
}, function()
|
|
||||||
{
|
|
||||||
$("#padtitlecancel").trigger('click');
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#options-close").click(function()
|
|
||||||
{
|
|
||||||
self.setShownPanel(null);
|
|
||||||
});
|
|
||||||
$("#security-close").click(function()
|
|
||||||
{
|
|
||||||
self.setShownPanel(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (pad.getIsProPad())
|
|
||||||
{
|
|
||||||
self.initPassword();
|
|
||||||
}
|
|
||||||
|
|
||||||
enabled = true;
|
|
||||||
self.render();
|
|
||||||
|
|
||||||
// public/private
|
|
||||||
$("#security-access input").bind("change click", function(evt)
|
|
||||||
{
|
|
||||||
pad.changePadOption('guestPolicy', $("#security-access input[name='padaccess']:checked").val());
|
|
||||||
});
|
|
||||||
self.setGuestPolicy(opts.guestPolicy);
|
|
||||||
},
|
|
||||||
setGuestPolicy: function(newPolicy)
|
|
||||||
{
|
|
||||||
$("#security-access input[value='" + newPolicy + "']").attr("checked", "checked");
|
|
||||||
self.render();
|
|
||||||
},
|
|
||||||
initPassword: function()
|
|
||||||
{
|
|
||||||
self.renderPassword();
|
|
||||||
$("#password-clearlink").click(function()
|
|
||||||
{
|
|
||||||
changePassword(null);
|
|
||||||
});
|
|
||||||
$("#password-setlink, #password-display").click(function()
|
|
||||||
{
|
|
||||||
self.enterPassword();
|
|
||||||
});
|
|
||||||
$("#password-cancellink").click(function()
|
|
||||||
{
|
|
||||||
self.exitPassword(false);
|
|
||||||
});
|
|
||||||
$("#password-savelink").click(function()
|
|
||||||
{
|
|
||||||
self.exitPassword(true);
|
|
||||||
});
|
|
||||||
padutils.bindEnterAndEscape($("#security-passwordedit"), function()
|
|
||||||
{
|
|
||||||
self.exitPassword(true);
|
|
||||||
}, function()
|
|
||||||
{
|
|
||||||
self.exitPassword(false);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
enterPassword: function()
|
|
||||||
{
|
|
||||||
isEditingPassword = true;
|
|
||||||
$("#security-passwordedit").val(self.password || '');
|
|
||||||
self.renderPassword();
|
|
||||||
$("#security-passwordedit").focus().select();
|
|
||||||
},
|
|
||||||
exitPassword: function(accept)
|
|
||||||
{
|
|
||||||
isEditingPassword = false;
|
|
||||||
if (accept)
|
|
||||||
{
|
|
||||||
changePassword($("#security-passwordedit").val());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.renderPassword();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
renderPassword: function()
|
|
||||||
{
|
|
||||||
if (isEditingPassword)
|
|
||||||
{
|
|
||||||
$("#password-nonedit").hide();
|
|
||||||
$("#password-inedit").show();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$("#password-nonedit").toggleClass('nopassword', !self.password);
|
|
||||||
$("#password-setlink").html(self.password ? "Change..." : "Set...");
|
|
||||||
if (self.password)
|
|
||||||
{
|
|
||||||
$("#password-display").html(self.password.replace(/./g, '•'));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$("#password-display").html("None");
|
|
||||||
}
|
|
||||||
$("#password-inedit").hide();
|
|
||||||
$("#password-nonedit").show();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
togglePanel: function(panelName)
|
|
||||||
{
|
|
||||||
if (panelName in panels)
|
|
||||||
{
|
|
||||||
if (currentPanel == panelName)
|
|
||||||
{
|
|
||||||
self.setShownPanel(null);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.setShownPanel(panelName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
setShownPanel: function(panelName)
|
|
||||||
{
|
|
||||||
function animateHidePanel(panelName, next)
|
|
||||||
{
|
|
||||||
var delay = 0;
|
|
||||||
if (panelName == 'options' && isEditingPassword)
|
|
||||||
{
|
|
||||||
// give user feedback that the password they've
|
|
||||||
// typed in won't actually take effect
|
|
||||||
self.exitPassword(false);
|
|
||||||
delay = 500;
|
|
||||||
}
|
|
||||||
|
|
||||||
window.setTimeout(function()
|
|
||||||
{
|
|
||||||
panels[panelName].animator.hide();
|
|
||||||
if (next)
|
|
||||||
{
|
|
||||||
next();
|
|
||||||
}
|
|
||||||
}, delay);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!panelName)
|
|
||||||
{
|
|
||||||
if (currentPanel)
|
|
||||||
{
|
|
||||||
animateHidePanel(currentPanel);
|
|
||||||
setCurrentPanel(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (panelName in panels)
|
|
||||||
{
|
|
||||||
if (currentPanel != panelName)
|
|
||||||
{
|
|
||||||
if (currentPanel)
|
|
||||||
{
|
|
||||||
animateHidePanel(currentPanel, function()
|
|
||||||
{
|
|
||||||
panels[panelName].animator.show();
|
|
||||||
setCurrentPanel(panelName);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
panels[panelName].animator.show();
|
|
||||||
setCurrentPanel(panelName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
isPanelShown: function(panelName)
|
|
||||||
{
|
|
||||||
if (!panelName)
|
|
||||||
{
|
|
||||||
return !currentPanel;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return (panelName == currentPanel);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
changeTitle: function(newTitle)
|
|
||||||
{
|
|
||||||
self.title = newTitle;
|
|
||||||
self.render();
|
|
||||||
},
|
|
||||||
editTitle: function()
|
|
||||||
{
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
$("#padtitleedit").val(self.title);
|
|
||||||
isEditingTitle = true;
|
|
||||||
self.render();
|
|
||||||
$("#padtitleedit").focus().select();
|
|
||||||
},
|
|
||||||
closeTitleEdit: function(accept)
|
|
||||||
{
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (accept)
|
|
||||||
{
|
|
||||||
var newTitle = $("#padtitleedit").val();
|
|
||||||
if (newTitle)
|
|
||||||
{
|
|
||||||
newTitle = newTitle.substring(0, 80);
|
|
||||||
self.title = newTitle;
|
|
||||||
|
|
||||||
pad.notifyChangeTitle(newTitle);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
isEditingTitle = false;
|
|
||||||
self.render();
|
|
||||||
},
|
|
||||||
changePassword: function(newPass)
|
|
||||||
{
|
|
||||||
if (newPass)
|
|
||||||
{
|
|
||||||
self.password = newPass;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
self.password = null;
|
|
||||||
}
|
|
||||||
self.renderPassword();
|
|
||||||
},
|
|
||||||
render: function()
|
|
||||||
{
|
|
||||||
if (isEditingTitle)
|
|
||||||
{
|
|
||||||
$("#docbarpadtitle").hide();
|
|
||||||
$("#docbarrenamelink").hide();
|
|
||||||
$("#padtitleedit").show();
|
|
||||||
$("#padtitlebuttons").show();
|
|
||||||
if (!enabled)
|
|
||||||
{
|
|
||||||
$("#padtitleedit").attr('disabled', 'disabled');
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$("#padtitleedit").removeAttr('disabled');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$("#padtitleedit").hide();
|
|
||||||
$("#padtitlebuttons").hide();
|
|
||||||
|
|
||||||
var titleSpan = $("#docbarpadtitle span");
|
|
||||||
titleSpan.html(padutils.escapeHtml(self.title));
|
|
||||||
$("#docbarpadtitle").attr('title', (pad.isPadPublic() ? "Public Pad: " : "") + self.title);
|
|
||||||
$("#docbarpadtitle").show();
|
|
||||||
|
|
||||||
if (isTitleEditable)
|
|
||||||
{
|
|
||||||
var titleRight = $("#docbarpadtitle").position().left + $("#docbarpadtitle span").position().left + Math.min($("#docbarpadtitle").width(), $("#docbarpadtitle span").width());
|
|
||||||
$("#docbarrenamelink").css('left', titleRight + 10).show();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pad.isPadPublic())
|
|
||||||
{
|
|
||||||
$("#docbar").addClass("docbar-public");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$("#docbar").removeClass("docbar-public");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
disable: function()
|
|
||||||
{
|
|
||||||
enabled = false;
|
|
||||||
self.render();
|
|
||||||
},
|
|
||||||
handleResizePage: function()
|
|
||||||
{
|
|
||||||
// Side-step circular reference. This should be injected.
|
|
||||||
var padsavedrevs = require('./pad_savedrevs');
|
|
||||||
padsavedrevs.handleResizePage();
|
|
||||||
},
|
|
||||||
hideLaterIfNoOtherInteraction: function()
|
|
||||||
{
|
|
||||||
return padutils.getCancellableAction('hide-docbar-panel', function()
|
|
||||||
{
|
|
||||||
self.setShownPanel(null);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
return self;
|
|
||||||
}());
|
|
||||||
|
|
||||||
exports.paddocbar = paddocbar;
|
|
|
@ -156,10 +156,7 @@ var padeditbar = (function()
|
||||||
else if (cmd == 'insertorderedlist') ace.ace_doInsertOrderedList();
|
else if (cmd == 'insertorderedlist') ace.ace_doInsertOrderedList();
|
||||||
else if (cmd == 'indent')
|
else if (cmd == 'indent')
|
||||||
{
|
{
|
||||||
if (!ace.ace_doIndentOutdent(false))
|
ace.ace_doIndentOutdent(false);
|
||||||
{
|
|
||||||
ace.ace_doInsertUnorderedList();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else if (cmd == 'outdent')
|
else if (cmd == 'outdent')
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,14 +20,11 @@
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var paddocbar = require('./pad_docbar').paddocbar;
|
|
||||||
|
|
||||||
var padimpexp = (function()
|
var padimpexp = (function()
|
||||||
{
|
{
|
||||||
|
|
||||||
///// import
|
///// import
|
||||||
var currentImportTimer = null;
|
var currentImportTimer = null;
|
||||||
var hidePanelCall = null;
|
|
||||||
|
|
||||||
function addImportFrames()
|
function addImportFrames()
|
||||||
{
|
{
|
||||||
|
@ -72,7 +69,6 @@ var padimpexp = (function()
|
||||||
var ret = window.confirm(html10n.get("pad.impexp.confirmimport"));
|
var ret = window.confirm(html10n.get("pad.impexp.confirmimport"));
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
hidePanelCall = paddocbar.hideLaterIfNoOtherInteraction();
|
|
||||||
currentImportTimer = window.setTimeout(function()
|
currentImportTimer = window.setTimeout(function()
|
||||||
{
|
{
|
||||||
if (!currentImportTimer)
|
if (!currentImportTimer)
|
||||||
|
@ -255,11 +251,6 @@ var padimpexp = (function()
|
||||||
$("#exportopena").attr("href", pad_root_path + "/export/odt");
|
$("#exportopena").attr("href", pad_root_path + "/export/odt");
|
||||||
}
|
}
|
||||||
|
|
||||||
$("#impexp-close").click(function()
|
|
||||||
{
|
|
||||||
paddocbar.setShownPanel(null);
|
|
||||||
});
|
|
||||||
|
|
||||||
addImportFrames();
|
addImportFrames();
|
||||||
$("#importfileinput").change(fileInputUpdated);
|
$("#importfileinput").change(fileInputUpdated);
|
||||||
$('#importform').submit(fileInputSubmit);
|
$('#importform').submit(fileInputSubmit);
|
||||||
|
|
|
@ -107,14 +107,9 @@ var paduserlist = (function()
|
||||||
function getUserRowHtml(height, data)
|
function getUserRowHtml(height, data)
|
||||||
{
|
{
|
||||||
var nameHtml;
|
var nameHtml;
|
||||||
var isGuest = (data.id.charAt(0) != 'p');
|
|
||||||
if (data.name)
|
if (data.name)
|
||||||
{
|
{
|
||||||
nameHtml = padutils.escapeHtml(data.name);
|
nameHtml = padutils.escapeHtml(data.name);
|
||||||
if (isGuest && pad.getIsProPad())
|
|
||||||
{
|
|
||||||
nameHtml += ' ('+_(pad.userlist.guest)+')';
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -520,11 +520,11 @@ function setupGlobalExceptionHandler() {
|
||||||
$("#editorloadingbox").css("padding", "10px");
|
$("#editorloadingbox").css("padding", "10px");
|
||||||
$("#editorloadingbox").css("padding-top", "45px");
|
$("#editorloadingbox").css("padding-top", "45px");
|
||||||
$("#editorloadingbox").html("<div style='text-align:left;color:red;font-size:16px;'><b>An error occured</b><br>The error was reported with the following id: '" + errorId + "'<br><br><span style='color:black;font-weight:bold;font-size:16px'>Please send this error message to us: </span><div style='color:black;font-size:14px'>'"
|
$("#editorloadingbox").html("<div style='text-align:left;color:red;font-size:16px;'><b>An error occured</b><br>The error was reported with the following id: '" + errorId + "'<br><br><span style='color:black;font-weight:bold;font-size:16px'>Please send this error message to us: </span><div style='color:black;font-size:14px'>'"
|
||||||
+ "ErrorId: " + errorId + "<br>UserAgent: " + navigator.userAgent + "<br>" + msg + " in " + url + " at line " + linenumber + "'</div></div>");
|
+ "ErrorId: " + errorId + "<br>URL: " + window.location.href + "<br>UserAgent: " + navigator.userAgent + "<br>" + msg + " in " + url + " at line " + linenumber + "'</div></div>");
|
||||||
}
|
}
|
||||||
|
|
||||||
//send javascript errors to the server
|
//send javascript errors to the server
|
||||||
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: window.location.href, 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";
|
||||||
|
|
||||||
|
|
|
@ -70,10 +70,12 @@ exports.flatten = function (lst) {
|
||||||
|
|
||||||
exports.callAll = function (hook_name, args) {
|
exports.callAll = function (hook_name, args) {
|
||||||
if (!args) args = {};
|
if (!args) args = {};
|
||||||
|
if (exports.plugins){
|
||||||
if (exports.plugins.hooks[hook_name] === undefined) return [];
|
if (exports.plugins.hooks[hook_name] === undefined) return [];
|
||||||
return _.flatten(_.map(exports.plugins.hooks[hook_name], function (hook) {
|
return _.flatten(_.map(exports.plugins.hooks[hook_name], function (hook) {
|
||||||
return hookCallWrapper(hook, hook_name, args);
|
return hookCallWrapper(hook, hook_name, args);
|
||||||
}), true);
|
}), true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
exports.aCallAll = function (hook_name, args, cb) {
|
exports.aCallAll = function (hook_name, args, cb) {
|
||||||
|
|
|
@ -94,11 +94,12 @@ exports.search = function(query, cache, cb) {
|
||||||
if (er) return cb(er);
|
if (er) return cb(er);
|
||||||
var res = {};
|
var res = {};
|
||||||
var i = 0;
|
var i = 0;
|
||||||
|
var pattern = query.pattern.toLowerCase();
|
||||||
for (key in data) { // for every plugin in the data from npm
|
for (key in data) { // for every plugin in the data from npm
|
||||||
if ( key.indexOf(plugins.prefix) == 0
|
if ( key.indexOf(plugins.prefix) == 0
|
||||||
&& key.indexOf(query.pattern) != -1
|
&& key.indexOf(pattern) != -1
|
||||||
|| key.indexOf(plugins.prefix) == 0
|
|| key.indexOf(plugins.prefix) == 0
|
||||||
&& data[key].description.indexOf(query.pattern) != -1
|
&& data[key].description.indexOf(pattern) != -1
|
||||||
) { // If the name contains ep_ and the search string is in the name or description
|
) { // If the name contains ep_ and the search string is in the name or description
|
||||||
i++;
|
i++;
|
||||||
if (i > query.offset
|
if (i > query.offset
|
||||||
|
|
|
@ -2,4 +2,9 @@
|
||||||
// Proviedes a require'able version of jQuery without leaking $ and jQuery;
|
// Proviedes a require'able version of jQuery without leaking $ and jQuery;
|
||||||
|
|
||||||
require('./jquery');
|
require('./jquery');
|
||||||
exports.jQuery = exports.$ = $.noConflict(true);
|
var jq = window.$.noConflict(true);
|
||||||
|
|
||||||
|
//added the old browser recognition
|
||||||
|
jq.browser = require('./jquery_browser').browser;
|
||||||
|
|
||||||
|
exports.jQuery = exports.$ = jq;
|
|
@ -29,8 +29,9 @@ var createCookie = require('./pad_utils').createCookie;
|
||||||
var readCookie = require('./pad_utils').readCookie;
|
var readCookie = require('./pad_utils').readCookie;
|
||||||
var randomString = require('./pad_utils').randomString;
|
var randomString = require('./pad_utils').randomString;
|
||||||
var _ = require('./underscore');
|
var _ = require('./underscore');
|
||||||
|
var hooks = require('./pluginfw/hooks');
|
||||||
|
|
||||||
var socket, token, padId, export_links;
|
var token, padId, export_links;
|
||||||
|
|
||||||
function init() {
|
function init() {
|
||||||
$(document).ready(function ()
|
$(document).ready(function ()
|
||||||
|
@ -106,6 +107,9 @@ function init() {
|
||||||
window.location.reload();
|
window.location.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
exports.socket = socket; // make the socket available
|
||||||
|
|
||||||
|
hooks.aCallAll("postTimesliderInit");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Admin Dashboard - Etherpad lite</title>
|
<title>Admin Dashboard - Etherpad</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
<meta name="viewport" content="width=device-width">
|
||||||
<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>
|
||||||
|
@ -9,13 +10,15 @@
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<h1>Etherpad lite</h1>
|
<h1>Etherpad</h1>
|
||||||
<li><a href="admin/plugins">Plugin manager</a> </li>
|
<ul>
|
||||||
<li><a href="admin/settings">Settings</a> </li>
|
<% e.begin_block("adminMenu"); %>
|
||||||
<li><a href="admin/plugins/info">Troubleshooting information</a> </li>
|
<li><a href="plugins">Plugin manager</a> </li>
|
||||||
|
<li><a href="settings">Settings</a> </li>
|
||||||
|
<li><a href="plugins/info">Troubleshooting information</a> </li>
|
||||||
|
<% e.end_block(); %>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
<div id="topborder"></div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,20 +1,24 @@
|
||||||
<%
|
<%
|
||||||
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins");
|
var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins");
|
||||||
%>
|
%>
|
||||||
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Plugin information - Etherpad lite</title>
|
<title>Plugin information - Etherpad</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
<meta name="viewport" content="width=device-width">
|
||||||
<link rel="stylesheet" href="../../static/css/admin.css">
|
<link rel="stylesheet" href="../../static/css/admin.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div id="wrapper">
|
<div id="wrapper">
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<h1>Etherpad lite</h1>
|
<h1>Etherpad</h1>
|
||||||
|
<ul>
|
||||||
|
<% e.begin_block("adminMenu"); %>
|
||||||
<li><a href="../plugins">Plugin manager</a> </li>
|
<li><a href="../plugins">Plugin manager</a> </li>
|
||||||
<li><a href="../settings">Settings</a> </li>
|
<li><a href="../settings">Settings</a> </li>
|
||||||
<li><a href="../plugins/info">Troubleshooting information</a> </li>
|
<li><a href="../plugins/info">Troubleshooting information</a> </li>
|
||||||
|
<% e.end_block(); %>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="innerwrapper">
|
<div class="innerwrapper">
|
||||||
|
@ -34,6 +38,5 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="topborder"></div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Plugin manager - Etherpad lite</title>
|
<title>Plugin manager - Etherpad</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
<meta name="viewport" content="width=device-width">
|
||||||
<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>
|
||||||
|
@ -19,12 +20,15 @@
|
||||||
<% } %>
|
<% } %>
|
||||||
|
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<h1>Etherpad lite</h1>
|
<h1>Etherpad</h1>
|
||||||
|
<ul>
|
||||||
|
<% e.begin_block("adminMenu"); %>
|
||||||
<li><a href="plugins">Plugin manager</a> </li>
|
<li><a href="plugins">Plugin manager</a> </li>
|
||||||
<li><a href="settings">Settings</a> </li>
|
<li><a href="settings">Settings</a> </li>
|
||||||
<li><a href="plugins/info">Troubleshooting information</a> </li>
|
<li><a href="plugins/info">Troubleshooting information</a> </li>
|
||||||
|
<% e.end_block(); %>
|
||||||
<div id="progress"><img src="../static/img/loading.gif" alt=""/> <span class="message"></span></div>
|
</ul>
|
||||||
|
<div id="progress"><img src="../static/img/loading.gif"> <span class="message"></span></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="innerwrapper">
|
<div class="innerwrapper">
|
||||||
|
@ -40,9 +44,9 @@
|
||||||
</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" data-label="Name"></td>
|
||||||
<td class="description"></td>
|
<td class="description" data-label="Description"></td>
|
||||||
<td class="version"></td>
|
<td class="version" data-label="Version"></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>
|
||||||
|
@ -71,9 +75,9 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="template">
|
<tbody class="template">
|
||||||
<tr>
|
<tr>
|
||||||
<td class="name"></td>
|
<td class="name" data-label="Name"></td>
|
||||||
<td class="description"></td>
|
<td class="description" data-label="Description"></td>
|
||||||
<td class="version"></td>
|
<td class="version" data-label="Version"></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>
|
||||||
|
@ -89,6 +93,5 @@
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div id="topborder"></div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>Settings - Etherpad lite</title>
|
<title>Settings - Etherpad</title>
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0">
|
<meta name="viewport" content="width=device-width">
|
||||||
<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>
|
||||||
|
@ -23,22 +24,26 @@
|
||||||
|
|
||||||
|
|
||||||
<div class="menu">
|
<div class="menu">
|
||||||
<h1>Etherpad lite</h1>
|
<h1>Etherpad</h1>
|
||||||
|
<ul>
|
||||||
|
<% e.begin_block("adminMenu"); %>
|
||||||
<li><a href="plugins">Plugin manager</a> </li>
|
<li><a href="plugins">Plugin manager</a> </li>
|
||||||
<li><a href="settings">Settings</a> </li>
|
<li><a href="settings">Settings</a> </li>
|
||||||
<li><a href="plugins/info">Troubleshooting information</a> </li>
|
<li><a href="plugins/info">Troubleshooting information</a> </li>
|
||||||
|
<% e.end_block(); %>
|
||||||
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="innerwrapper">
|
<div class="innerwrapper">
|
||||||
<a href='https://github.com/ether/etherpad-lite/wiki/Example-Production-Settings.JSON'>Example production settings template</a>
|
<h2>Current configuration</h2>
|
||||||
<a href='https://github.com/ether/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 class="separator"></div>
|
||||||
|
<a href='https://github.com/ether/etherpad-lite/wiki/Example-Production-Settings.JSON'>Example production settings template</a>
|
||||||
|
<a href='https://github.com/ether/etherpad-lite/wiki/Example-Development-Settings.JSON'>Example development settings template</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="topborder"></div>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
@ -64,7 +64,8 @@
|
||||||
box-shadow: 0px 1px 8px rgba(0,0,0,0.3);
|
box-shadow: 0px 1px 8px rgba(0,0,0,0.3);
|
||||||
}
|
}
|
||||||
#inner {
|
#inner {
|
||||||
width: 300px;
|
position:relative;
|
||||||
|
max-width: 300px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
#button {
|
#button {
|
||||||
|
@ -100,6 +101,10 @@
|
||||||
text-shadow: 0 1px 1px #fff;
|
text-shadow: 0 1px 1px #fff;
|
||||||
margin: 16px auto 0;
|
margin: 16px auto 0;
|
||||||
}
|
}
|
||||||
|
#padname{
|
||||||
|
height:38px;
|
||||||
|
max-width:280px;
|
||||||
|
}
|
||||||
form {
|
form {
|
||||||
height: 38px;
|
height: 38px;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
|
@ -115,7 +120,8 @@
|
||||||
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;
|
line-height:36px; /* IE8 hack */
|
||||||
|
padding: 0px 45px 0 10px;
|
||||||
*padding: 0; /* IE7 hack */
|
*padding: 0; /* IE7 hack */
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -125,7 +131,7 @@
|
||||||
}
|
}
|
||||||
button[type="submit"] {
|
button[type="submit"] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
left:253px;
|
||||||
width: 45px;
|
width: 45px;
|
||||||
height: 38px;
|
height: 38px;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,10 @@
|
||||||
<% e.end_block(); %>
|
<% e.end_block(); %>
|
||||||
|
|
||||||
<link rel="localizations" type="application/l10n+json" href="../../locales.json" />
|
<link rel="localizations" type="application/l10n+json" href="../../locales.json" />
|
||||||
|
<% e.begin_block("timesliderScripts"); %>
|
||||||
<script type="text/javascript" src="../../static/js/html10n.js"></script>
|
<script type="text/javascript" src="../../static/js/html10n.js"></script>
|
||||||
<script type="text/javascript" src="../../static/js/l10n.js"></script>
|
<script type="text/javascript" src="../../static/js/l10n.js"></script>
|
||||||
|
<% e.end_block(); %>
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<% e.begin_block("timesliderBody"); %>
|
<% e.begin_block("timesliderBody"); %>
|
||||||
|
@ -211,6 +213,8 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
var plugins = require('ep_etherpad-lite/static/js/pluginfw/client_plugins');
|
var plugins = require('ep_etherpad-lite/static/js/pluginfw/client_plugins');
|
||||||
|
var socket = require('ep_etherpad-lite/static/js/timeslider').socket;
|
||||||
|
|
||||||
plugins.baseURL = baseURL;
|
plugins.baseURL = baseURL;
|
||||||
|
|
||||||
plugins.update(function () {
|
plugins.update(function () {
|
||||||
|
|
|
@ -85,8 +85,8 @@ var helper = {};
|
||||||
return !$iframe.contents().find("#editorloadingbox").is(":visible");
|
return !$iframe.contents().find("#editorloadingbox").is(":visible");
|
||||||
}, 50000).done(function(){
|
}, 50000).done(function(){
|
||||||
helper.padChrome$ = getFrameJQuery( $('#iframe-container iframe'));
|
helper.padChrome$ = getFrameJQuery( $('#iframe-container iframe'));
|
||||||
helper.padOuter$ = getFrameJQuery(helper.padChrome$('iframe.[name="ace_outer"]'));
|
helper.padOuter$ = getFrameJQuery(helper.padChrome$('iframe[name="ace_outer"]'));
|
||||||
helper.padInner$ = getFrameJQuery( helper.padOuter$('iframe.[name="ace_inner"]'));
|
helper.padInner$ = getFrameJQuery( helper.padOuter$('iframe[name="ace_inner"]'));
|
||||||
|
|
||||||
//disable all animations, this makes tests faster and easier
|
//disable all animations, this makes tests faster and easier
|
||||||
helper.padChrome$.fx.off = true;
|
helper.padChrome$.fx.off = true;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
<div id="iframe-container"></div>
|
<div id="iframe-container"></div>
|
||||||
|
|
||||||
<script src="/static/js/jquery.js"></script>
|
<script src="/static/js/jquery.js"></script>
|
||||||
|
<script src="/static/js/jquery_browser.js"></script>
|
||||||
<script src="lib/underscore.js"></script>
|
<script src="lib/underscore.js"></script>
|
||||||
|
|
||||||
<script src="lib/mocha.js"></script>
|
<script src="lib/mocha.js"></script>
|
||||||
|
|
|
@ -179,7 +179,11 @@ $(function(){
|
||||||
//inject spec scripts into the dom
|
//inject spec scripts into the dom
|
||||||
var $body = $('body');
|
var $body = $('body');
|
||||||
$.each(specs, function(i, spec){
|
$.each(specs, function(i, spec){
|
||||||
|
if(spec[0] != "/"){ // if the spec isn't a plugin spec which means the spec file might be in a different subfolder
|
||||||
$body.append('<script src="specs/' + spec + '"></script>')
|
$body.append('<script src="specs/' + spec + '"></script>')
|
||||||
|
}else{
|
||||||
|
$body.append('<script src="' + spec + '"></script>')
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
//initalize the test helper
|
//initalize the test helper
|
||||||
|
|
|
@ -100,8 +100,8 @@ describe("embed links", function(){
|
||||||
|
|
||||||
//open share dropdown
|
//open share dropdown
|
||||||
chrome$(".buttonicon-embed").click();
|
chrome$(".buttonicon-embed").click();
|
||||||
//check read only checkbox, a bit hacky
|
chrome$('#readonlyinput').click();
|
||||||
chrome$('#readonlyinput').attr('checked','checked').click().attr('checked','checked');
|
chrome$('#readonlyinput:checkbox:not(:checked)').attr('checked', 'checked');
|
||||||
|
|
||||||
//get the link of the share field + the actual pad url and compare them
|
//get the link of the share field + the actual pad url and compare them
|
||||||
var shareLink = chrome$("#linkinput").val();
|
var shareLink = chrome$("#linkinput").val();
|
||||||
|
@ -119,7 +119,9 @@ describe("embed links", function(){
|
||||||
//open share dropdown
|
//open share dropdown
|
||||||
chrome$(".buttonicon-embed").click();
|
chrome$(".buttonicon-embed").click();
|
||||||
//check read only checkbox, a bit hacky
|
//check read only checkbox, a bit hacky
|
||||||
chrome$('#readonlyinput').attr('checked','checked').click().attr('checked','checked');
|
chrome$('#readonlyinput').click();
|
||||||
|
chrome$('#readonlyinput:checkbox:not(:checked)').attr('checked', 'checked');
|
||||||
|
|
||||||
|
|
||||||
//get the link of the share field + the actual pad url and compare them
|
//get the link of the share field + the actual pad url and compare them
|
||||||
var embedCode = chrome$("#embedinput").val();
|
var embedCode = chrome$("#embedinput").val();
|
||||||
|
@ -129,5 +131,6 @@ describe("embed links", function(){
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,6 +19,7 @@ describe("font select", function(){
|
||||||
|
|
||||||
//select monospace and fire change event
|
//select monospace and fire change event
|
||||||
$monospaceoption.attr('selected','selected');
|
$monospaceoption.attr('selected','selected');
|
||||||
|
$viewfontmenu.val("monospace");
|
||||||
$viewfontmenu.change();
|
$viewfontmenu.change();
|
||||||
|
|
||||||
//check if font changed to monospace
|
//check if font changed to monospace
|
||||||
|
|
|
@ -56,10 +56,8 @@ describe("Language select and change", function(){
|
||||||
|
|
||||||
//click the language button
|
//click the language button
|
||||||
var $language = chrome$("#languagemenu");
|
var $language = chrome$("#languagemenu");
|
||||||
var $languageoption = $language.find("[value=en]");
|
//select english
|
||||||
|
$language.val("en");
|
||||||
//select german
|
|
||||||
$languageoption.attr('selected','selected');
|
|
||||||
$language.change();
|
$language.change();
|
||||||
|
|
||||||
//get the value of the bold button
|
//get the value of the bold button
|
||||||
|
|
64
tests/frontend/specs/timeslider_labels.js
Normal file
64
tests/frontend/specs/timeslider_labels.js
Normal file
|
@ -0,0 +1,64 @@
|
||||||
|
describe("timeslider", function(){
|
||||||
|
//create a new pad before each test run
|
||||||
|
beforeEach(function(cb){
|
||||||
|
helper.newPad(cb);
|
||||||
|
this.timeout(60000);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("Shows a date and time in the timeslider and make sure it doesn't include NaN", function(done) {
|
||||||
|
var inner$ = helper.padInner$;
|
||||||
|
var chrome$ = helper.padChrome$;
|
||||||
|
|
||||||
|
// make some changes to produce 100 revisions
|
||||||
|
var revs = 10;
|
||||||
|
this.timeout(60000);
|
||||||
|
for(var i=0; i < revs; i++) {
|
||||||
|
setTimeout(function() {
|
||||||
|
// enter 'a' in the first text element
|
||||||
|
inner$("div").first().sendkeys('a');
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
// go to timeslider
|
||||||
|
$('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider');
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
var timeslider$ = $('#iframe-container iframe')[0].contentWindow.$;
|
||||||
|
var $sliderBar = timeslider$('#ui-slider-bar');
|
||||||
|
|
||||||
|
var latestContents = timeslider$('#padcontent').text();
|
||||||
|
|
||||||
|
// Expect the date and time to be shown
|
||||||
|
|
||||||
|
// Click somewhere on the timeslider
|
||||||
|
var e = new jQuery.Event('mousedown');
|
||||||
|
e.clientX = e.pageX = 150;
|
||||||
|
e.clientY = e.pageY = 45;
|
||||||
|
$sliderBar.trigger(e);
|
||||||
|
|
||||||
|
e = new jQuery.Event('mousedown');
|
||||||
|
e.clientX = e.pageX = 150;
|
||||||
|
e.clientY = e.pageY = 40;
|
||||||
|
$sliderBar.trigger(e);
|
||||||
|
|
||||||
|
e = new jQuery.Event('mousedown');
|
||||||
|
e.clientX = e.pageX = 150;
|
||||||
|
e.clientY = e.pageY = 50;
|
||||||
|
$sliderBar.trigger(e);
|
||||||
|
|
||||||
|
$sliderBar.trigger('mouseup')
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
//make sure the text has changed
|
||||||
|
expect( timeslider$('#timer').text() ).not.to.eql( "" );
|
||||||
|
expect( timeslider$('#revision_date').text() ).not.to.eql( "" );
|
||||||
|
expect( timeslider$('#revision_label').text() ).not.to.eql( "" );
|
||||||
|
var includesNaN = timeslider$('#revision_label').text().indexOf("NaN"); // NaN is bad. Naan ist gut
|
||||||
|
expect( includesNaN ).to.eql( -1 ); // not quite so tasty, I like curry.
|
||||||
|
done();
|
||||||
|
}, 400);
|
||||||
|
}, 2000);
|
||||||
|
}, 2000);
|
||||||
|
});
|
||||||
|
});
|
|
@ -4,8 +4,7 @@ describe("timeslider", function(){
|
||||||
helper.newPad(cb);
|
helper.newPad(cb);
|
||||||
this.timeout(6000);
|
this.timeout(6000);
|
||||||
});
|
});
|
||||||
|
it("loads adds a hundred revisions", function(done) {
|
||||||
xit("loads adds a hundred revisions", function(done) {
|
|
||||||
var inner$ = helper.padInner$;
|
var inner$ = helper.padInner$;
|
||||||
var chrome$ = helper.padChrome$;
|
var chrome$ = helper.padChrome$;
|
||||||
|
|
||||||
|
@ -57,14 +56,13 @@ describe("timeslider", function(){
|
||||||
}, 6000);
|
}, 6000);
|
||||||
}, revs*timePerRev);
|
}, revs*timePerRev);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("changes the url when clicking on the timeslider", function(done) {
|
it("changes the url when clicking on the timeslider", function(done) {
|
||||||
var inner$ = helper.padInner$;
|
var inner$ = helper.padInner$;
|
||||||
var chrome$ = helper.padChrome$;
|
var chrome$ = helper.padChrome$;
|
||||||
|
|
||||||
// make some changes to produce 7 revisions
|
// make some changes to produce 7 revisions
|
||||||
var timePerRev = 900
|
var timePerRev = 1000
|
||||||
, revs = 7;
|
, revs = 20;
|
||||||
this.timeout(revs*timePerRev+10000);
|
this.timeout(revs*timePerRev+10000);
|
||||||
for(var i=0; i < revs; i++) {
|
for(var i=0; i < revs; i++) {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
|
@ -100,28 +98,48 @@ describe("timeslider", function(){
|
||||||
}, 6000);
|
}, 6000);
|
||||||
}, revs*timePerRev);
|
}, revs*timePerRev);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("jumps to a revision given in the url", function(done) {
|
it("jumps to a revision given in the url", function(done) {
|
||||||
var inner$ = helper.padInner$;
|
var inner$ = helper.padInner$;
|
||||||
var chrome$ = helper.padChrome$;
|
var chrome$ = helper.padChrome$;
|
||||||
this.timeout(11000);
|
this.timeout(20000);
|
||||||
|
|
||||||
|
// wait for the text to be loaded
|
||||||
|
helper.waitFor(function(){
|
||||||
|
return inner$('body').text().length != 0;
|
||||||
|
}, 6000).always(function() {
|
||||||
|
var newLines = inner$('body div').length;
|
||||||
|
var oldLength = inner$('body').text().length + newLines / 2;
|
||||||
|
expect( oldLength ).to.not.eql( 0 );
|
||||||
inner$("div").first().sendkeys('a');
|
inner$("div").first().sendkeys('a');
|
||||||
|
|
||||||
setTimeout(function() {
|
// wait for our additional revision to be added
|
||||||
// go to timeslider
|
|
||||||
$('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider#0');
|
|
||||||
var timeslider$;
|
|
||||||
|
|
||||||
helper.waitFor(function(){
|
helper.waitFor(function(){
|
||||||
|
// newLines takes the new lines into account which are strippen when using
|
||||||
|
// inner$('body').text(), one <div> is used for one line in ACE.
|
||||||
|
var lenOkay = inner$('body').text().length + newLines / 2 != oldLength;
|
||||||
|
// this waits for the color to be added to our <span>, which means that the revision
|
||||||
|
// was accepted by the server.
|
||||||
|
var colorOkay = inner$('span').first().attr('class').indexOf("author-") == 0;
|
||||||
|
return lenOkay && colorOkay;
|
||||||
|
}, 6000).always(function() {
|
||||||
|
// go to timeslider with a specific revision set
|
||||||
|
$('#iframe-container iframe').attr('src', $('#iframe-container iframe').attr('src')+'/timeslider#0');
|
||||||
|
|
||||||
|
// wait for the timeslider to be loaded
|
||||||
|
helper.waitFor(function(){
|
||||||
|
try {
|
||||||
timeslider$ = $('#iframe-container iframe')[0].contentWindow.$;
|
timeslider$ = $('#iframe-container iframe')[0].contentWindow.$;
|
||||||
return timeslider$ && timeslider$('#padcontent').text().length == 230;
|
} catch(e){}
|
||||||
|
if(timeslider$){
|
||||||
|
return timeslider$('#padcontent').text().length == oldLength;
|
||||||
|
}
|
||||||
}, 6000).always(function(){
|
}, 6000).always(function(){
|
||||||
expect( timeslider$('#padcontent').text().length ).to.eql( 230 );
|
expect( timeslider$('#padcontent').text().length ).to.eql( oldLength );
|
||||||
done();
|
done();
|
||||||
});
|
});
|
||||||
}, 2500);
|
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
it("checks the export url", function(done) {
|
it("checks the export url", function(done) {
|
||||||
var inner$ = helper.padInner$;
|
var inner$ = helper.padInner$;
|
||||||
var chrome$ = helper.padChrome$;
|
var chrome$ = helper.padChrome$;
|
||||||
|
@ -135,7 +153,9 @@ describe("timeslider", function(){
|
||||||
var exportLink;
|
var exportLink;
|
||||||
|
|
||||||
helper.waitFor(function(){
|
helper.waitFor(function(){
|
||||||
|
try{
|
||||||
timeslider$ = $('#iframe-container iframe')[0].contentWindow.$;
|
timeslider$ = $('#iframe-container iframe')[0].contentWindow.$;
|
||||||
|
}catch(e){}
|
||||||
if(!timeslider$)
|
if(!timeslider$)
|
||||||
return false;
|
return false;
|
||||||
exportLink = timeslider$('#exportplaina').attr('href');
|
exportLink = timeslider$('#exportplaina').attr('href');
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue