diff --git a/CHANGELOG.md b/CHANGELOG.md index 052a819c0..762ef39e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,34 @@ +# 1.5.0 + * NEW: Lots of performance improvements for page load times + * NEW: Hook for adding CSS to Exports + * NEW: Allow shardable socket io + * NEW: Allow UI to show when attr/prop is applied (CSS) + * NEW: Various scripts + * NEW: Export full fidelity pads (including authors etc.) + * NEW: Various front end tests + * NEW: Backend tests + * NEW: switchPad hook to instantly switch between pads + * NEW: Various translations + * NEW: Icon sets instead of images to provide quality high DPI experience + * Fix: HTML Import blocking / hanging server + * Fix: Export Bullet / Numbered lists HTML + * Fix: Swagger deprecated warning + * Fix: Bad session from crashing server + * Fix: Allow relative settings path + * Fix: Stop attributes being improperly assigned between 2 lines + * Fix: Copy / Move Pad API race condition + * Fix: Save all user preferences + * Fix: Upgrade majority of dependency inc upgrade to SocketIO1+ + * Fix: Provide UI button to restore maximized chat window + * Fix: Timeslider UI Fix + * Fix: Remove Dokuwiki + * Fix: Remove long paths from windows build (stops error during extract) + * Fix: Various globals remvoed + * Fix: Move all scripts into bin/ + * Fix: Various CSS bugfixes for Mobile devices + * Fix: Overflow Toolbar + * Fix: Line Attribute management + # 1.4.1 * NEW: Translations * NEW: userLeave Hook diff --git a/Makefile b/Makefile index b656d5d9b..25fbf8e87 100644 --- a/Makefile +++ b/Makefile @@ -14,7 +14,7 @@ out/doc/assets/%: doc/assets/% out/doc/%.html: doc/%.md mkdir -p $(@D) - node tools/doc/generate.js --format=html --template=doc/template.html $< > $@ + node bin/doc/generate.js --format=html --template=doc/template.html $< > $@ ifeq ($(UNAME),Darwin) sed -i '' 's/__VERSION__/${VERSION}/' $@ else diff --git a/README.md b/README.md index c5186decc..0cddb0b0f 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ that allows your web application to manage pads, users and groups. It is recomme 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. By default your Etherpad is rather sparce and because Etherpad takes a lot of it's inspiration from Wordpress plugins are really easy to install and update. Once you have Etherpad installed you should visit the plugin page and take control. +There's also a full-featured plugin framework, allowing you to easily add your own features. By default your Etherpad is rather sparse and because Etherpad takes a lot of it's inspiration from Wordpress plugins are really easy to install and update. Once you have Etherpad installed you should visit the plugin page and take control. Finally, Etherpad comes with translations into most languages! Users are automatically delivered the correct language for their local settings. @@ -50,9 +50,9 @@ Update to the latest version with `git pull origin`, then run `bin\installOnWind ## GNU/Linux and other UNIX-like systems You'll need gzip, git, curl, libssl develop libraries, python and gcc. -*For Debian/Ubuntu*: `apt-get install gzip git-core curl python libssl-dev pkg-config build-essential` -*For Fedora/CentOS*: `yum install gzip git-core curl python openssl-devel && yum groupinstall "Development Tools"` -*For FreeBSD*: `portinstall node, npm, git (optional)` +- *For Debian/Ubuntu*: `apt-get install gzip git-core curl python libssl-dev pkg-config build-essential` +- *For Fedora/CentOS*: `yum install gzip git-core curl python openssl-devel && yum groupinstall "Development Tools"` +- *For FreeBSD*: `portinstall node, npm, git (optional)` Additionally, you'll need [node.js](http://nodejs.org) installed, Ideally the latest stable version, we recommend installing/compiling nodejs from source (avoiding apt). @@ -74,6 +74,10 @@ You can initially modify the settings in `settings.json`. (If you need to handle You should use a dedicated database such as "mysql", if you are planning on using etherpad-in a production environment, since the "dirtyDB" database driver is only for testing and/or development purposes. +## Plugins and themes + +Etherpad is very customizable through plugins. Instructions for installing themes and plugins can be found in [the plugin wiki article](https://github.com/ether/etherpad-lite/wiki/Available-Plugins). + ## Helpful resources The [wiki](https://github.com/ether/etherpad-lite/wiki) is your one-stop resource for Tutorials and How-to's, really check it out! Also, feel free to improve these wiki pages. diff --git a/bin/backendTests.sh b/bin/backendTests.sh new file mode 100755 index 000000000..ec12775ba --- /dev/null +++ b/bin/backendTests.sh @@ -0,0 +1 @@ +src/node_modules/mocha/bin/mocha --timeout 5000 --reporter nyan tests/backend/specs/api diff --git a/bin/buildForWindows.sh b/bin/buildForWindows.sh index a1e2c7570..78441ba04 100755 --- a/bin/buildForWindows.sh +++ b/bin/buildForWindows.sh @@ -58,6 +58,8 @@ rm -rf .git/objects echo "remove windows jsdom-nocontextify/test folder" rm -rf /tmp/etherpad-lite-win/node_modules/ep_etherpad-lite/node_modules/jsdom-nocontextifiy/test/ rm -rf /tmp/etherpad-lite-win/src/node_modules/jsdom-nocontextifiy/test/ +rm -rf /tmp/etherpad-lite-win/src/node_modules/wd/node_modules/request/node_modules/form-data/node_modules/combined-stream/test +rm -rf /tmp/etherpad-lite-win/src/node_modules/nodemailer/node_modules/mailcomposer/node_modules/mimelib/node_modules/encoding/node_modules/iconv-lite/encodings/tables echo "create the zip..." cd /tmp diff --git a/bin/dirty-db-cleaner.py b/bin/dirty-db-cleaner.py new file mode 100755 index 000000000..8ed9c5065 --- /dev/null +++ b/bin/dirty-db-cleaner.py @@ -0,0 +1,45 @@ +#!/usr/bin/python -u +# +# Created by Bjarni R. Einarsson, placed in the public domain. Go wild! +# +import json +import os +import sys + +try: + dirtydb_input = sys.argv[1] + dirtydb_output = '%s.new' % dirtydb_input + assert(os.path.exists(dirtydb_input)) + assert(not os.path.exists(dirtydb_output)) +except: + print + print 'Usage: %s /path/to/dirty.db' % sys.argv[0] + print + print 'Note: Will create a file named dirty.db.new in the same folder,' + print ' please make sure permissions are OK and a file by that' + print ' name does not exist already. This script works by omitting' + print ' duplicate lines from the dirty.db file, keeping only the' + print ' last (latest) instance. No revision data should be lost,' + print ' but be careful, make backups. If it breaks you get to keep' + print ' both pieces!' + print + sys.exit(1) + +dirtydb = {} +lines = 0 +with open(dirtydb_input, 'r') as fd: + print 'Reading %s' % dirtydb_input + for line in fd: + lines += 1 + data = json.loads(line) + dirtydb[data['key']] = line + if lines % 10000 == 0: + sys.stderr.write('.') +print +print 'OK, found %d unique keys in %d lines' % (len(dirtydb), lines) + +with open(dirtydb_output, 'w') as fd: + for data in dirtydb.values(): + fd.write(data) + +print 'Wrote data to %s. All done!' % dirtydb_output diff --git a/tools/doc/LICENSE b/bin/doc/LICENSE similarity index 100% rename from tools/doc/LICENSE rename to bin/doc/LICENSE diff --git a/tools/doc/README.md b/bin/doc/README.md similarity index 100% rename from tools/doc/README.md rename to bin/doc/README.md diff --git a/tools/doc/generate.js b/bin/doc/generate.js similarity index 100% rename from tools/doc/generate.js rename to bin/doc/generate.js diff --git a/tools/doc/html.js b/bin/doc/html.js similarity index 100% rename from tools/doc/html.js rename to bin/doc/html.js diff --git a/tools/doc/json.js b/bin/doc/json.js similarity index 100% rename from tools/doc/json.js rename to bin/doc/json.js diff --git a/tools/doc/node_modules/.bin/marked b/bin/doc/node_modules/.bin/marked similarity index 100% rename from tools/doc/node_modules/.bin/marked rename to bin/doc/node_modules/.bin/marked diff --git a/tools/doc/node_modules/marked/.npmignore b/bin/doc/node_modules/marked/.npmignore similarity index 100% rename from tools/doc/node_modules/marked/.npmignore rename to bin/doc/node_modules/marked/.npmignore diff --git a/tools/doc/node_modules/marked/LICENSE b/bin/doc/node_modules/marked/LICENSE similarity index 100% rename from tools/doc/node_modules/marked/LICENSE rename to bin/doc/node_modules/marked/LICENSE diff --git a/tools/doc/node_modules/marked/Makefile b/bin/doc/node_modules/marked/Makefile similarity index 100% rename from tools/doc/node_modules/marked/Makefile rename to bin/doc/node_modules/marked/Makefile diff --git a/tools/doc/node_modules/marked/README.md b/bin/doc/node_modules/marked/README.md similarity index 100% rename from tools/doc/node_modules/marked/README.md rename to bin/doc/node_modules/marked/README.md diff --git a/tools/doc/node_modules/marked/bin/marked b/bin/doc/node_modules/marked/bin/marked similarity index 100% rename from tools/doc/node_modules/marked/bin/marked rename to bin/doc/node_modules/marked/bin/marked diff --git a/tools/doc/node_modules/marked/index.js b/bin/doc/node_modules/marked/index.js similarity index 100% rename from tools/doc/node_modules/marked/index.js rename to bin/doc/node_modules/marked/index.js diff --git a/tools/doc/node_modules/marked/lib/marked.js b/bin/doc/node_modules/marked/lib/marked.js similarity index 100% rename from tools/doc/node_modules/marked/lib/marked.js rename to bin/doc/node_modules/marked/lib/marked.js diff --git a/tools/doc/node_modules/marked/man/marked.1 b/bin/doc/node_modules/marked/man/marked.1 similarity index 100% rename from tools/doc/node_modules/marked/man/marked.1 rename to bin/doc/node_modules/marked/man/marked.1 diff --git a/tools/doc/node_modules/marked/package.json b/bin/doc/node_modules/marked/package.json similarity index 100% rename from tools/doc/node_modules/marked/package.json rename to bin/doc/node_modules/marked/package.json diff --git a/tools/doc/package.json b/bin/doc/package.json similarity index 100% rename from tools/doc/package.json rename to bin/doc/package.json diff --git a/bin/installDeps.sh b/bin/installDeps.sh index 84f2e227f..58eb32f2d 100755 --- a/bin/installDeps.sh +++ b/bin/installDeps.sh @@ -36,8 +36,9 @@ hash npm > /dev/null 2>&1 || { #check npm version NPM_VERSION=$(npm --version) -if [ ! $(echo $NPM_VERSION | cut -d "." -f 1) = "1" ]; then - echo "You're running a wrong version of npm, you're using $NPM_VERSION, we need 1.x" >&2 +NPM_MAIN_VERSION=$(echo $NPM_VERSION | cut -d "." -f 1) +if [ $(echo $NPM_MAIN_VERSION) = "0" ]; then + echo "You're running a wrong version of npm, you're using $NPM_VERSION, we need 1.x or higher" >&2 exit 1 fi @@ -98,7 +99,7 @@ fi echo "Clear minfified cache..." rm -f var/minified* -echo "ensure custom css/js files are created..." +echo "Ensure custom css/js files are created..." for f in "index" "pad" "timeslider" do diff --git a/bin/jshint.sh b/bin/jshint.sh deleted file mode 100755 index 4dea73961..000000000 --- a/bin/jshint.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh - -if [ -d "../bin" ]; then - cd "../" -fi - -JSHINT=./node_modules/jshint/bin/hint - -$JSHINT ./node/ diff --git a/bin/loadTesting/README b/bin/loadTesting/README deleted file mode 100644 index c8ecd71e4..000000000 --- a/bin/loadTesting/README +++ /dev/null @@ -1,79 +0,0 @@ -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. - -TODO: -Emulate characters being typed into a pad - -HOW TO USE (from @mjd75) proper formatting at: https://github.com/ether/etherpad-lite/issues/360 - -Server 1: -Installed Node.js (etc), EtherPad and MySQL - -Server 2: -Installed Xvfb and PhantomJS - -I installed Xvfb following (roughly) this guide: http://blog.martin-lyness.com/archives/installing-xvfb-on-ubuntu-9-10-karmic-koala - - #sudo apt-get install xvfb - #sudo apt-get install xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic - -Launched two instances of Xvfb directly from the terminal: - - #Xvfb :0 -ac - #Xvfb :1 -ac - -I installed PhantomJS following this guide: http://code.google.com/p/phantomjs/wiki/Installation - - #sudo add-apt-repository ppa:jerome-etienne/neoip - #sudo apt-get update - #sudo apt-get install phantomjs - -I created a small JavaScript file for PhatomJS to use to control the browser instances: - -### BEGIN JAVASCRIPT ### - -var page = new WebPage(), - t, address; - -if (phantom.args.length === 0) { - console.log('Usage: loader.js '); - phantom.exit(); -} else { - t = Date.now(); - address = phantom.args[0]; - - var page = new WebPage(); - page.onResourceRequested = function (request) { - console.log('Request ' + JSON.stringify(request, undefined, 4)); - }; - page.onResourceReceived = function (response) { - console.log('Receive ' + JSON.stringify(response, undefined, 4)); - }; - page.open(address); - -} - -### END JAVASCRIPT ### - -And finally a launcher script that uses screen to run 400 instances of PhantomJS with the above script: - -### BEGIN SHELL SCRIPT ### - -#!/bin/bash - -# connect 200 instances to display :0 -for i in {1..200} -do - DISPLAY=:0 screen -d -m phantomjs loader.js http://ec2-50-17-168-xx.compute-1.amazonaws.com:9001/p/pad2 && sleep 2 -done - -# connect 200 instances to display :1 -for i in {1..200} -do - DISPLAY=:1 screen -d -m phantomjs loader.js http://ec2-50-17-168-xx.compute-1.amazonaws.com:9001/p/pad2 && sleep 2 -done - -### END SHELL SCRIPT ### diff --git a/bin/loadTesting/launcher.sh b/bin/loadTesting/launcher.sh deleted file mode 100755 index e940f8e0f..000000000 --- a/bin/loadTesting/launcher.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/bin/bash - -# connect 500 instances to display :0 -for i in {1..500} -do - echo $i - echo "Displaying Some shit" - DISPLAY=:0 screen -d -m /home/phantomjs/bin/phantomjs loader.js http://10.0.0.55:9001/p/pad2 && sleep 2 -done - -# connect 500 instances to display :1 -for i in {1..500} -do - echo $i - DISPLAY=:1 screen -d -m /home/phantomjs/bin/phantomjs loader.js http://10.0.0.55:9001/p/pad2 && sleep 2 -done diff --git a/bin/loadTesting/loader.js b/bin/loadTesting/loader.js deleted file mode 100644 index ddcd0572d..000000000 --- a/bin/loadTesting/loader.js +++ /dev/null @@ -1,20 +0,0 @@ -var page = new WebPage(), - t, address; - -if (phantom.args.length === 0) { - console.log('Usage: loader.js '); - phantom.exit(); -} else { - t = Date.now(); - address = phantom.args[0]; - - var page = new WebPage(); - page.onResourceRequested = function (request) { - console.log('Request ' + JSON.stringify(request, undefined, 4)); - }; - page.onResourceReceived = function (response) { - console.log('Receive ' + JSON.stringify(response, undefined, 4)); - }; - page.open(address); - -} diff --git a/bin/rebuildPad.js b/bin/rebuildPad.js new file mode 100644 index 000000000..c83833420 --- /dev/null +++ b/bin/rebuildPad.js @@ -0,0 +1,120 @@ +/* + This is a repair tool. It rebuilds an old pad at a new pad location up to a + known "good" revision. +*/ + +if(process.argv.length != 4 && process.argv.length != 5) { + console.error("Use: node bin/repairPad.js $PADID $REV [$NEWPADID]"); + process.exit(1); +} + +var npm = require("../src/node_modules/npm"); +var async = require("../src/node_modules/async"); +var ueberDB = require("../src/node_modules/ueberDB"); + +var padId = process.argv[2]; +var newRevHead = process.argv[3]; +var newPadId = process.argv[4] || padId + "-rebuilt"; + +var db, oldPad, newPad, settings; +var AuthorManager, ChangeSet, Pad, PadManager; + +async.series([ + function(callback) { + npm.load({}, function(err) { + if(err) { + console.error("Could not load NPM: " + err) + process.exit(1); + } else { + callback(); + } + }) + }, + function(callback) { + // Get a handle into the database + db = require('../src/node/db/DB'); + db.init(callback); + }, function(callback) { + PadManager = require('../src/node/db/PadManager'); + Pad = require('../src/node/db/Pad').Pad; + // Get references to the original pad and to a newly created pad + // HACK: This is a standalone script, so we want to write everything + // out to the database immediately. The only problem with this is + // that a driver (like the mysql driver) can hardcode these values. + db.db.db.settings = {cache: 0, writeInterval: 0, json: true}; + // Validate the newPadId if specified and that a pad with that ID does + // not already exist to avoid overwriting it. + if (!PadManager.isValidPadId(newPadId)) { + console.error("Cannot create a pad with that id as it is invalid"); + process.exit(1); + } + PadManager.doesPadExists(newPadId, function(err, exists) { + if (exists) { + console.error("Cannot create a pad with that id as it already exists"); + process.exit(1); + } + }); + PadManager.getPad(padId, function(err, pad) { + oldPad = pad; + newPad = new Pad(newPadId); + callback(); + }); + }, function(callback) { + // Clone all Chat revisions + var chatHead = oldPad.chatHead; + for(var i = 0, curHeadNum = 0; i <= chatHead; i++) { + db.db.get("pad:" + padId + ":chat:" + i, function (err, chat) { + db.db.set("pad:" + newPadId + ":chat:" + curHeadNum++, chat); + console.log("Created: Chat Revision: pad:" + newPadId + ":chat:" + curHeadNum); + }); + } + callback(); + }, function(callback) { + // Rebuild Pad from revisions up to and including the new revision head + AuthorManager = require("../src/node/db/AuthorManager"); + Changeset = require("ep_etherpad-lite/static/js/Changeset"); + // Author attributes are derived from changesets, but there can also be + // non-author attributes with specific mappings that changesets depend on + // and, AFAICT, cannot be recreated any other way + newPad.pool.numToAttrib = oldPad.pool.numToAttrib; + for(var curRevNum = 0; curRevNum <= newRevHead; curRevNum++) { + db.db.get("pad:" + padId + ":revs:" + curRevNum, function(err, rev) { + var newRevNum = ++newPad.head; + var newRevId = "pad:" + newPad.id + ":revs:" + newRevNum; + db.db.set(newRevId, rev); + AuthorManager.addPad(rev.meta.author, newPad.id); + newPad.atext = Changeset.applyToAText(rev.changeset, newPad.atext, newPad.pool); + console.log("Created: Revision: pad:" + newPad.id + ":revs:" + newRevNum); + if (newRevNum == newRevHead) { + callback(); + } + }); + } + }, function(callback) { + // Add saved revisions up to the new revision head + console.log(newPad.head); + var newSavedRevisions = []; + for(var i in oldPad.savedRevisions) { + savedRev = oldPad.savedRevisions[i] + if (savedRev.revNum <= newRevHead) { + newSavedRevisions.push(savedRev); + console.log("Added: Saved Revision: " + savedRev.revNum); + } + } + newPad.savedRevisions = newSavedRevisions; + callback(); + }, function(callback) { + // Save the source pad + db.db.set("pad:"+newPadId, newPad, function(err) { + console.log("Created: Source Pad: pad:" + newPadId); + newPad.saveToDatabase(); + callback(); + }); + } +], function (err) { + if(err) throw err; + else { + console.info("finished"); + process.exit(0); + } +}); diff --git a/bin/run.sh b/bin/run.sh index 92ae8d482..f21623101 100755 --- a/bin/run.sh +++ b/bin/run.sh @@ -32,7 +32,7 @@ fi bin/installDeps.sh $* || exit 1 #Move to the node folder and start -echo "start..." +echo "Started Etherpad..." SCRIPTPATH=`pwd -P` node $SCRIPTPATH/node_modules/ep_etherpad-lite/node/server.js $* diff --git a/bin/updatePlugins.sh b/bin/updatePlugins.sh new file mode 100755 index 000000000..d696eca79 --- /dev/null +++ b/bin/updatePlugins.sh @@ -0,0 +1,12 @@ +#!/bin/sh + +#Move to the folder where ep-lite is installed +cd `dirname $0` + +#Was this script started in the bin folder? if yes move out +if [ -d "../bin" ]; then + cd "../" +fi + +npm outdated --depth=0 | grep -v "^Package" | awk '{print $1}' | xargs npm install $1 --save-dev + diff --git a/doc/api/hooks_client-side.md b/doc/api/hooks_client-side.md index b8a58b316..ca429a075 100644 --- a/doc/api/hooks_client-side.md +++ b/doc/api/hooks_client-side.md @@ -80,6 +80,22 @@ This hook is called during the attribute processing procedure, and should be use The return value for this function should be a list of classes, which will then be parsed into a valid class string. +## aceAttribClasses +Called from: src/static/js/linestylefilter.js + +Things in context: +1. Attributes - Object of Attributes + +This hook is called when attributes are investigated on a line. It is useful if you want to add another attribute type or property type to a pad. + +Example: +``` +exports.aceAttribClasses = function(hook_name, attr, cb){ + attr.sub = 'tag:sub'; + cb(attr); +} +``` + ## aceGetFilterStack Called from: src/static/js/linestylefilter.js diff --git a/doc/api/hooks_server-side.md b/doc/api/hooks_server-side.md index 435872ea1..251cbf11e 100644 --- a/doc/api/hooks_server-side.md +++ b/doc/api/hooks_server-side.md @@ -247,6 +247,40 @@ Things in context: This hook will allow a plug-in developer to re-write each line when exporting to HTML. +## stylesForExport +Called from: src/node/utils/ExportHtml.js + +Things in context: + +1. padId - The Pad Id + +This hook will allow a plug-in developer to append Styles to the Exported HTML. + +Example: + +``` +exports.stylesForExport = function(hook, padId, cb){ + cb("body{font-size:13.37em !important}"); +} +``` + +## aceAttribClasses +Called from: src/static/js/linestylefilter.js + +Things in context: +1. Attributes - Object of Attributes + +This hook is called when attributes are investigated on a line. It is useful if you want to add another attribute type or property type to a pad. + +Example: + +``` +exports.aceAttribClasses = function(hook_name, attr, cb){ + attr.sub = 'tag:sub'; + cb(attr); +} +``` + ## exportFileName Called from src/node/handler/ExportHandler.js @@ -264,6 +298,24 @@ exports.exportFileName = function(hook, padId, callback){ } ``` +## exportHtmlAdditionalTags +Called from src/node/utils/ExportHtml.js + +Things in context: + +1. Pad object + +This hook will allow a plug-in developer to include more properties and attributes to support during HTML Export. An Array should be returned. + +Example: +``` +// Add the props to be supported in export +exports.exportHtmlAdditionalTags = function(hook, pad, cb){ + var padId = pad.id; + cb(["massive","jugs"]); +}; + + ## userLeave Called from src/node/handler/PadMessageHandler.js diff --git a/settings.json.template b/settings.json.template index 5868af6a3..3f84af9b8 100644 --- a/settings.json.template +++ b/settings.json.template @@ -74,19 +74,22 @@ /* This is the path to the Abiword executable. Setting it to null, disables abiword. Abiword is needed to advanced import/export features of pads*/ "abiword" : null, + + /* Allow import of file types other than the supported types: txt, doc, docx, rtf, odt, html & htm */ + "allowUnknownFileEnds" : true, /* This setting is used if you require authentication of all users. Note: /admin always requires authentication. */ - "requireAuthentication": false, + "requireAuthentication" : false, /* Require authorization by a module, or a user with is_admin set, see below. */ - "requireAuthorization": false, + "requireAuthorization" : false, /*when you use NginX or another proxy/ load-balancer set this to true*/ - "trustProxy": false, + "trustProxy" : false, /* Privacy: disable IP logging */ - "disableIPlogging": false, + "disableIPlogging" : false, /* Users for basic authentication. is_admin = true gives access to /admin. If you do not uncomment this, /admin will not be available! */ diff --git a/src/locales/af.json b/src/locales/af.json index 9bf302e0d..eb04e479c 100644 --- a/src/locales/af.json +++ b/src/locales/af.json @@ -25,7 +25,6 @@ "pad.settings.fontType.monospaced": "Monospasie", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportpdf": "PDF", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.modals.userdup.advice": "Maak weer 'n verbinding as u die venster wil gebruik.", "pad.modals.unauth": "Nie toegestaan", "pad.modals.deleted": "Geskrap.", diff --git a/src/locales/ar.json b/src/locales/ar.json index 6e5d14bd5..b4ea58dd2 100644 --- a/src/locales/ar.json +++ b/src/locales/ar.json @@ -2,7 +2,8 @@ "@metadata": { "authors": [ "Ali1", - "Tux-tn" + "Tux-tn", + "Alami" ] }, "index.newPad": "باد جديد", @@ -17,6 +18,7 @@ "pad.toolbar.unindent.title": "حذف الإزاحة", "pad.toolbar.undo.title": "فك (Ctrl-Z)", "pad.toolbar.redo.title": "تكرار (Ctrl-Y)", + "pad.toolbar.clearAuthorship.title": "مسح ألوان التأليف", "pad.toolbar.import_export.title": "استيراد/تصدير من/إلى تنسيقات ملفات مختلفة", "pad.toolbar.timeslider.title": "متصفح التاريخ", "pad.toolbar.savedRevision.title": "حفظ المراجعة", @@ -49,7 +51,7 @@ "pad.importExport.exportword": "مايكروسوفت وورد", "pad.importExport.exportpdf": "صيغة المستندات المحمولة", "pad.importExport.exportopen": "ODF (نسق المستند المفتوح)", - "pad.importExport.exportdokuwiki": "دوکوويكي", + "pad.importExport.abiword.innerHTML": "لايمكنك الاستيراد إلا من نص عادي أو من تنسيقات إتش تي إم إل. للحصول على المزيد من ميزات الاستيراد المتقدمة، يرجى تثبيت أبيورد .", "pad.modals.connected": "متصل.", "pad.modals.reconnecting": "إعادة الاتصال ببادك", "pad.modals.forcereconnect": "فرض إعادة الاتصال", @@ -57,21 +59,31 @@ "pad.modals.userdup.explanation": "يبدو أن هذا الباد تم فتحه في أكثر من نافذة متصفح في هذا الحاسوب.", "pad.modals.userdup.advice": "إعادة الاتصال لإستعمال هذه النافذة بدلاً من الاخرى.", "pad.modals.unauth": "غير مخول", + "pad.modals.unauth.explanation": "لقد تغيرت الأذونات الخاصة بك أثناء عرض هذه الصفحة. حاول إعادة الاتصال.", + "pad.modals.looping.explanation": "هناك مشاكل في الاتصال مع ملقم التزامن.", + "pad.modals.looping.cause": "ربما كنت متصلاً من خلال وكيل أو جدار حماية غير متوافق.", "pad.modals.initsocketfail": "لا يمكن الوصول إلى الخادم", "pad.modals.initsocketfail.explanation": "تعذر الاتصال بخادم المزامنة.", + "pad.modals.initsocketfail.cause": "وهذا على الأرجح بسبب مشكلة في المستعرض الخاص بك أو الاتصال بإنترنت.", "pad.modals.slowcommit.explanation": "الخادم لا يستجيب.", "pad.modals.slowcommit.cause": "يمكن أن يكون هذا بسبب مشاكل في الاتصال بالشبكة.", + "pad.modals.badChangeset.explanation": "لقد صنفت إحدى عمليات التحرير التي قمت بها كعملية غير مسموح بها من قبل ملقم التزامن.", + "pad.modals.badChangeset.cause": "يمكن أن يكون هذا بسبب تكوين ملقم خاطئ أو بسبب سلوك آخر غير متوقع. يرجى الاتصال بمسؤول الخدمة إذا كنت تعتقد بأن هناك خطأ ما. حاول إعادة الاتصال لمتابعة التحرير.", + "pad.modals.corruptPad.explanation": "الباد الذي تحاول الوصول إليه تالف.", + "pad.modals.corruptPad.cause": "قد يكون هذا بسبب تكوين ملقم خاطئ أو بسبب سلوك آخر غير متوقع. يرجى الاتصال بمسؤول الخدمة.", "pad.modals.deleted": "محذوف.", "pad.modals.deleted.explanation": "تمت إزالة هذا الباد", "pad.modals.disconnected": "لم تعد متّصل.", "pad.modals.disconnected.explanation": "تم فقدان الإتصال بالخادم", - "pad.modals.disconnected.cause": "قد يكون الخادم غير متوفر. الرجاء إعلامنا إذا تكرر هذا.", + "pad.modals.disconnected.cause": "قد يكون الخادم غير متوفر. يرجى إعلام مسؤول الخدمة إذا كان هذا لا يزال يحدث.", + "pad.share": "شارك هذه الباد", "pad.share.readonly": "للقراءة فقط", "pad.share.link": "رابط", "pad.share.emebdcode": "URL للتضمين", "pad.chat": "دردشة", "pad.chat.title": "فتح الدردشة لهذا الباد", "pad.chat.loadmessages": "تحميل المزيد من الرسائل", + "timeslider.pageTitle": "{{appTitle}} متصفح التاريخ", "timeslider.toolbar.returnbutton": "العودة إلى الباد", "timeslider.toolbar.authors": "المؤلفون:", "timeslider.toolbar.authorsList": "بدون مؤلفين", @@ -92,14 +104,20 @@ "timeslider.month.october": "أكتوبر", "timeslider.month.november": "نوفمبر", "timeslider.month.december": "ديسمبر", - "pad.userlist.entername": "إدخل اسمك", + "timeslider.unnamedauthors": "بدون اسم {{num}} {[plural(num) واحد: كاتب، آخر: مؤلف]}", + "pad.savedrevs.marked": "هذا التنقيح محدد الآن كمراجعة محفوظة", + "pad.userlist.entername": "أدخل اسمك", "pad.userlist.unnamed": "غير مسمى", "pad.userlist.guest": "ضيف", "pad.userlist.deny": "رفض", "pad.userlist.approve": "موافقة", + "pad.editbar.clearcolors": "مسح ألوان التأليف أو المستند بأكمله؟", "pad.impexp.importbutton": "الاستيراد الآن", "pad.impexp.importing": "الاستيراد...", + "pad.impexp.confirmimport": "استيراد ملف سيؤدي للكتابة فوق النص الحالي بالباد. هل أنت متأكد من أنك تريد المتابعة؟", + "pad.impexp.convertFailed": "لم نتمكن من استيراد هذا الملف. يرجى استخدام تنسيق مستند مختلف، أو النسخ واللصق يدوياً", "pad.impexp.uploadFailed": "فشل التحميل، الرجاء المحاولة مرة أخرى", "pad.impexp.importfailed": "فشل الاستيراد", - "pad.impexp.copypaste": "الرجاء نسخ/لصق" + "pad.impexp.copypaste": "الرجاء نسخ/لصق", + "pad.impexp.exportdisabled": "تصدير التنسيق {{type}} معطل. يرجى الاتصال بمسؤول النظام الخاص بك للحصول على التفاصيل." } diff --git a/src/locales/ast.json b/src/locales/ast.json index 45ee93911..8eda58c8f 100644 --- a/src/locales/ast.json +++ b/src/locales/ast.json @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Sólo se pue importar dende los formatos de testu planu o html. Pa carauterístiques d'importación más avanzaes instala abiword.", "pad.modals.connected": "Coneutáu.", "pad.modals.reconnecting": "Reconeutando col to bloc...", diff --git a/src/locales/az.json b/src/locales/az.json index f45043232..25a8ecc2f 100644 --- a/src/locales/az.json +++ b/src/locales/az.json @@ -51,7 +51,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Açıq Sənəd Formatı)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Siz yalnız adi mətndən və ya HTML-dən idxal edə bilərsiniz. İdxalın daha mürəkkəb funksiyaları üçün, zəhmət olmasa, AbiWord-i quraşdırın.", "pad.modals.connected": "Bağlandı.", "pad.modals.reconnecting": "Sizin pad yenidən qoşulur..", diff --git a/src/locales/azb.json b/src/locales/azb.json index b3b76f805..799c5b6b3 100644 --- a/src/locales/azb.json +++ b/src/locales/azb.json @@ -2,7 +2,8 @@ "@metadata": { "authors": [ "Amir a57", - "Mousa" + "Mousa", + "Koroğlu" ] }, "index.newPad": "یئنی یادداشت دفترچه سی", @@ -45,7 +46,6 @@ "pad.importExport.exportword": "مایکروسافت وورد", "pad.importExport.exportpdf": "پی دی اف", "pad.importExport.exportopen": "او دی اف", - "pad.importExport.exportdokuwiki": "دوکو ویکی", "pad.modals.connected": "متصل اولدی", "pad.modals.reconnecting": "سیزین یادداشت دفترچه سینه یئنی دن متصیل اولدی", "pad.modals.forcereconnect": "یئنی اتصال اوچون زورلاما", @@ -68,5 +68,21 @@ "timeslider.pageTitle": "{{appTitle}}زمان اسلایدری", "timeslider.toolbar.returnbutton": "یادداشت دفترچه سینه قاییت", "timeslider.toolbar.authors": "یازیچیلار", - "timeslider.toolbar.authorsList": "یازیچی سیز" + "timeslider.toolbar.authorsList": "یازیچی سیز", + "timeslider.month.january": "ژانویه", + "timeslider.month.february": "فوریه", + "timeslider.month.march": "مارس", + "timeslider.month.april": "آپریل", + "timeslider.month.may": "مای", + "timeslider.month.june": "ژوئن", + "timeslider.month.july": "جولای", + "timeslider.month.august": "آقوست", + "timeslider.month.september": "سپتامبر", + "timeslider.month.october": "اوْکتوبر", + "timeslider.month.november": "نوْوامبر", + "timeslider.month.december": "دسامبر", + "pad.userlist.unnamed": "آدسیز", + "pad.userlist.guest": "قوْناق", + "pad.userlist.deny": "دانماق", + "pad.userlist.approve": "اوْنایلا" } diff --git a/src/locales/bcc.json b/src/locales/bcc.json new file mode 100644 index 000000000..7ae420053 --- /dev/null +++ b/src/locales/bcc.json @@ -0,0 +1,121 @@ +{ + "@metadata": { + "authors": [ + "Baloch Afghanistan" + ] + }, + "index.newPad": "دفترچه یادداشت تازه", + "index.createOpenPad": "یا ایجاد/بازکردن یک دفترچه یادداشت با نام:", + "pad.toolbar.bold.title": "پررنگ (Ctrl-B)", + "pad.toolbar.italic.title": "کج (Ctrl-I)", + "pad.toolbar.underline.title": "زیرخط (Ctrl-U)", + "pad.toolbar.strikethrough.title": "خط خورده", + "pad.toolbar.ol.title": "فهرست مرتب شده", + "pad.toolbar.ul.title": "فهرست مرتب نشده", + "pad.toolbar.indent.title": "تورفتگی (TAB)", + "pad.toolbar.unindent.title": "بیرون رفتگی (Shift+TAB)", + "pad.toolbar.undo.title": "باطل‌کردن (Ctrl-Z)", + "pad.toolbar.redo.title": "از نو (Ctrl-Y)", + "pad.toolbar.clearAuthorship.title": "پاک‌کردن رنگ‌های نویسندگی", + "pad.toolbar.import_export.title": "درون‌ریزی/برون‌ریزی از/به قالب‌های مختلف", + "pad.toolbar.timeslider.title": "لغزندهٔ زمان", + "pad.toolbar.savedRevision.title": "ذخیره‌سازی نسخه", + "pad.toolbar.settings.title": "تنظیمات", + "pad.toolbar.embed.title": "اشتراک و جاسازی این دفترچه یادداشت", + "pad.toolbar.showusers.title": "نمایش کاربران در این دفترچه یادداشت", + "pad.colorpicker.save": "زاپاس کورتین", + "pad.colorpicker.cancel": "کنسیل", + "pad.loading": "...بار بیت", + "pad.passwordRequired": "برای دسترسی به این دفترچه یادداشت نیاز به یک گذرواژه دارید", + "pad.permissionDenied": "شرمنده، شما را اجازت په دسترسی ای صفحه نیست.", + "pad.wrongPassword": "گذرواژه‌ی شما درست نیست", + "pad.settings.padSettings": "تنظیمات دفترچه یادداشت", + "pad.settings.myView": "نمای من", + "pad.settings.stickychat": "گفتگو همیشه روی صفحه نمایش باشد", + "pad.settings.colorcheck": "رنگ‌های نویسندگی", + "pad.settings.linenocheck": "شماره‌ی خطوط", + "pad.settings.rtlcheck": "خواندن محتوا از راست به چپ؟", + "pad.settings.fontType": "نوع قلم:", + "pad.settings.fontType.normal": "نرمال", + "pad.settings.fontType.monospaced": "Monospace", + "pad.settings.globalView": "نمای سراسری", + "pad.settings.language": "زبان:", + "pad.importExport.import_export": "درون‌ریزی/برون‌ریزی", + "pad.importExport.import": "بارگذاری پرونده‌ی متنی یا سند", + "pad.importExport.importSuccessful": "موفقیت آمیز بود!", + "pad.importExport.export": "برون‌ریزی این دفترچه یادداشت با قالب:", + "pad.importExport.exporthtml": "HTML", + "pad.importExport.exportplain": "سادگین متن", + "pad.importExport.exportword": "Microsoft Word", + "pad.importExport.exportpdf": "PDF", + "pad.importExport.exportopen": "ODF (قالب سند باز)", + "pad.importExport.abiword.innerHTML": "شما تنها می‌توانید از قالب متن ساده یا اچ‌تی‌ام‌ال درون‌ریزی کنید. برای بیشتر شدن ویژگی‌های درون‌ریزی پیشرفته AbiWord را نصب کنید.", + "pad.modals.connected": "متصل شد.", + "pad.modals.reconnecting": "در حال اتصال دوباره به دفترچه یادداشت شما..", + "pad.modals.forcereconnect": "واداشتن به اتصال دوباره", + "pad.modals.userdup": "در پنجره‌ای دیگر باز شد", + "pad.modals.userdup.explanation": "گمان می‌رود این دفترچه یادداشت در بیش از یک پنجره‌ی مرورگر باز شده‌است.", + "pad.modals.userdup.advice": "برای استفاده از این پنجره دوباره وصل شوید.", + "pad.modals.unauth": "مجاز نیست", + "pad.modals.unauth.explanation": "دسترسی شما در حین مشاهده‌ی این برگه تغییر یافته‌است. دوباره متصل شوید.", + "pad.modals.looping.explanation": "مشکلاتی ارتباطی با سرور همگام‌سازی وجود دارد.", + "pad.modals.looping.cause": "شاید شما از طریق یک فایروال یا پروکسی ناسازگار متصل شده‌اید.", + "pad.modals.initsocketfail": "سرور در دسترس نیست.", + "pad.modals.initsocketfail.explanation": "نمی‌توان به سرور همگام سازی وصل شد.", + "pad.modals.initsocketfail.cause": "شاید این به خاطر مشکلی در مرورگر یا اتصال اینترنتی شما باشد.", + "pad.modals.slowcommit.explanation": "سرور پاسخ نمی‌دهد.", + "pad.modals.slowcommit.cause": "این می‌تواند به خاطر مشکلاتی در اتصال به شبکه باشد.", + "pad.modals.badChangeset.explanation": "ویرایشی که شما انجام داده‌اید توسط سرور همگام‌سازی نادرست طیقه‌بندی شده‌است.", + "pad.modals.badChangeset.cause": "این می‌تواند به دلیل پیکربندی اشتباه یا سایر رفتارهای غیرمنتظره باشد. اگر فکر می‌کنید این یک خطا است لطفاً با مدیر خدمت تماس بگیرید. برای ادامهٔ ویرایش سعی کنید که دوباره متصل شوید.", + "pad.modals.corruptPad.explanation": "پدی که شما سعی دارید دسترسی پیدا کنید خراب است.", + "pad.modals.corruptPad.cause": "این احتمالاً به دلیل تنظیمات اشتباه کارساز یا سایر رفتارهای غیرمنتظره است. لطفاً با مدیر خدمت تماس حاصل کنید.", + "pad.modals.deleted": "پاک کورتین", + "pad.modals.deleted.explanation": "این دفترچه یادداشت پاک شده‌است.", + "pad.modals.disconnected": "اتصال شما قطع شده‌است.", + "pad.modals.disconnected.explanation": "اتصال به سرور قطع شده‌است.", + "pad.modals.disconnected.cause": "ممکن است سرور در دسترس نباشد. اگر این مشکل باز هم رخ داد مدیر حدمت را آگاه کنید.", + "pad.share": "به اشتراک‌گذاری این دفترچه یادداشت", + "pad.share.readonly": "فقط خواندنی", + "pad.share.link": "پیوند", + "pad.share.emebdcode": "جاسازی نشانی", + "pad.chat": "گفتگو", + "pad.chat.title": "بازکردن گفتگو برای این دفترچه یادداشت", + "pad.chat.loadmessages": "بارگیری پیام‌های بیشتر", + "timeslider.pageTitle": "لغزندهٔ زمان {{appTitle}}", + "timeslider.toolbar.returnbutton": "بازگشت به دفترچه یادداشت", + "timeslider.toolbar.authors": "نویسوک:", + "timeslider.toolbar.authorsList": "بدون نویسنده", + "timeslider.toolbar.exportlink.title": "درگیزگ", + "timeslider.exportCurrent": "برون‌ریزی نگارش کنونی به عنوان:", + "timeslider.version": "نگارش {{version}}", + "timeslider.saved": "{{month}} {{day}}، {{year}} ذخیره شد", + "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", + "timeslider.month.january": "جنوری", + "timeslider.month.february": "پیبروری", + "timeslider.month.march": "مارچ", + "timeslider.month.april": "آپریل", + "timeslider.month.may": "می", + "timeslider.month.june": "جون", + "timeslider.month.july": "جولای", + "timeslider.month.august": "آگوست", + "timeslider.month.september": "سپٹامبر", + "timeslider.month.october": "اکتوبر", + "timeslider.month.november": "نوامبر", + "timeslider.month.december": "دسمبر", + "timeslider.unnamedauthors": "{{num}} نویسندهٔ بی‌نام", + "pad.savedrevs.marked": "این بازنویسی هم اکنون به عنوان ذخیره شده علامت‌گذاری شد", + "pad.userlist.entername": "وتی یوزرنامء بلک ات", + "pad.userlist.unnamed": "بدون نام", + "pad.userlist.guest": "مهمان", + "pad.userlist.deny": "رد کردن", + "pad.userlist.approve": "تایید", + "pad.editbar.clearcolors": "رنگ نویسندگی از همه‌ی سند پاک شود؟", + "pad.impexp.importbutton": "هم اکنون درون‌ریزی کن", + "pad.impexp.importing": "در حال درون‌ریزی...", + "pad.impexp.confirmimport": "با درون‌ریزی یک پرونده نوشتهٔ کنونی دفترچه پاک می‌شود. آیا می‌خواهید ادامه دهید؟", + "pad.impexp.convertFailed": "ما نمی‌توانیم این پرونده را درون‌ریزی کنیم. خواهشمندیم قالب دیگری برای سندتان انتخاب کرده یا بصورت دستی آنرا کپی کنید", + "pad.impexp.uploadFailed": "آپلود انجام نشد، دوباره تلاش کنید", + "pad.impexp.importfailed": "درون‌ریزی انجام نشد", + "pad.impexp.copypaste": "کپی پیست کنید", + "pad.impexp.exportdisabled": "برون‌ریزی با قالب {{type}} از کار افتاده است. برای جزئیات بیشتر با مدیر سیستمتان تماس بگیرید." +} diff --git a/src/locales/be-tarask.json b/src/locales/be-tarask.json index ae29c3968..61a785399 100644 --- a/src/locales/be-tarask.json +++ b/src/locales/be-tarask.json @@ -11,14 +11,14 @@ "pad.toolbar.bold.title": "Тоўсты (Ctrl-B)", "pad.toolbar.italic.title": "Курсіў (Ctrl-I)", "pad.toolbar.underline.title": "Падкрэсьліваньне (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Закрэсьліваньне", - "pad.toolbar.ol.title": "Упарадкаваны сьпіс", - "pad.toolbar.ul.title": "Неўпарадкаваны сьпіс", + "pad.toolbar.strikethrough.title": "Закрэсьліваньне (Ctrl+5)", + "pad.toolbar.ol.title": "Упарадкаваны сьпіс (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Неўпарадкаваны сьпіс (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Водступ (TAB)", "pad.toolbar.unindent.title": "Выступ (Shift+TAB)", "pad.toolbar.undo.title": "Скасаваць(Ctrl-Z)", "pad.toolbar.redo.title": "Вярнуць (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Прыбраць колер дакумэнту", + "pad.toolbar.clearAuthorship.title": "Прыбраць колер дакумэнту (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Імпарт/Экспарт з выкарыстаньне розных фарматаў файлаў", "pad.toolbar.timeslider.title": "Шкала часу", "pad.toolbar.savedRevision.title": "Захаваць вэрсію", @@ -51,7 +51,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Вы можаце імпартаваць толькі з звычайнага тэксту або HTML. Дзеля больш пашыраных магчымасьцяў імпарту, калі ласка, усталюйце abiword.", "pad.modals.connected": "Падлучыліся.", "pad.modals.reconnecting": "Перападлучэньне да вашага дакумэнта...", diff --git a/src/locales/bn.json b/src/locales/bn.json index 6c3d6cfc3..10a804b4f 100644 --- a/src/locales/bn.json +++ b/src/locales/bn.json @@ -4,7 +4,8 @@ "Bellayet", "Nasir8891", "Sankarshan", - "Aftab1995" + "Aftab1995", + "Aftabuzzaman" ] }, "index.newPad": "নতুন প্যাড", @@ -18,7 +19,7 @@ "pad.toolbar.unindent.title": "আউটডেন্ট (Shift+TAB)", "pad.toolbar.undo.title": "বাতিল করুন (Ctrl-Z)", "pad.toolbar.redo.title": "পুনরায় করুন (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "কৃতি রং পরিষ্কার করুন", + "pad.toolbar.clearAuthorship.title": "কৃতি রং পরিষ্কার করুন (Ctrl+Shift+C)", "pad.toolbar.timeslider.title": "টাইমস্লাইডার", "pad.toolbar.savedRevision.title": "সংস্করণ সংরক্ষণ করুন", "pad.toolbar.settings.title": "সেটিং", @@ -49,7 +50,6 @@ "pad.importExport.exportword": "মাইক্রোসফট ওয়ার্ড", "pad.importExport.exportpdf": "পিডিএফ", "pad.importExport.exportopen": "ওডিএফ (ওপেন ডকুমেন্ট ফরম্যাট)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.modals.connected": "যোগাযোগ সফল", "pad.modals.reconnecting": "আপনার প্যাডের সাথে সংযোগস্থাপন করা হচ্ছে..", "pad.modals.forcereconnect": "পুনরায় সংযোগস্থাপনের চেষ্টা", diff --git a/src/locales/br.json b/src/locales/br.json index e22802c10..6e455d232 100644 --- a/src/locales/br.json +++ b/src/locales/br.json @@ -12,14 +12,14 @@ "pad.toolbar.bold.title": "Tev (Ctrl-B)", "pad.toolbar.italic.title": "Italek (Ctrl-I)", "pad.toolbar.underline.title": "Islinennañ (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Barrennet", - "pad.toolbar.ol.title": "Roll urzhiet", - "pad.toolbar.ul.title": "Roll en dizurzh", + "pad.toolbar.strikethrough.title": "Barrennet(Ktrl+5)", + "pad.toolbar.ol.title": "Listenn urzhiet (Ktrl+Pennlizherenn+N)", + "pad.toolbar.ul.title": "Listenn en dizurzh (Ktrl+Pennlizherenn+L)", "pad.toolbar.indent.title": "Endantañ (TAB)", "pad.toolbar.unindent.title": "Diendantañ (Shift+TAB)", "pad.toolbar.undo.title": "Dizober (Ktrl-Z)", "pad.toolbar.redo.title": "Adober (Ktrl-Y)", - "pad.toolbar.clearAuthorship.title": "Diverkañ al livioù oc'h anaout an aozerien", + "pad.toolbar.clearAuthorship.title": "Diverkañ al livioù oc'h anaout an aozerien (Ktrl+Pennlizherenn+C)", "pad.toolbar.import_export.title": "Enporzhiañ/Ezporzhiañ eus/war-zu ur furmad restr disheñvel", "pad.toolbar.timeslider.title": "Istor dinamek", "pad.toolbar.savedRevision.title": "Doareoù enrollet", @@ -52,7 +52,6 @@ "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ñ furmadoù testennoù kriz pe html. Evit arc'hwelioù enporzhiañ emdroetoc'h, staliit abiword mar plij.", "pad.modals.connected": "Kevreet.", "pad.modals.reconnecting": "Adkevreañ war-zu ho pad...", diff --git a/src/locales/ca.json b/src/locales/ca.json index f6870db82..92da9d029 100644 --- a/src/locales/ca.json +++ b/src/locales/ca.json @@ -4,7 +4,8 @@ "Alvaro Vidal-Abarca", "Pginer", "Pitort", - "Toniher" + "Toniher", + "Macofe" ] }, "index.newPad": "Nou pad", @@ -19,7 +20,7 @@ "pad.toolbar.unindent.title": "Sagnat invers (Majúsc+TAB)", "pad.toolbar.undo.title": "Desfés (Ctrl-Z)", "pad.toolbar.redo.title": "Refés (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Neteja els colors d'autoria", + "pad.toolbar.clearAuthorship.title": "Neteja els colors d'autoria (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importa/exporta a partir de diferents formats de fitxer", "pad.toolbar.timeslider.title": "Línia temporal", "pad.toolbar.savedRevision.title": "Desa la revisió", @@ -52,7 +53,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Només podeu importar de text net o html. Per a opcions d'importació més avançades instal·leu l'Abiword.", "pad.modals.connected": "Connectat.", "pad.modals.reconnecting": "S'està tornant a connectar al vostre pad…", diff --git a/src/locales/cs.json b/src/locales/cs.json index 62a2302c5..1c1357c44 100644 --- a/src/locales/cs.json +++ b/src/locales/cs.json @@ -53,7 +53,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Importovat můžeš pouze prostý text nebo HTML formátování. Pro pokročilejší funkce importu, prosím, nainstaluj „abiword“.", "pad.modals.connected": "Připojeno.", "pad.modals.reconnecting": "Znovupřipojování k Padu…", diff --git a/src/locales/da.json b/src/locales/da.json index a6a07d149..662e9afbd 100644 --- a/src/locales/da.json +++ b/src/locales/da.json @@ -11,14 +11,14 @@ "pad.toolbar.bold.title": "Fed (Ctrl-B)", "pad.toolbar.italic.title": "Kursiv (Ctrl-I)", "pad.toolbar.underline.title": "Understregning (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Gennemstregning", - "pad.toolbar.ol.title": "Sorteret liste", - "pad.toolbar.ul.title": "Usorteret liste", + "pad.toolbar.strikethrough.title": "Gennemstregning (Ctrl+5)", + "pad.toolbar.ol.title": "Sorteret liste (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Usorteret liste (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Indrykning (TAB)", "pad.toolbar.unindent.title": "Ryk ud (Shift+TAB)", "pad.toolbar.undo.title": "Fortryd (Ctrl-Z)", "pad.toolbar.redo.title": "Annuller Fortryd (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Fjern farver for forfatterskab", + "pad.toolbar.clearAuthorship.title": "Fjern farver for forfatterskab (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Import/eksport fra/til forskellige filformater", "pad.toolbar.timeslider.title": "Timeslider", "pad.toolbar.savedRevision.title": "Gem Revision", @@ -51,7 +51,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Du kan kun importere fra almindelig tekst eller HTML-formater. For mere avancerede importfunktioner, installer venligst abiword.", "pad.modals.connected": "Forbundet.", "pad.modals.reconnecting": "Genopretter forbindelsen til din pad...", diff --git a/src/locales/de.json b/src/locales/de.json index 05a9af799..f05d43c3e 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -12,14 +12,14 @@ "pad.toolbar.bold.title": "Fett (Strg-B)", "pad.toolbar.italic.title": "Kursiv (Strg-I)", "pad.toolbar.underline.title": "Unterstrichen (Strg-U)", - "pad.toolbar.strikethrough.title": "Durchgestrichen", - "pad.toolbar.ol.title": "Nummerierte Liste", - "pad.toolbar.ul.title": "Ungeordnete Liste", + "pad.toolbar.strikethrough.title": "Durchgestrichen (Strg+5)", + "pad.toolbar.ol.title": "Nummerierte Liste (Strg+Shift+N)", + "pad.toolbar.ul.title": "Ungeordnete Liste (Strg+Shift+L)", "pad.toolbar.indent.title": "Einrücken (TAB)", "pad.toolbar.unindent.title": "Ausrücken (Shift+TAB)", "pad.toolbar.undo.title": "Rückgängig (Strg-Z)", "pad.toolbar.redo.title": "Wiederholen (Strg-Y)", - "pad.toolbar.clearAuthorship.title": "Autorenfarben zurücksetzen", + "pad.toolbar.clearAuthorship.title": "Autorenfarben zurücksetzen (Strg+Shift+C)", "pad.toolbar.import_export.title": "Import/Export von/zu verschiedenen Dateiformaten", "pad.toolbar.timeslider.title": "Pad-Versionsgeschichte anzeigen", "pad.toolbar.savedRevision.title": "Version markieren", @@ -52,7 +52,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Sie können nur aus Klartext oder HTML-Formaten importieren. Für mehr erweiterte Importfunktionen installieren Sie bitte abiword.", "pad.modals.connected": "Verbunden.", "pad.modals.reconnecting": "Wiederherstellen der Verbindung …", diff --git a/src/locales/diq.json b/src/locales/diq.json index a98b3c145..61d401696 100644 --- a/src/locales/diq.json +++ b/src/locales/diq.json @@ -10,14 +10,14 @@ "pad.toolbar.bold.title": "Qalın (Ctrl-B)", "pad.toolbar.italic.title": "Namıte (Ctrl-I)", "pad.toolbar.underline.title": "Bınxetın (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Serxetın", - "pad.toolbar.ol.title": "Lista rêzkerdiye", - "pad.toolbar.ul.title": "Lista rêznêkerdiye", + "pad.toolbar.strikethrough.title": "Serxetın (Ctrl+5)", + "pad.toolbar.ol.title": "Lista rêzkerdiye (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Lista rêznêkerdiye (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Serrêze (TAB)", "pad.toolbar.unindent.title": "Teberdayış (Shift+TAB)", "pad.toolbar.undo.title": "Meke (Ctrl-Z)", "pad.toolbar.redo.title": "Fına bıke (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Rengê Nuştoğiê Arıstey", + "pad.toolbar.clearAuthorship.title": "Rengê Nuştoğiê Arıstey (Ctrl+Shift+C)", "pad.toolbar.timeslider.title": "Ğızagê zemani", "pad.toolbar.savedRevision.title": "Çımraviyarnayışi qeyd ke", "pad.toolbar.settings.title": "Sazkerdışi", @@ -43,7 +43,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.modals.connected": "Gırediya.", "pad.modals.forcereconnect": "Mecbur anciya gırê de", "pad.modals.userdup": "Zewbina pençere de bi a", @@ -80,7 +79,7 @@ "timeslider.month.november": "Tışrino Peyên", "timeslider.month.december": "Kanun", "timeslider.unnamedauthors": "{{num}} unnamed {[plural(num) zu: nuştoğ, zewbi: nustoği ]}", - "pad.userlist.entername": "Namey ğo cı kewe", + "pad.userlist.entername": "Nameyê xo cıkewe", "pad.userlist.unnamed": "Name nébıyo", "pad.userlist.guest": "Meyman", "pad.userlist.deny": "Red ke", diff --git a/src/locales/dsb.json b/src/locales/dsb.json index a24536d49..0600be900 100644 --- a/src/locales/dsb.json +++ b/src/locales/dsb.json @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Móžoš jano z fprmatow lutnego teksta abo z HTML-formata importěrowaś. Za wěcej rozšyrjone importěrowańske funkcije instalěruj pšosym Abiword.", "pad.modals.connected": "Zwězany.", "pad.modals.reconnecting": "Zwězujo se znowego z twójim zapisnikom...", diff --git a/src/locales/el.json b/src/locales/el.json index 0c334c1ca..f20e1e87e 100644 --- a/src/locales/el.json +++ b/src/locales/el.json @@ -13,14 +13,14 @@ "pad.toolbar.bold.title": "Έντονη (Ctrl-B)", "pad.toolbar.italic.title": "Πλάγια (Ctrl-I)", "pad.toolbar.underline.title": "Υπογράμμιση (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Διακριτή διαγραφή", - "pad.toolbar.ol.title": "Ταξινομημένη λίστα", - "pad.toolbar.ul.title": "Λίστα χωρίς σειρά", + "pad.toolbar.strikethrough.title": "Διακριτή διαγραφή (Ctrl+5)", + "pad.toolbar.ol.title": "Ταξινομημένη λίστα (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Λίστα χωρίς σειρά (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Αριστερά εσοχή (TAB)", "pad.toolbar.unindent.title": "Δεξιά εσοχή (Shift+TAB)", "pad.toolbar.undo.title": "Αναίρεση (Ctrl-Z)", "pad.toolbar.redo.title": "Επανάληψη (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Εκκαθάριση των χρωμάτων των συντακτών", + "pad.toolbar.clearAuthorship.title": "Εκκαθάριση των χρωμάτων των συντακτών (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Εισαγωγή/Εξαγωγή από/σε διαφορετικούς τύπους αρχείων", "pad.toolbar.timeslider.title": "Χρονοδιάγραμμα", "pad.toolbar.savedRevision.title": "Αποθήκευση Αναθεώρησης", @@ -53,14 +53,13 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Μορφή Open Document)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Μπορείτε να κάνετε εισαγωγή απλού κειμένου ή μορφής html. Για πιο προηγμένες δυνατότητες εισαγωγής παρακαλώ εγκαταστήστε το abiword.", "pad.modals.connected": "Συνδεμένοι.", "pad.modals.reconnecting": "Επανασύνδεση στο pad σας...", "pad.modals.forcereconnect": "Επιβολή επανασύνδεσης", "pad.modals.userdup": "Ανοιγμένο σε άλλο παράθυρο", "pad.modals.userdup.explanation": "Αυτό το pad φαίνεται να είναι ανοιχτό σε περισσότερα από ένα παράθυρο του προγράμματος περιήγησης σε αυτόν τον υπολογιστή.", - "pad.modals.userdup.advice": "Επανασύνδεση για να χρησιμοποιήσετε αυτό το παράθυρο.", + "pad.modals.userdup.advice": "Επανασυνδεθείτε για να χρησιμοποιήσετε αυτό το παράθυρο.", "pad.modals.unauth": "Δεν επιτρέπεται", "pad.modals.unauth.explanation": "Τα δικαιώματά σας άλλαξαν όσο βλέπατε αυτήν τη σελίδα. Δοκιμάστε να επανασυνδεθείτε.", "pad.modals.looping.explanation": "Υπάρχουν προβλήματα επικοινωνίας με τον διακομιστή συγχρονισμού.", @@ -76,7 +75,7 @@ "pad.modals.corruptPad.cause": "Αυτό μπορεί να οφείλεται σε ένα λάθος στη ρύθμιση του διακομιστή ή κάποια άλλη απρόβλεπτη συμπεριφορά. Παρακαλώ επικοινωνήστε με τον διαχειριστή της υπηρεσίας.", "pad.modals.deleted": "Διεγράφη.", "pad.modals.deleted.explanation": "Αυτό το pad έχει καταργηθεί.", - "pad.modals.disconnected": "Έχετε αποσυνδεθεί.", + "pad.modals.disconnected": "Είστε αποσυνδεδεμένοι.", "pad.modals.disconnected.explanation": "Χάθηκε η σύνδεση με τον διακομιστή", "pad.modals.disconnected.cause": "Ο διακομιστής μπορεί να μην είναι διαθέσιμος. Παρακαλούμε ειδοποιήστε τον διαχειριστή της υπηρεσίας εάν εξακολουθεί να συμβαίνει αυτό.", "pad.share": "Μοιραστείτε αυτό το pad", diff --git a/src/locales/en.json b/src/locales/en.json index 01d3ff4ff..7f5846fd2 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -2,17 +2,17 @@ "index.newPad": "New Pad", "index.createOpenPad": "or create/open a Pad with the name:", - "pad.toolbar.bold.title": "Bold (Ctrl-B)", - "pad.toolbar.italic.title": "Italic (Ctrl-I)", - "pad.toolbar.underline.title": "Underline (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Strikethrough", - "pad.toolbar.ol.title": "Ordered list", - "pad.toolbar.ul.title": "Unordered List", + "pad.toolbar.bold.title": "Bold (Ctrl+B)", + "pad.toolbar.italic.title": "Italic (Ctrl+I)", + "pad.toolbar.underline.title": "Underline (Ctrl+U)", + "pad.toolbar.strikethrough.title": "Strikethrough (Ctrl+5)", + "pad.toolbar.ol.title": "Ordered list (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Unordered List (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Indent (TAB)", "pad.toolbar.unindent.title": "Outdent (Shift+TAB)", - "pad.toolbar.undo.title": "Undo (Ctrl-Z)", - "pad.toolbar.redo.title": "Redo (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Clear Authorship Colors", + "pad.toolbar.undo.title": "Undo (Ctrl+Z)", + "pad.toolbar.redo.title": "Redo (Ctrl+Y)", + "pad.toolbar.clearAuthorship.title": "Clear Authorship Colors (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Import/Export from/to different file formats", "pad.toolbar.timeslider.title": "Timeslider", "pad.toolbar.savedRevision.title": "Save Revision", @@ -24,6 +24,7 @@ "pad.colorpicker.cancel": "Cancel", "pad.loading": "Loading...", + "pad.noCookie": "Cookie could not be found. Please allow cookies in your browser!", "pad.passwordRequired": "You need a password to access this pad", "pad.permissionDenied": "You do not have permission to access this pad", "pad.wrongPassword": "Your password was wrong", @@ -44,12 +45,12 @@ "pad.importExport.import": "Upload any text file or document", "pad.importExport.importSuccessful": "Successful!", "pad.importExport.export": "Export current pad as:", + "pad.importExport.exportetherpad": "Etherpad", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportplain": "Plain text", "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "You only can import from plain text or HTML formats. For more advanced import features please install abiword.", "pad.modals.connected": "Connected.", @@ -85,7 +86,7 @@ "pad.modals.disconnected": "You have been disconnected.", "pad.modals.disconnected.explanation": "The connection to the server was lost", "pad.modals.disconnected.cause": "The server may be unavailable. Please notify the service administrator if this continues to happen.", - + "pad.share": "Share this pad", "pad.share.readonly": "Read only", "pad.share.link": "Link", @@ -130,6 +131,7 @@ "pad.impexp.importing": "Importing...", "pad.impexp.confirmimport": "Importing a file will overwrite the current text of the pad. Are you sure you want to proceed?", "pad.impexp.convertFailed": "We were not able to import this file. Please use a different document format or copy paste manually", + "pad.impexp.padHasData": "We were not able to import this file because this Pad has already had changes, please import to a new pad", "pad.impexp.uploadFailed": "The upload failed, please try again", "pad.impexp.importfailed": "Import failed", "pad.impexp.copypaste": "Please copy paste", diff --git a/src/locales/es.json b/src/locales/es.json index 831b89c12..df9a415ec 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -9,22 +9,23 @@ "Rubenwap", "VegaDark", "Vivaelcelta", - "Xuacu" + "Xuacu", + "Macofe" ] }, - "index.newPad": "Nuevo Pad", - "index.createOpenPad": "o crea/abre un Pad con el nombre:", + "index.newPad": "Nuevo pad", + "index.createOpenPad": "o crea/abre un pad con el nombre:", "pad.toolbar.bold.title": "Negrita (Ctrl-B)", "pad.toolbar.italic.title": "Cursiva (Ctrl-I)", "pad.toolbar.underline.title": "Subrayado (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Tachado", - "pad.toolbar.ol.title": "Lista ordenada", - "pad.toolbar.ul.title": "Lista desordenada", + "pad.toolbar.strikethrough.title": "Tachado (Ctrl+5)", + "pad.toolbar.ol.title": "Lista ordenada (Ctrl+Mayús+N)", + "pad.toolbar.ul.title": "Lista desordenada (Ctrl+Mayús+L)", "pad.toolbar.indent.title": "Sangría (TAB)", "pad.toolbar.unindent.title": "Eliminar sangría (Shift+TAB)", "pad.toolbar.undo.title": "Deshacer (Ctrl-Z)", "pad.toolbar.redo.title": "Rehacer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Eliminar los colores de los autores", + "pad.toolbar.clearAuthorship.title": "Eliminar los colores de autoría (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importar/Exportar a diferentes formatos de archivos", "pad.toolbar.timeslider.title": "Línea de tiempo", "pad.toolbar.savedRevision.title": "Guardar revisión", @@ -34,13 +35,13 @@ "pad.colorpicker.save": "Guardar", "pad.colorpicker.cancel": "Cancelar", "pad.loading": "Cargando...", - "pad.passwordRequired": "Necesitas una contraseña para acceder a este documento", - "pad.permissionDenied": "No tienes permiso para acceder a esta página", + "pad.passwordRequired": "Necesitas una contraseña para acceder a este pad", + "pad.permissionDenied": "No tienes permiso para acceder a este pad", "pad.wrongPassword": "La contraseña era incorrecta", - "pad.settings.padSettings": "Configuración del Pad", + "pad.settings.padSettings": "Configuración del pad", "pad.settings.myView": "Preferencias personales", - "pad.settings.stickychat": "Chat siempre encima", - "pad.settings.colorcheck": "Color de autoría", + "pad.settings.stickychat": "Chat siempre en pantalla", + "pad.settings.colorcheck": "Colores de autoría", "pad.settings.linenocheck": "Números de línea", "pad.settings.rtlcheck": "¿Leer contenido de derecha a izquierda?", "pad.settings.fontType": "Tipografía:", @@ -50,40 +51,39 @@ "pad.settings.language": "Idioma:", "pad.importExport.import_export": "Importar/Exportar", "pad.importExport.import": "Subir cualquier texto o documento", - "pad.importExport.importSuccessful": "¡Operación realizada con éxito!", + "pad.importExport.importSuccessful": "¡Éxito!", "pad.importExport.export": "Exporta el pad actual como:", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportplain": "Texto plano", "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", - "pad.importExport.abiword.innerHTML": "Sólo puede importar formatos de texto plano o html. Para funciones más avanzadas instale abiword.", + "pad.importExport.abiword.innerHTML": "Sólo puedes importar formatos de texto plano o html. Para funciones más avanzadas instala abiword.", "pad.modals.connected": "Conectado.", "pad.modals.reconnecting": "Reconectando a tu pad..", - "pad.modals.forcereconnect": "Reconexión forzosa", + "pad.modals.forcereconnect": "Forzar reconexión", "pad.modals.userdup": "Abierto en otra ventana", "pad.modals.userdup.explanation": "Este pad parece estar abierto en más de una ventana de tu navegador.", "pad.modals.userdup.advice": "Reconectar para usar esta ventana.", "pad.modals.unauth": "No autorizado.", - "pad.modals.unauth.explanation": "Los permisos han cambiado mientras estabas viendo esta página. Intenta reconectar de nuevo.", - "pad.modals.looping.explanation": "Estamos teniendo problemas con la sincronización en el servidor.", + "pad.modals.unauth.explanation": "Tus permisos han cambiado mientras estabas viendo esta página. Intenta reconectarte.", + "pad.modals.looping.explanation": "Hay problemas con el servidor de sincronización.", "pad.modals.looping.cause": "Puede deberse a que te conectes a través de un proxy o un cortafuegos incompatible.", "pad.modals.initsocketfail": "Servidor incalcanzable.", "pad.modals.initsocketfail.explanation": "No se pudo conectar al servidor de sincronización.", - "pad.modals.initsocketfail.cause": "Puede ser a causa de tu navegador o de una caída en tu conexión de Internet.", + "pad.modals.initsocketfail.cause": "Probablemente debido a un problema en tu navegador o en tu conexión a internet.", "pad.modals.slowcommit.explanation": "El servidor no responde.", "pad.modals.slowcommit.cause": "Puede deberse a problemas con tu conexión de red.", - "pad.modals.badChangeset.explanation": "Ha hecho una edición clasificada como ilegal por el servidor de sincronización.", - "pad.modals.badChangeset.cause": "Esto podría ser debido a una mala configuración del servidor o algún otro comportamiento inesperado. Póngase en contacto con el administrador del servicio, si siente que esto es un error. Intente volver a conectar con el fin de seguir editando.", - "pad.modals.corruptPad.explanation": "El pad que está intentando acceder está dañado.", - "pad.modals.corruptPad.cause": "Esto puede deberse a una mala configuración de servidor o algún otro comportamiento inesperado. Póngase en contacto con el administrador del servicio.", + "pad.modals.badChangeset.explanation": "Has hecho una edición clasificada como ilegal por el servidor de sincronización.", + "pad.modals.badChangeset.cause": "Esto podría deberse a una mala configuración del servidor o algún otro comportamiento inesperado. Contacta al administrador del servicio, si piensas que esto es un error. Intenta reconectarte con el fin de seguir editando.", + "pad.modals.corruptPad.explanation": "El pad que intentas acceder está dañado.", + "pad.modals.corruptPad.cause": "Esto puede deberse a una mala configuración del servidor o algún otro comportamiento inesperado. Contacta al administrador del servicio.", "pad.modals.deleted": "Borrado.", "pad.modals.deleted.explanation": "Este pad ha sido borrado.", - "pad.modals.disconnected": "Has sido desconectado.", + "pad.modals.disconnected": "Te has desconectado.", "pad.modals.disconnected.explanation": "Se perdió la conexión con el servidor", - "pad.modals.disconnected.cause": "El servidor podría no estar disponible. Contacte con nosotros si esto continúa sucediendo.", - "pad.share": "Compatir el pad", + "pad.modals.disconnected.cause": "El servidor podría no estar disponible. Contacta al administrador del servicio si esto continúa sucediendo.", + "pad.share": "Compatir este pad", "pad.share.readonly": "Sólo lectura", "pad.share.link": "Enlace", "pad.share.emebdcode": "Incrustar URL", @@ -99,18 +99,18 @@ "timeslider.version": "Versión {{version}}", "timeslider.saved": "Guardado el {{day}} de {{month}} de {{year}}", "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Enero", - "timeslider.month.february": "Febrero", - "timeslider.month.march": "Marzo", - "timeslider.month.april": "Abril", - "timeslider.month.may": "Mayo", - "timeslider.month.june": "Junio", - "timeslider.month.july": "Julio", - "timeslider.month.august": "Agosto", - "timeslider.month.september": "Septiembre", - "timeslider.month.october": "Octubre", - "timeslider.month.november": "Noviembre", - "timeslider.month.december": "Diciembre", + "timeslider.month.january": "enero", + "timeslider.month.february": "febrero", + "timeslider.month.march": "marzo", + "timeslider.month.april": "abril", + "timeslider.month.may": "mayo", + "timeslider.month.june": "junio", + "timeslider.month.july": "julio", + "timeslider.month.august": "agosto", + "timeslider.month.september": "septiembre", + "timeslider.month.october": "octubre", + "timeslider.month.november": "noviembre", + "timeslider.month.december": "diciembre", "timeslider.unnamedauthors": "{{num}} {[ plural(num) one: autor desconocido, other: autores desconocidos]}", "pad.savedrevs.marked": "Revisión guardada", "pad.userlist.entername": "Escribe tu nombre", @@ -118,13 +118,13 @@ "pad.userlist.guest": "Invitado", "pad.userlist.deny": "Denegar", "pad.userlist.approve": "Aprobar", - "pad.editbar.clearcolors": "¿Desea borrar el color de los autores en todo el documento?", - "pad.impexp.importbutton": "Importar", + "pad.editbar.clearcolors": "¿Quieres borrar los colores de autoría en todo el documento?", + "pad.impexp.importbutton": "Importar ahora", "pad.impexp.importing": "Importando...", - "pad.impexp.confirmimport": "Al importar un fichero se borrará el contenido actual del documento. ¿Quiere continuar?", - "pad.impexp.convertFailed": "No pudimos importar este fichero. Intentalo con otro formato diferente o copia y pega manualmente.", - "pad.impexp.uploadFailed": "El envío del fichero falló. Intentelo de nuevo.", + "pad.impexp.confirmimport": "Al importar un archivo se borrará el contenido actual del pad. ¿Estás seguro de que quieres continuar?", + "pad.impexp.convertFailed": "No pudimos importar este archivo. Inténtalo con un formato diferente o copia y pega manualmente.", + "pad.impexp.uploadFailed": "El envío falló. Intentalo de nuevo.", "pad.impexp.importfailed": "Fallo al importar", - "pad.impexp.copypaste": "Intente copiar y pegar", - "pad.impexp.exportdisabled": "La exportación al formato {{type}} format está desactivada. Contacte con su administrador de sistemas." + "pad.impexp.copypaste": "Intenta copiar y pegar", + "pad.impexp.exportdisabled": "La exportación al formato {{type}} está desactivada. Contacta a tu administrador de sistemas." } diff --git a/src/locales/et.json b/src/locales/et.json index 29cd92b9a..3ea8b3e63 100644 --- a/src/locales/et.json +++ b/src/locales/et.json @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Paraku on ainult lihttekstis voi HTML-vormingus dokumentide importimine võimaldatud. Rohkem võimaluste jaoks peab paigaldama abiword.", "pad.modals.connected": "Ühendatud.", "pad.modals.reconnecting": "Proovitakse luua ühendus klade juurde...", diff --git a/src/locales/eu.json b/src/locales/eu.json index 5aa3ec4eb..f12b8d21e 100644 --- a/src/locales/eu.json +++ b/src/locales/eu.json @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DocuWiki", "pad.importExport.abiword.innerHTML": "Testu laua edo html formatudun testuak bakarrik inporta ditzakezu. Aurreratuagoak diren inportazio aukerak izateko abiword instala ezazu.", "pad.modals.connected": "Konektatuta.", "pad.modals.reconnecting": "Zure pad-era birkonektatu...", diff --git a/src/locales/fa.json b/src/locales/fa.json index 3b421972e..94f2d69f5 100644 --- a/src/locales/fa.json +++ b/src/locales/fa.json @@ -14,14 +14,14 @@ "pad.toolbar.bold.title": "پررنگ (Ctrl-B)", "pad.toolbar.italic.title": "کج (Ctrl-I)", "pad.toolbar.underline.title": "زیرخط (Ctrl-U)", - "pad.toolbar.strikethrough.title": "خط خورده", - "pad.toolbar.ol.title": "فهرست مرتب شده", - "pad.toolbar.ul.title": "فهرست مرتب نشده", + "pad.toolbar.strikethrough.title": "خط خورده (Ctrl+5)", + "pad.toolbar.ol.title": "فهرست مرتب شده (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "فهرست مرتب نشده (Ctrl+Shift+L)", "pad.toolbar.indent.title": "تورفتگی (TAB)", "pad.toolbar.unindent.title": "بیرون رفتگی (Shift+TAB)", "pad.toolbar.undo.title": "باطل‌کردن (Ctrl-Z)", "pad.toolbar.redo.title": "از نو (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "پاک‌کردن رنگ‌های نویسندگی", + "pad.toolbar.clearAuthorship.title": "پاک‌کردن رنگ‌های نویسندگی (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "درون‌ریزی/برون‌ریزی از/به قالب‌های مختلف", "pad.toolbar.timeslider.title": "لغزندهٔ زمان", "pad.toolbar.savedRevision.title": "ذخیره‌سازی نسخه", @@ -54,7 +54,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (قالب سند باز)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "شما تنها می‌توانید از قالب متن ساده یا اچ‌تی‌ام‌ال درون‌ریزی کنید. برای بیشتر شدن ویژگی‌های درون‌ریزی پیشرفته AbiWord را نصب کنید.", "pad.modals.connected": "متصل شد.", "pad.modals.reconnecting": "در حال اتصال دوباره به دفترچه یادداشت شما..", diff --git a/src/locales/fi.json b/src/locales/fi.json index 656f0a212..ee1775dc2 100644 --- a/src/locales/fi.json +++ b/src/locales/fi.json @@ -9,7 +9,8 @@ "Stryn", "Tomi Toivio", "Veikk0.ma", - "VezonThunder" + "VezonThunder", + "Macofe" ] }, "index.newPad": "Uusi muistio", @@ -17,14 +18,14 @@ "pad.toolbar.bold.title": "Lihavointi (Ctrl-B)", "pad.toolbar.italic.title": "Kursivointi (Ctrl-I)", "pad.toolbar.underline.title": "Alleviivaus (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Yliviivaus", - "pad.toolbar.ol.title": "Numeroitu lista", - "pad.toolbar.ul.title": "Numeroimaton lista", + "pad.toolbar.strikethrough.title": "Yliviivaus (Ctrl+5)", + "pad.toolbar.ol.title": "Numeroitu lista (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Numeroimaton lista (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Sisennä (TAB)", "pad.toolbar.unindent.title": "Ulonna (Shift+TAB)", "pad.toolbar.undo.title": "Kumoa (Ctrl-Z)", "pad.toolbar.redo.title": "Tee uudelleen (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Poista kirjoittajavärit", + "pad.toolbar.clearAuthorship.title": "Poista kirjoittajavärit (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Tuo tai vie eri tiedostomuodoista tai -muotoihin", "pad.toolbar.timeslider.title": "Aikajana", "pad.toolbar.savedRevision.title": "Tallenna muutos", @@ -57,7 +58,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Tuonti on tuettu vain HTML- ja raakatekstitiedostoista. Lisätietoja tuonnin lisäasetuksista on sivulla install abiword.", "pad.modals.connected": "Yhdistetty.", "pad.modals.reconnecting": "Muodostetaan yhteyttä muistioon uudelleen...", diff --git a/src/locales/fo.json b/src/locales/fo.json index cd72dec76..43e9d9f1a 100644 --- a/src/locales/fo.json +++ b/src/locales/fo.json @@ -43,7 +43,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Opið Dokument Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Tú kanst bert innflyta frá einføldum teksti ella html formatum. Fyri funksjónir til innflytan fyri víðarikomin vinarliga installera abiword.", "pad.modals.connected": "Tú hevur samband.", "pad.modals.reconnecting": "Roynir aftur at fáa samband við tín pad..", diff --git a/src/locales/fr.json b/src/locales/fr.json index 757cd15ad..921d1eeb9 100644 --- a/src/locales/fr.json +++ b/src/locales/fr.json @@ -16,7 +16,9 @@ "Rastus Vernon", "Stephane Cottin", "Tux-tn", - "Maxim21" + "Maxim21", + "Boniface", + "Macofe" ] }, "index.newPad": "Nouveau pad", @@ -24,14 +26,14 @@ "pad.toolbar.bold.title": "Gras (Ctrl-B)", "pad.toolbar.italic.title": "Italique (Ctrl-I)", "pad.toolbar.underline.title": "Souligné (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Barré", - "pad.toolbar.ol.title": "Liste ordonnée", - "pad.toolbar.ul.title": "Liste non ordonnée", + "pad.toolbar.strikethrough.title": "Barré (Ctrl+5)", + "pad.toolbar.ol.title": "Liste ordonnée (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Liste non ordonnée (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Indenter (TAB)", "pad.toolbar.unindent.title": "Désindenter (Maj+TAB)", "pad.toolbar.undo.title": "Annuler (Ctrl-Z)", "pad.toolbar.redo.title": "Rétablir (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Effacer les couleurs identifiant les auteurs", + "pad.toolbar.clearAuthorship.title": "Effacer les couleurs identifiant les auteurs (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importer/Exporter de/vers un format de fichier différent", "pad.toolbar.timeslider.title": "Historique dynamique", "pad.toolbar.savedRevision.title": "Enregistrer la révision", @@ -49,7 +51,7 @@ "pad.settings.stickychat": "Toujours afficher le chat", "pad.settings.colorcheck": "Couleurs d’identification", "pad.settings.linenocheck": "Numéros de lignes", - "pad.settings.rtlcheck": "Lecture de droite à gauche", + "pad.settings.rtlcheck": "Le contenu doit-il être lu de droite à gauche ?", "pad.settings.fontType": "Police :", "pad.settings.fontType.normal": "Normal", "pad.settings.fontType.monospaced": "Monospace", @@ -57,14 +59,13 @@ "pad.settings.language": "Langue :", "pad.importExport.import_export": "Importer/Exporter", "pad.importExport.import": "Charger un texte ou un document", - "pad.importExport.importSuccessful": "Réussi!", + "pad.importExport.importSuccessful": "Réussi !", "pad.importExport.export": "Exporter le pad actuel comme :", "pad.importExport.exporthtml": "HTML", "pad.importExport.exportplain": "Texte brut", "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Vous ne pouvez importer que des formats texte brut ou html. Pour des fonctionnalités d'importation plus évoluées, veuillez installer abiword.", "pad.modals.connected": "Connecté.", "pad.modals.reconnecting": "Reconnexion vers votre pad...", @@ -83,7 +84,7 @@ "pad.modals.slowcommit.cause": "Ce problème peut venir d'une mauvaise connectivité au réseau.", "pad.modals.badChangeset.explanation": "Une modification que vous avez effectuée a été classée comme illégale par le serveur de synchronisation.", "pad.modals.badChangeset.cause": "Cela peut être dû à une mauvaise configuration du serveur ou à un autre comportement inattendu. Veuillez contacter l’administrateur du service, si vous pensez que c’est une erreur. Essayez de vous reconnecter pour continuer à modifier.", - "pad.modals.corruptPad.explanation": "Le bloc auquel vous essayez d’accéder est corrompu.", + "pad.modals.corruptPad.explanation": "Le pad auquel vous essayez d’accéder est corrompu.", "pad.modals.corruptPad.cause": "Cela peut être dû à une mauvaise configuration du serveur ou à un autre comportement inattendu. Veuillez contacter l’administrateur du service.", "pad.modals.deleted": "Supprimé.", "pad.modals.deleted.explanation": "Ce pad a été supprimé.", @@ -102,22 +103,22 @@ "timeslider.toolbar.authors": "Auteurs :", "timeslider.toolbar.authorsList": "Aucun auteur", "timeslider.toolbar.exportlink.title": "Exporter", - "timeslider.exportCurrent": "Exporter la version actuelle en :", + "timeslider.exportCurrent": "Exporter la version actuelle sous :", "timeslider.version": "Version {{version}}", "timeslider.saved": "Enregistré le {{day}} {{month}} {{year}}", "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", - "timeslider.month.january": "Janvier", - "timeslider.month.february": "Février", - "timeslider.month.march": "Mars", - "timeslider.month.april": "Avril", - "timeslider.month.may": "Mai", - "timeslider.month.june": "Juin", - "timeslider.month.july": "Juillet", - "timeslider.month.august": "Août", - "timeslider.month.september": "Septembre", - "timeslider.month.october": "Octobre", - "timeslider.month.november": "Novembre", - "timeslider.month.december": "Décembre", + "timeslider.month.january": "janvier", + "timeslider.month.february": "février", + "timeslider.month.march": "mars", + "timeslider.month.april": "avril", + "timeslider.month.may": "mai", + "timeslider.month.june": "juin", + "timeslider.month.july": "juillet", + "timeslider.month.august": "août", + "timeslider.month.september": "septembre", + "timeslider.month.october": "octobre", + "timeslider.month.november": "novembre", + "timeslider.month.december": "décembre", "timeslider.unnamedauthors": "{{num}} {[plural(num) one: auteur anonyme, other: auteurs anonymes ]}", "pad.savedrevs.marked": "Cette révision est maintenant marquée comme révision enregistrée", "pad.userlist.entername": "Entrez votre nom", @@ -128,10 +129,10 @@ "pad.editbar.clearcolors": "Effacer les couleurs de paternité dans tout le document ?", "pad.impexp.importbutton": "Importer maintenant", "pad.impexp.importing": "Import en cours...", - "pad.impexp.confirmimport": "Importer un fichier écrasera le texte actuel du pad. Êtes-vous sûr de vouloir le faire?", + "pad.impexp.confirmimport": "Importer un fichier écrasera le texte actuel du pad. Êtes-vous sûr de vouloir le faire ?", "pad.impexp.convertFailed": "Nous ne pouvons pas importer ce fichier. Veuillez utiliser un autre format de document ou faire un copier/coller manuel", "pad.impexp.uploadFailed": "Le téléchargement a échoué, veuillez réessayer", "pad.impexp.importfailed": "Échec de l'importation", "pad.impexp.copypaste": "Veuillez copier/coller", - "pad.impexp.exportdisabled": "Exporter au format {{type}} est désactivé. Veuillez contacter votre administrateur système pour plus de détails." + "pad.impexp.exportdisabled": "L'option d'export au format {{type}} est désactivée. Veuillez contacter votre administrateur système pour plus de détails." } diff --git a/src/locales/gl.json b/src/locales/gl.json index 93855a8b5..a14fbb126 100644 --- a/src/locales/gl.json +++ b/src/locales/gl.json @@ -1,7 +1,8 @@ { "@metadata": { "authors": [ - "Toliño" + "Toliño", + "Elisardojm" ] }, "index.newPad": "Novo documento", @@ -9,14 +10,14 @@ "pad.toolbar.bold.title": "Negra (Ctrl-B)", "pad.toolbar.italic.title": "Cursiva (Ctrl-I)", "pad.toolbar.underline.title": "Subliñar (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Riscar", - "pad.toolbar.ol.title": "Lista ordenada", - "pad.toolbar.ul.title": "Lista sen ordenar", + "pad.toolbar.strikethrough.title": "Riscar (Ctrl+5)", + "pad.toolbar.ol.title": "Lista ordenada (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Lista sen ordenar (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Sangría (TAB)", "pad.toolbar.unindent.title": "Sen sangría (Maiús.+TAB)", "pad.toolbar.undo.title": "Desfacer (Ctrl-Z)", "pad.toolbar.redo.title": "Refacer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Limpar as cores de identificación dos autores", + "pad.toolbar.clearAuthorship.title": "Limpar as cores de identificación dos autores (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importar/Exportar desde/a diferentes formatos de ficheiro", "pad.toolbar.timeslider.title": "Liña do tempo", "pad.toolbar.savedRevision.title": "Gardar a revisión", @@ -49,7 +50,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Só pode importar texto simple ou formatos HTML. Para obter máis información sobre as características de importación avanzadas instale abiword.", "pad.modals.connected": "Conectado.", "pad.modals.reconnecting": "Reconectando co seu documento...", diff --git a/src/locales/he.json b/src/locales/he.json index 555cb5f5f..573bc5f61 100644 --- a/src/locales/he.json +++ b/src/locales/he.json @@ -12,14 +12,14 @@ "pad.toolbar.bold.title": "בולט (Ctrl-B)", "pad.toolbar.italic.title": "נטוי (Ctrl-I)", "pad.toolbar.underline.title": "קו תחתי (Ctrl-U)", - "pad.toolbar.strikethrough.title": "קו מוחק", - "pad.toolbar.ol.title": "רשימה ממוספרת", - "pad.toolbar.ul.title": "רשימה", + "pad.toolbar.strikethrough.title": "קו מוחק (Ctrl+5)", + "pad.toolbar.ol.title": "רשימה ממוספרת (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "רשימת תבליטים (Ctrl+Shift+L)", "pad.toolbar.indent.title": "הזחה (טאב)", "pad.toolbar.unindent.title": "צמצום הזחה (שיפט–טאב)", "pad.toolbar.undo.title": "ביטול (Ctrl-Z)", "pad.toolbar.redo.title": "ביצוע מחדש", - "pad.toolbar.clearAuthorship.title": "ניקוי צבעים", + "pad.toolbar.clearAuthorship.title": "ניקוי צבעי כותבים (Ctrl-Shift-C)", "pad.toolbar.import_export.title": "ייבוא/ייצוא בתסדירי קבצים שונים", "pad.toolbar.timeslider.title": "גולל זמן", "pad.toolbar.savedRevision.title": "שמירת גרסה", @@ -52,7 +52,6 @@ "pad.importExport.exportword": "מיקרוסופט וורד", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "באפשרותך לייבא מטקסט פשוט או מ־HTML. לאפשרויות ייבוא מתקדמות יותר יש להתקין את abiword.", "pad.modals.connected": "מחובר.", "pad.modals.reconnecting": "מתבצע חיבור מחדש...", diff --git a/src/locales/hrx.json b/src/locales/hrx.json index 808a12975..74630efa5 100644 --- a/src/locales/hrx.json +++ b/src/locales/hrx.json @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Sie können nur aus Klartext oder HTML-Formaten importieren. Für mehr erweiterte Importfunktionen installieren Sie bitte abiword.", "pad.modals.connected": "Verbünd (konnektiert).", "pad.modals.reconnecting": "Wiederherstelle von der Verbinnung …", diff --git a/src/locales/hsb.json b/src/locales/hsb.json index c86f60787..ddf3cc4a6 100644 --- a/src/locales/hsb.json +++ b/src/locales/hsb.json @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Móžeš jenož z formatow luteho teksta abo z HTML-formata importować. Za bóle rozšěrjene importowanske funkcije instaluj prošu Abiword.", "pad.modals.connected": "Zwjazany.", "pad.modals.reconnecting": "Zwjazuje so znowa z twojim zapisnikom...", diff --git a/src/locales/hu.json b/src/locales/hu.json index 2cbf57496..7efac2df2 100644 --- a/src/locales/hu.json +++ b/src/locales/hu.json @@ -13,14 +13,14 @@ "pad.toolbar.bold.title": "Félkövér (Ctrl-B)", "pad.toolbar.italic.title": "Dőlt (Ctrl-I)", "pad.toolbar.underline.title": "Aláhúzás (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Áthúzás", - "pad.toolbar.ol.title": "Számozott lista", - "pad.toolbar.ul.title": "Számozatlan lista", + "pad.toolbar.strikethrough.title": "Áthúzás (Ctrl+5)", + "pad.toolbar.ol.title": "Számozott lista (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Számozatlan lista (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Behúzás növelése (TAB)", "pad.toolbar.unindent.title": "Behúzás csökkentése (Shift+TAB)", "pad.toolbar.undo.title": "Visszavonás (Ctrl-Z)", "pad.toolbar.redo.title": "Újra (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Szerzők színezésének kikapcsolása", + "pad.toolbar.clearAuthorship.title": "Szerzők színezésének kikapcsolása (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importálás/exportálás különböző fájlformátumokból/ba", "pad.toolbar.timeslider.title": "Időcsúszka", "pad.toolbar.savedRevision.title": "Revízió mentése", @@ -53,7 +53,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document formátum)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Csak szöveges, vagy HTML formátumokból importálhatsz. A speciális importálási funkciókért kérjük telepítsd az abiword-öt.", "pad.modals.connected": "Kapcsolódva.", "pad.modals.reconnecting": "Újrakapcsolódás a noteszhez...", diff --git a/src/locales/ia.json b/src/locales/ia.json index 971f2919e..50a0690cc 100644 --- a/src/locales/ia.json +++ b/src/locales/ia.json @@ -9,14 +9,14 @@ "pad.toolbar.bold.title": "Grasse (Ctrl-B)", "pad.toolbar.italic.title": "Italic (Ctrl-I)", "pad.toolbar.underline.title": "Sublinear (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Cancellar", - "pad.toolbar.ol.title": "Lista ordinate", - "pad.toolbar.ul.title": "Lista non ordinate", + "pad.toolbar.strikethrough.title": "Cancellar (Ctrl+5)", + "pad.toolbar.ol.title": "Lista ordinate (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Lista non ordinate (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Indentar (TAB)", "pad.toolbar.unindent.title": "Disindentar (Shift+TAB)", "pad.toolbar.undo.title": "Disfacer (Ctrl-Z)", "pad.toolbar.redo.title": "Refacer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Rader colores de autor", + "pad.toolbar.clearAuthorship.title": "Rader colores de autor (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importar/exportar in differente formatos de file", "pad.toolbar.timeslider.title": "Glissa-tempore", "pad.toolbar.savedRevision.title": "Version salveguardate", @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Tu pote solmente importar files in formato de texto simple o HTML. Pro functionalitate de importation plus extense, installa AbiWord.", "pad.modals.connected": "Connectite.", "pad.modals.reconnecting": "Reconnecte a tu pad…", diff --git a/src/locales/it.json b/src/locales/it.json index 8292c4f27..02ae8a9f7 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -4,7 +4,8 @@ "Beta16", "Gianfranco", "Muxator", - "Vituzzu" + "Vituzzu", + "Macofe" ] }, "index.newPad": "Nuovo Pad", @@ -12,14 +13,14 @@ "pad.toolbar.bold.title": "Grassetto (Ctrl-B)", "pad.toolbar.italic.title": "Corsivo (Ctrl-I)", "pad.toolbar.underline.title": "Sottolineato (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Barrato", - "pad.toolbar.ol.title": "Elenco numerato", - "pad.toolbar.ul.title": "Elenco puntato", + "pad.toolbar.strikethrough.title": "Barrato (Ctrl+5)", + "pad.toolbar.ol.title": "Elenco numerato (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Elenco puntato (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Rientro (TAB)", "pad.toolbar.unindent.title": "Riduci rientro (Shift+TAB)", "pad.toolbar.undo.title": "Annulla (Ctrl-Z)", "pad.toolbar.redo.title": "Ripeti (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Elimina i colori che indicano gli autori", + "pad.toolbar.clearAuthorship.title": "Elimina i colori che indicano gli autori (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importa/esporta da/a diversi formati di file", "pad.toolbar.timeslider.title": "Presentazione cronologia", "pad.toolbar.savedRevision.title": "Versione salvata", @@ -52,7 +53,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "È possibile importare solo i formati di testo semplice o HTML. Per metodi più avanzati di importazione installare Abiword.", "pad.modals.connected": "Connesso.", "pad.modals.reconnecting": "Riconnessione al pad in corso...", diff --git a/src/locales/ja.json b/src/locales/ja.json index f9d63cd26..62e6dc624 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -6,16 +6,16 @@ }, "index.newPad": "新規作成", "index.createOpenPad": "または作成/編集するパッド名を入力:", - "pad.toolbar.bold.title": "太字 (Ctrl-B)", - "pad.toolbar.italic.title": "斜体 (Ctrl-I)", - "pad.toolbar.underline.title": "下線 (Ctrl-U)", - "pad.toolbar.strikethrough.title": "取り消し線", - "pad.toolbar.ol.title": "番号付きリスト", - "pad.toolbar.ul.title": "番号なしリスト", + "pad.toolbar.bold.title": "太字 (Ctrl+B)", + "pad.toolbar.italic.title": "斜体 (Ctrl+I)", + "pad.toolbar.underline.title": "下線 (Ctrl+U)", + "pad.toolbar.strikethrough.title": "取り消し線 (Ctrl+5)", + "pad.toolbar.ol.title": "番号付きリスト (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "番号なしリスト (Ctrl+Shift+L)", "pad.toolbar.indent.title": "インデント (Tab)", "pad.toolbar.unindent.title": "インデント解除 (Shift+Tab)", - "pad.toolbar.undo.title": "元に戻す (Ctrl-Z)", - "pad.toolbar.redo.title": "やり直し (Ctrl-Y)", + "pad.toolbar.undo.title": "元に戻す (Ctrl+Z)", + "pad.toolbar.redo.title": "やり直し (Ctrl+Y)", "pad.toolbar.clearAuthorship.title": "作者の色分けを消去", "pad.toolbar.import_export.title": "他の形式のファイルのインポート/エクスポート", "pad.toolbar.timeslider.title": "タイムスライダー", @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "プレーンテキストまたは HTML ファイルからのみインポートできます。より高度なインポート機能を使用するには、abiword をインストールしてください。", "pad.modals.connected": "接続されました。", "pad.modals.reconnecting": "パッドに再接続中...", diff --git a/src/locales/km.json b/src/locales/km.json index a90c0e970..4dea037aa 100644 --- a/src/locales/km.json +++ b/src/locales/km.json @@ -47,7 +47,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.modals.connected": "បាន​តភ្ជាប់​។", "pad.modals.reconnecting": "កំពុង​ភ្ជាប់​ទៅ​ផេត​របស់​អ្នក​ម្ដង​ទៀត..", "pad.modals.forcereconnect": "បង្ខំ​ឲ្យ​ភ្ជាប់​ឡើង​វិញ", diff --git a/src/locales/ko.json b/src/locales/ko.json index 16a478f97..e18c5bbd4 100644 --- a/src/locales/ko.json +++ b/src/locales/ko.json @@ -2,7 +2,8 @@ "@metadata": { "authors": [ "Hym411", - "아라" + "아라", + "Revi" ] }, "index.newPad": "새 패드", @@ -10,14 +11,14 @@ "pad.toolbar.bold.title": "굵게 (Ctrl-B)", "pad.toolbar.italic.title": "기울임 (Ctrl-I)", "pad.toolbar.underline.title": "밑줄 (Ctrl-U)", - "pad.toolbar.strikethrough.title": "취소선", - "pad.toolbar.ol.title": "순서 있는 목록", - "pad.toolbar.ul.title": "순서 없는 목록", + "pad.toolbar.strikethrough.title": "취소선 (Ctrl+5)", + "pad.toolbar.ol.title": "순서 있는 목록 (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "순서 없는 목록 (Ctrl+Shift+L)", "pad.toolbar.indent.title": "들여쓰기 (TAB)", "pad.toolbar.unindent.title": "내어쓰기 (Shift+TAB)", "pad.toolbar.undo.title": "실행 취소 (Ctrl-Z)", "pad.toolbar.redo.title": "다시 실행 (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "저자의 색 지우기", + "pad.toolbar.clearAuthorship.title": "저자의 색 지우기 (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "다른 파일 형식으로 가져오기/내보내기", "pad.toolbar.timeslider.title": "시간슬라이더", "pad.toolbar.savedRevision.title": "판 저장", @@ -50,7 +51,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "일반 텍스트나 html 형식으로만 가져올 수 있습니다. 고급 가져오기 기능에 대해서는 abiword를 설치하세요.", "pad.modals.connected": "연결했습니다.", "pad.modals.reconnecting": "패드에 다시 연결 중..", diff --git a/src/locales/ksh.json b/src/locales/ksh.json index 1de3c450d..8443e0ec9 100644 --- a/src/locales/ksh.json +++ b/src/locales/ksh.json @@ -9,14 +9,14 @@ "pad.toolbar.bold.title": "Fättschreff (Strg-B)", "pad.toolbar.italic.title": "Scheive Schreff (Strg-I)", "pad.toolbar.underline.title": "Ongerstresche (Strg-U)", - "pad.toolbar.strikethrough.title": "Dorschjeschtresche", - "pad.toolbar.ol.title": "Leß met Nommere", - "pad.toolbar.ul.title": "Leß met Pongkte", + "pad.toolbar.strikethrough.title": "Dorschjeschtresche (Strg+5)", + "pad.toolbar.ol.title": "Leß met Nommere (Strg+Jruhß+N)", + "pad.toolbar.ul.title": "Leß met Pongkte (Strg+Jruhß+L)", "pad.toolbar.indent.title": "Enjerök (TAB)", "pad.toolbar.unindent.title": "Ußjerök (Jruhßschreff+TAB)", "pad.toolbar.undo.title": "Retuur nämme (Strg-Z)", "pad.toolbar.redo.title": "Norrens (Strg-Y)", - "pad.toolbar.clearAuthorship.title": "Donn dä Schriiver ier Färve fottnämme", + "pad.toolbar.clearAuthorship.title": "Donn dä Schriiver ier Färve fottnämme (Strg+Jruhß+C)", "pad.toolbar.import_export.title": "Ongerscheidlijje Dattei_Fommaate empotteere udder äxpotteere", "pad.toolbar.timeslider.title": "Verjangeheid afschpelle", "pad.toolbar.savedRevision.title": "Di Väsjohn faßhallde", @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF (Poteerbaa Dokemänte Fommaat)", "pad.importExport.exportopen": "ODF (Offe Dokemänte-Fommaat)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Mer künne bloß eijfaache Täxte udder HTML_Fommaate empoteere. Opwändejere Müjjeleschkeite fö der Empoot jon och, doför bruch mer en Enschtallazjuhn met Abiword.", "pad.modals.connected": "Verbonge.", "pad.modals.reconnecting": "Ben wider aam Verbenge …", diff --git a/src/locales/lb.json b/src/locales/lb.json index 7f936906f..841add75f 100644 --- a/src/locales/lb.json +++ b/src/locales/lb.json @@ -6,8 +6,8 @@ ] }, "index.newPad": "Neie Pad", - "pad.toolbar.ol.title": "Numeréiert Lëscht", - "pad.toolbar.ul.title": "Net-numeréiert Lëscht", + "pad.toolbar.ol.title": "Numeréiert Lëscht (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Net-numeréiert Lëscht (Ctrl+Shift+L)", "pad.toolbar.undo.title": "Réckgängeg (Ctrl-Z)", "pad.toolbar.redo.title": "Widderhuelen (Ctrl-Y)", "pad.toolbar.savedRevision.title": "Versioun späicheren", diff --git a/src/locales/lki.json b/src/locales/lki.json new file mode 100644 index 000000000..b74362980 --- /dev/null +++ b/src/locales/lki.json @@ -0,0 +1,75 @@ +{ + "@metadata": { + "authors": [ + "Hosseinblue" + ] + }, + "index.newPad": "تازۀpad", + "index.createOpenPad": ":ئۀ وسیلۀ نؤمpadسازین/وآز کردن یه گلۀ", + "pad.toolbar.bold.title": "پررنگ-تئژ(Ctrl-B)", + "pad.toolbar.italic.title": "ایتالیک (Ctrl-I)", + "pad.toolbar.underline.title": "ژئر خطی(Ctrl-U)", + "pad.toolbar.strikethrough.title": "خط هوواردئ", + "pad.toolbar.ol.title": "فئرست رزگی-مرتب", + "pad.toolbar.ul.title": "نۀچنریا-نامرتب", + "pad.toolbar.indent.title": "تورفتگی-ئه نؤم چئن (TAB)", + "pad.toolbar.unindent.title": "(Shift+TAB)بیرون آمدگی-درچئن", + "pad.toolbar.undo.title": "گِلّا دائن-ئآهۀتن(Ctrl-Z)", + "pad.toolbar.redo.title": "ئۀ نوواهۀتن (Ctrl-Y)", + "pad.toolbar.clearAuthorship.title": "پاکاکردن رنگۀل تالیفی", + "pad.toolbar.import_export.title": "دربردن/ئه نؤم ئآووردن ئۀ/ئِِژ فرمتۀل گوناگون", + "pad.toolbar.timeslider.title": "اسلایدر وختی-زمانی", + "pad.toolbar.savedRevision.title": "ذخیرل دسکاریۀل", + "pad.toolbar.settings.title": "تنظیمۀل", + "pad.toolbar.embed.title": "بۀشاکردن ؤ نیائن(اشتراک ونشاندن)ئۀ نؤم سایت", + "pad.toolbar.showusers.title": "نیشان دائن کاربر ئۀ نؤم ئئ\npad", + "pad.colorpicker.save": "ذخیرۀ", + "pad.colorpicker.cancel": "ئآهووسانن-لغو", + "pad.loading": "...(loading)بارنیائن", + "pad.passwordRequired": "هؤمۀ رمزتؤنه گرۀکۀ-لازمۀ ئۀرا اتصال ئئ \npad", + "pad.wrongPassword": "رمزۀ تؤن دؤرس نیۀ", + "pad.settings.padSettings": "pad تنظیمۀل", + "pad.settings.myView": "نمایش-سئرکردن مه", + "pad.settings.stickychat": "چت همؤیشۀ ئۀ ولگۀ نمایش بوو", + "pad.settings.colorcheck": "رنگۀل تالیفی", + "pad.settings.linenocheck": "شؤمارۀل خطی", + "pad.settings.fontType": ":شئؤۀ فؤنت", + "pad.settings.fontType.normal": "عادی", + "pad.settings.fontType.monospaced": "پئنی-پهنا", + "pad.settings.globalView": "نمایش جئ هانی", + "pad.settings.language": ":زوون", + "pad.importExport.import_export": "در بردن/ئه نؤم ئآووردن", + "pad.importExport.import": "بارنیائن هر جور نوشته یا سندئ", + "pad.importExport.importSuccessful": "! موفق بی-پیرووز بی", + "pad.importExport.exporthtml": "html", + "pad.importExport.exportplain": "متن پئن-درئژ", + "pad.importExport.exportword": "مایکروسافت وورد", + "pad.importExport.exportpdf": "پی دی اف", + "pad.modals.connected": "وصل بیۀ", + "pad.modals.deleted": "پاک بیا-حذف بی", + "pad.share.readonly": "تنیا بخؤۀن", + "pad.share.link": "لینک", + "pad.chat": "گپ", + "pad.chat.loadmessages": "پئامۀلئ تر باره سۀر", + "timeslider.toolbar.exportlink.title": "در بِردن", + "timeslider.month.january": "دی)نورووژ)", + "timeslider.month.february": "(خاکه لێه(بهمن", + "timeslider.month.march": "(مانگ ئێد(اسفندگان", + "timeslider.month.april": "(په نجه(فروردین", + "timeslider.month.may": "(مێرێان(اردیبهشت", + "timeslider.month.june": "(گاکوور(خرداد", + "timeslider.month.july": "تیر)ئاگرانی)", + "timeslider.month.august": "مرداد)مردار)", + "timeslider.month.september": "(ماڵه ژێر(شهریور", + "timeslider.month.october": "(ماڵه ژێر دوماێنه(مهر", + "timeslider.month.november": "آبان)تویل ته کن)", + "timeslider.month.december": "(مانگه سێه(آذر", + "pad.userlist.entername": "نؤم تؤن وارد کۀن", + "pad.userlist.unnamed": "بئ نؤم", + "pad.userlist.guest": "مئمان", + "pad.userlist.deny": "رد کردن", + "pad.userlist.approve": "راووا داشتن-تصویب کردن", + "pad.impexp.importbutton": "ایسۀ وارد کۀ", + "pad.impexp.importing": "...وارد مۀهه", + "pad.impexp.importfailed": "وارد نؤنئ-خطای واردکردن" +} diff --git a/src/locales/lrc.json b/src/locales/lrc.json index 322b6f23b..910f8f1ef 100644 --- a/src/locales/lrc.json +++ b/src/locales/lrc.json @@ -36,7 +36,6 @@ "pad.importExport.exportword": "واجه پالایشتگر مایکروسافت", "pad.importExport.exportpdf": "پی دی اف", "pad.importExport.exportopen": "او دی اف(قالو سند وا بیه)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.modals.connected": "وصل بیه", "pad.modals.forcereconnect": "سی وصل بین مژبور کو", "pad.modals.userdup": "د نیمدری هنی واز بیه", diff --git a/src/locales/lt.json b/src/locales/lt.json index 503b65893..7b4e14818 100644 --- a/src/locales/lt.json +++ b/src/locales/lt.json @@ -28,7 +28,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Atvirasis dokumento formatas)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.modals.connected": "Prisijungta.", "pad.modals.unauth": "Neleidžiama", "pad.modals.initsocketfail": "Serveris yra nepasiekiamas.", diff --git a/src/locales/lv.json b/src/locales/lv.json index e57c4259c..acdaaccd1 100644 --- a/src/locales/lv.json +++ b/src/locales/lv.json @@ -46,7 +46,6 @@ "pad.importExport.exportword": "Programma Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open dokumenta formāts)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.modals.userdup": "Atvērts citā logā", "pad.modals.unauth": "Nav atļauts", "pad.modals.looping.explanation": "Pastāv sakaru problēmas ar sinhronizācijas servera.", diff --git a/src/locales/map-bms.json b/src/locales/map-bms.json index 883b1d8f9..1b87bac89 100644 --- a/src/locales/map-bms.json +++ b/src/locales/map-bms.json @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Rika mung teyeng impor sekang format plain text utawa HTML. Kanggo fitur impor sing lewih maju monggo masang abiword.", "pad.modals.connected": "Nyambung.", "pad.modals.reconnecting": "Mbaleli nyambung ming pad Rika...", diff --git a/src/locales/mk.json b/src/locales/mk.json index 8aaf9917b..fc18533fa 100644 --- a/src/locales/mk.json +++ b/src/locales/mk.json @@ -10,14 +10,14 @@ "pad.toolbar.bold.title": "Задебелено (Ctrl-B)", "pad.toolbar.italic.title": "Косо (Ctrl-I)", "pad.toolbar.underline.title": "Подвлечено (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Прецртано", - "pad.toolbar.ol.title": "Подреден список", - "pad.toolbar.ul.title": "Неподреден список", + "pad.toolbar.strikethrough.title": "Прецртано (Ctrl+5)", + "pad.toolbar.ol.title": "Подреден список (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Неподреден список (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Вовлекување (TAB)", "pad.toolbar.unindent.title": "Отстап (Shift+TAB)", "pad.toolbar.undo.title": "Врати (Ctrl-Z)", "pad.toolbar.redo.title": "Повтори (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Поништи ги авторските бои", + "pad.toolbar.clearAuthorship.title": "Тргни ги авторските бои (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Увоз/Извоз од/во разни податотечни формати", "pad.toolbar.timeslider.title": "Историски преглед", "pad.toolbar.savedRevision.title": "Зачувај преработка", @@ -50,7 +50,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Можете да увезувате само од прост текст и HTML-формат. Понапредни можности за увоз ќе добиете ако воспоставите AbiWord.", "pad.modals.connected": "Поврзано.", "pad.modals.reconnecting": "Ве преповрзувам со тетратката...", diff --git a/src/locales/ml.json b/src/locales/ml.json index ff7a38f33..680df0c24 100644 --- a/src/locales/ml.json +++ b/src/locales/ml.json @@ -13,14 +13,14 @@ "pad.toolbar.bold.title": "കടുപ്പത്തിലെഴുതുക (Ctrl-B)", "pad.toolbar.italic.title": "ചെരിച്ചെഴുതുക (Ctrl-I)", "pad.toolbar.underline.title": "അടിവരയിടുക (Ctrl-U)", - "pad.toolbar.strikethrough.title": "വെട്ടുക", - "pad.toolbar.ol.title": "ക്രമത്തിലുള്ള പട്ടിക", - "pad.toolbar.ul.title": "ക്രമരഹിത പട്ടിക", + "pad.toolbar.strikethrough.title": "വെട്ടുക (Ctrl+5)", + "pad.toolbar.ol.title": "ക്രമത്തിലുള്ള പട്ടിക (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "ക്രമരഹിത പട്ടിക (Ctrl+Shift+L)", "pad.toolbar.indent.title": "വലത്തേക്ക് തള്ളുക (ടാബ്)", "pad.toolbar.unindent.title": "ഇടത്തേക്ക് തള്ളുക (ഷിഫ്റ്റ്+ടാബ്)", "pad.toolbar.undo.title": "തിരസ്കരിക്കുക (Ctrl-Z)", "pad.toolbar.redo.title": "വീണ്ടും ചെയ്യുക (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "രചയിതാക്കൾക്കുള്ള നിറം കളയുക", + "pad.toolbar.clearAuthorship.title": "രചയിതാക്കൾക്കുള്ള നിറം കളയുക (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "വ്യത്യസ്ത ഫയൽ തരങ്ങളിലേക്ക്/തരങ്ങളിൽ നിന്ന് ഇറക്കുമതി/കയറ്റുമതി ചെയ്യുക", "pad.toolbar.timeslider.title": "സമയരേഖ", "pad.toolbar.savedRevision.title": "നാൾപ്പതിപ്പ് സേവ് ചെയ്യുക", @@ -53,7 +53,6 @@ "pad.importExport.exportword": "മൈക്രോസോഫ്റ്റ് വേഡ്", "pad.importExport.exportpdf": "പി.ഡി.എഫ്.", "pad.importExport.exportopen": "ഒ.ഡി.എഫ്. (ഓപ്പൺ ഡോക്യുമെന്റ് ഫോർമാറ്റ്)", - "pad.importExport.exportdokuwiki": "ഡോകുവിക്കി", "pad.importExport.abiword.innerHTML": "പ്ലെയിൻ ടെക്സ്റ്റോ എച്ച്.റ്റി.എം.എൽ. തരമോ മാത്രമേ താങ്കൾക്ക് ഇറക്കുമതി ചെയ്യാനാവൂ. കൂടുതൽ വിപുലീകൃത ഇറക്കുമതി സൗകര്യങ്ങൾക്കായി ദയവായി അബിവേഡ് ഇൻസ്റ്റോൾ ചെയ്യുക.", "pad.modals.connected": "ബന്ധിപ്പിച്ചിരിക്കുന്നു.", "pad.modals.reconnecting": "താങ്കളുടെ പാഡിലേയ്ക്ക് വീണ്ടും ബന്ധിപ്പിക്കുന്നു...", diff --git a/src/locales/mn.json b/src/locales/mn.json new file mode 100644 index 000000000..4b418bef4 --- /dev/null +++ b/src/locales/mn.json @@ -0,0 +1,76 @@ +{ + "@metadata": { + "authors": [ + "MongolWiki", + "Wisdom" + ] + }, + "pad.toolbar.bold.title": "Болд тескт (Ctrl-B)", + "pad.toolbar.italic.title": "Налуу тескт (Ctrl-I)", + "pad.toolbar.underline.title": "Доогуур зураас (Ctrl-U)", + "pad.toolbar.strikethrough.title": "Дундуураа зураастай", + "pad.toolbar.ol.title": "Эрэмбэлэгдсэн жагсаалт", + "pad.toolbar.ul.title": "Эрэмбэлээгүй жагсаалт", + "pad.toolbar.undo.title": "Буцаах (Ctrl-Z)", + "pad.toolbar.redo.title": "Undo -ын эсрэг (Ctrl-Y)", + "pad.toolbar.settings.title": "Тохиргоо", + "pad.colorpicker.save": "Хадгалах", + "pad.colorpicker.cancel": "Цуцлах", + "pad.loading": "Уншиж байна...", + "pad.settings.padSettings": "Падын тохиргоо", + "pad.settings.linenocheck": "Мөрийн дугаар", + "pad.settings.fontType": "Фонтын төрөл:", + "pad.settings.fontType.normal": "Ердийн", + "pad.settings.fontType.monospaced": "Зай ихтэй фонт", + "pad.settings.language": "Хэл:", + "pad.importExport.import_export": "Импорт/Экспорт", + "pad.importExport.import": "Бичвэр, текст файл оруулах", + "pad.importExport.importSuccessful": "Амжилттай!", + "pad.importExport.exportplain": "Цулгаа бичвэр", + "pad.importExport.exportpdf": "PDF файл", + "pad.importExport.exportopen": "ODF файл", + "pad.modals.connected": "Холбогдсон.", + "pad.modals.unauth": "Үл зөвшөөрөгдсөн", + "pad.modals.initsocketfail": "Сервер холбогдох боломжгүй.", + "pad.modals.slowcommit.explanation": "Сервер хариу өгөхгүй байна.", + "pad.modals.deleted": "Устгагдсан", + "pad.modals.deleted.explanation": "Энэ паб устсан байна.", + "pad.modals.disconnected": "Таны холболт салсан байна.", + "pad.modals.disconnected.explanation": "Серверын холболт салсан байна", + "pad.share": "Энэ падыг тараах", + "pad.share.readonly": "Зөвхөн унших", + "pad.share.link": "Холбоос", + "pad.share.emebdcode": "URL хавсаргах", + "pad.chat": "Чат", + "pad.chat.loadmessages": "Нэмэж мессеж оруулах", + "timeslider.toolbar.returnbutton": "Падруу буцах", + "timeslider.toolbar.authors": "Зохиогч:", + "timeslider.toolbar.authorsList": "Зохиогчгүй", + "timeslider.toolbar.exportlink.title": "Экспорт", + "timeslider.exportCurrent": "Энэ хувилбарыг экспортлохдоо:", + "timeslider.version": "Хувилбар {{version}}", + "timeslider.saved": "{{year}}-ы {{month}}-н {{day}}-нд да;галсан.", + "timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", + "timeslider.month.january": "Нэгдүгээр сар", + "timeslider.month.february": "Хоёрдугаар сар", + "timeslider.month.march": "Гуравдугаар сар", + "timeslider.month.april": "Дөрөвдүгээр сар", + "timeslider.month.may": "Тавдугаар сар", + "timeslider.month.june": "Зургаадугаар сар", + "timeslider.month.july": "Долоодугаар сар", + "timeslider.month.august": "Наймдугаар сар", + "timeslider.month.september": "Есдүгээр сар", + "timeslider.month.october": "Аравдугаар сар", + "timeslider.month.november": "Арваннэгдүгээр сар", + "timeslider.month.december": "Арванхоёрдугаар сар", + "pad.savedrevs.marked": "Энэ хувилбар хадгалагдаагүй байна", + "pad.userlist.entername": "Нэрээ бичнэ үү", + "pad.userlist.unnamed": "нэргүй", + "pad.userlist.guest": "Зочин", + "pad.userlist.deny": "Үл зөвшөөр", + "pad.userlist.approve": "Зөвшөөр", + "pad.impexp.importbutton": "Одоо импорт хий", + "pad.impexp.importing": "Импортлож байна...", + "pad.impexp.importfailed": "Импортлоход алдаа", + "pad.impexp.copypaste": "Хуулаад тавина уу" +} diff --git a/src/locales/mr.json b/src/locales/mr.json index 31de89aaf..536b578c0 100644 --- a/src/locales/mr.json +++ b/src/locales/mr.json @@ -26,7 +26,6 @@ "pad.importExport.exportword": "मायक्रोसॉफ्ट वर्ड", "pad.importExport.exportpdf": "पीडीएफ", "pad.importExport.exportopen": "ओडीएफ(ओपन डॉक्यूमेंट फॉरमॅट)", - "pad.importExport.exportdokuwiki": "डुकुविकि", "pad.modals.connected": "अनुबंधित", "pad.modals.initsocketfail": "विदागारास पोच नाही.", "pad.modals.deleted": "वगळले.", diff --git a/src/locales/ms.json b/src/locales/ms.json index 033de1bc6..cf15be6e2 100644 --- a/src/locales/ms.json +++ b/src/locales/ms.json @@ -9,14 +9,14 @@ "pad.toolbar.bold.title": "Tebal (Ctrl-B)", "pad.toolbar.italic.title": "Miring (Ctrl-I)", "pad.toolbar.underline.title": "Garis bawah (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Garis lorek", - "pad.toolbar.ol.title": "Senarai tertib", - "pad.toolbar.ul.title": "Senarai tak tertib", + "pad.toolbar.strikethrough.title": "Garis lorek (Ctrl+5)", + "pad.toolbar.ol.title": "Senarai tertib (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Senarai tak tertib (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Engsot ke dalam (TAB)", "pad.toolbar.unindent.title": "Engsot ke luar (Shift + TAB)", "pad.toolbar.undo.title": "Buat asal (Ctrl-Z)", "pad.toolbar.redo.title": "Buat semula (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Padamkan Warna Pengarang", + "pad.toolbar.clearAuthorship.title": "Padamkan Warna Pengarang (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Import/Eksport dari/ke format-format fail berbeza", "pad.toolbar.timeslider.title": "Gelangsar masa", "pad.toolbar.savedRevision.title": "Simpan Semakan", @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Anda hanya boleh mengimport dari format teks biasa atau html. Untuk ciri-ciri import yang lebih maju, sila memasang abiword.", "pad.modals.connected": "Bersambung.", "pad.modals.reconnecting": "Bersambung semula dengan pad anda...", diff --git a/src/locales/nap.json b/src/locales/nap.json new file mode 100644 index 000000000..ffc7b740b --- /dev/null +++ b/src/locales/nap.json @@ -0,0 +1,70 @@ +{ + "@metadata": { + "authors": [ + "Chelin" + ] + }, + "index.newPad": "Novo Pad", + "index.createOpenPad": "o crià o apre nu Pad cu 'o nomme:", + "pad.toolbar.bold.title": "Grassetto (Ctrl-B)", + "pad.toolbar.italic.title": "Cursivo (Ctrl-I)", + "pad.toolbar.underline.title": "Sottolineato (Ctrl-U)", + "pad.toolbar.strikethrough.title": "Barrato (Ctrl+5)", + "pad.toolbar.ol.title": "Ennece nummerato (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Ennece puntato (Ctrl+Shift+L)", + "pad.toolbar.indent.title": "Rientro (TAB)", + "pad.toolbar.unindent.title": "Riduce rientro (Shift+TAB)", + "pad.toolbar.undo.title": "Annulla (Ctrl-Z)", + "pad.toolbar.redo.title": "Ripete (Ctrl-Y)", + "pad.toolbar.clearAuthorship.title": "Elimina 'e culure ca 'ndicanno 'e auture (Ctrl+Shift+C)", + "pad.toolbar.import_export.title": "'Mporta/esporta 'e/a diverse furmate 'e file", + "pad.toolbar.timeslider.title": "Presentazzione cronologgia", + "pad.toolbar.savedRevision.title": "Sarva revisione", + "pad.toolbar.settings.title": "Mpustaziune", + "pad.colorpicker.save": "Sarva", + "pad.colorpicker.cancel": "Canciella", + "pad.loading": "Carecamiento 'n curso…", + "pad.passwordRequired": "Pe' accede a chisto Pad è necessaria 'na password", + "pad.permissionDenied": "Nun se dispunne d\"e permisse necessare pe' accede a chisto Pad", + "pad.wrongPassword": "'A password è sbagliata", + "pad.settings.padSettings": "Mpostazzione d\"o pad", + "pad.settings.fontType.normal": "Nurmale", + "pad.importExport.exporthtml": "HTML", + "pad.importExport.exportpdf": "PDF", + "pad.importExport.exportopen": "ODF (Open Document Format)", + "pad.modals.connected": "Cunnesso.", + "pad.modals.reconnecting": "Ricunnessione ô pad 'n curso...", + "pad.modals.forcereconnect": "Forza 'a ricunnessione", + "pad.modals.userdup": "Aprito 'n n'ata fenesta", + "pad.modals.unauth": "Nun autorizzato", + "pad.modals.deleted": "Canciellato.", + "timeslider.pageTitle": "Cronologgia {{appTitle}}", + "timeslider.toolbar.returnbutton": "Ritorna ô Pad", + "timeslider.toolbar.authors": "Auture:", + "timeslider.toolbar.authorsList": "Nisciun autore", + "timeslider.toolbar.exportlink.title": "Espurta", + "timeslider.exportCurrent": "Espurta 'a verzione corrente comme:", + "timeslider.version": "Verzione {{version}}", + "timeslider.saved": "Sarvato {{day}} {{month}} {{year}}", + "timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}", + "timeslider.month.january": "Jennaro", + "timeslider.month.february": "Frevaro", + "timeslider.month.march": "Màrzo", + "timeslider.month.april": "Abbrile", + "timeslider.month.may": "Màjo", + "timeslider.month.june": "Giùgno", + "timeslider.month.july": "Luglio", + "timeslider.month.august": "Aùsto", + "timeslider.month.september": "Settembre", + "timeslider.month.october": "Ottovre", + "timeslider.month.november": "Nuvembre", + "timeslider.month.december": "Dicembre", + "timeslider.unnamedauthors": "{{num}} {[plural(num) one: autore, other: auture ]} senza nomme", + "pad.userlist.entername": "'Nserisce 'o tujo nomme", + "pad.userlist.unnamed": "senza nomme", + "pad.userlist.guest": "Ospite", + "pad.userlist.deny": "Nega", + "pad.userlist.approve": "Appruva", + "pad.impexp.importbutton": "'Mpurta mmo", + "pad.impexp.importing": "'Mpurtazzione 'n curso..." +} diff --git a/src/locales/nb.json b/src/locales/nb.json index 0620d2b43..a1b3a5ca7 100644 --- a/src/locales/nb.json +++ b/src/locales/nb.json @@ -10,14 +10,14 @@ "pad.toolbar.bold.title": "Fet (Ctrl-B)", "pad.toolbar.italic.title": "Kursiv (Ctrl-I)", "pad.toolbar.underline.title": "Understreking (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Gjennomstreking", - "pad.toolbar.ol.title": "Nummerert liste", - "pad.toolbar.ul.title": "Punktliste", + "pad.toolbar.strikethrough.title": "Gjennomstreking (Ctrl+5)", + "pad.toolbar.ol.title": "Nummerert liste (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Punktliste (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Innrykk (TAB)", "pad.toolbar.unindent.title": "Rykk ut (Shift+TAB)", "pad.toolbar.undo.title": "Angre (Ctrl-Z)", "pad.toolbar.redo.title": "Gjør omigjen (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Fjern forfatterfarger", + "pad.toolbar.clearAuthorship.title": "Fjern forfatterfarger (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importer/eksporter fra/til forskjellige filformater", "pad.toolbar.timeslider.title": "Tidslinje", "pad.toolbar.savedRevision.title": "Lagre revisjoner", @@ -50,7 +50,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Du kan bare importere fra ren tekst eller HTML-formater. For mer avanserte importfunksjoner, installer abiword.", "pad.modals.connected": "Tilkoblet.", "pad.modals.reconnecting": "Kobler til din pad på nytt...", diff --git a/src/locales/nds.json b/src/locales/nds.json index 451a02112..dfb922782 100644 --- a/src/locales/nds.json +++ b/src/locales/nds.json @@ -50,7 +50,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Se köönt blots wat vun Kloortext oder HTML-Stücken röverhalen. Mit köönt Se ok anner Saken röverhalen. Dorför mööt Se bidde abiword inrichten.", "pad.modals.connected": "Verbindung steiht.", "pad.modals.reconnecting": "En Verbindung wedder opboen ...", diff --git a/src/locales/ne.json b/src/locales/ne.json index 371948848..b380526ed 100644 --- a/src/locales/ne.json +++ b/src/locales/ne.json @@ -48,7 +48,6 @@ "pad.importExport.exportword": "माइक्रोसफ्ट वर्ड", "pad.importExport.exportpdf": "पिडिएफ", "pad.importExport.exportopen": "ओडिएफ(खुल्ला कागजात ढाँचा)", - "pad.importExport.exportdokuwiki": "डकुविकि", "pad.modals.connected": "जोडीएको।", "pad.modals.reconnecting": "तपाईँको प्याडमा पुन: जडान गर्दै", "pad.modals.forcereconnect": "जडानको लागि जोडगर्ने", diff --git a/src/locales/nl.json b/src/locales/nl.json index 5a9d9fba1..ed69527e3 100644 --- a/src/locales/nl.json +++ b/src/locales/nl.json @@ -1,7 +1,9 @@ { "@metadata": { "authors": [ - "Siebrand" + "Siebrand", + "Macofe", + "Robin0van0der0vliet" ] }, "index.newPad": "Nieuw pad", @@ -9,14 +11,14 @@ "pad.toolbar.bold.title": "Vet (Ctrl-B)", "pad.toolbar.italic.title": "Cursief (Ctrl-I)", "pad.toolbar.underline.title": "Onderstrepen (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Doorhalen", - "pad.toolbar.ol.title": "Geordende lijst", - "pad.toolbar.ul.title": "Ongeordende lijst", + "pad.toolbar.strikethrough.title": "Doorhalen (Ctrl+5)", + "pad.toolbar.ol.title": "Geordende lijst (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Ongeordende lijst (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Inspringen (Tab)", "pad.toolbar.unindent.title": "Inspringing verkleinen (Shift+Tab)", "pad.toolbar.undo.title": "Ongedaan maken (Ctrl-Z)", "pad.toolbar.redo.title": "Opnieuw uitvoeren (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Kleuren auteurs wissen", + "pad.toolbar.clearAuthorship.title": "Kleuren auteurs wissen (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Naar/van andere opmaak exporteren/importeren", "pad.toolbar.timeslider.title": "Tijdlijn", "pad.toolbar.savedRevision.title": "Versie opslaan", @@ -49,7 +51,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "Pdf", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "U kunt alleen importeren vanuit platte tekst of een HTML-opmaak. Installeer abiword om meer geavanceerde importmogelijkheden te krijgen.", "pad.modals.connected": "Verbonden.", "pad.modals.reconnecting": "Opnieuw verbinding maken met uw pad...", diff --git a/src/locales/nn.json b/src/locales/nn.json index 104a17dc6..dc6368ed9 100644 --- a/src/locales/nn.json +++ b/src/locales/nn.json @@ -48,7 +48,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Du kan berre importera frå rein tekst- eller HTML-format. Ver venleg og installer Abiword om du treng meir avanserte importfunksjonar.", "pad.modals.connected": "Tilkopla.", "pad.modals.reconnecting": "Gjenopprettar tilkoplinga til blokka di …", diff --git a/src/locales/oc.json b/src/locales/oc.json index 5921f4ff5..54a375bab 100644 --- a/src/locales/oc.json +++ b/src/locales/oc.json @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Podètz pas importar que de formats tèxte brut o html. Per de foncionalitats d'importacion mai evoluadas, installatz abiword.", "pad.modals.connected": "Connectat.", "pad.modals.reconnecting": "Reconnexion cap a vòstre Pad...", diff --git a/src/locales/os.json b/src/locales/os.json index 109dada77..941fe2b8e 100644 --- a/src/locales/os.json +++ b/src/locales/os.json @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Дӕ бон у импорт кӕнын ӕрмӕст хуымӕтӕг текст кӕнӕ html форматӕй. Лӕмбынӕг импорты миниуджытӕн, дӕ хорзӕхӕй, сӕвӕр abiword.", "pad.modals.connected": "Иугонд.", "pad.modals.reconnecting": "Дӕ документмӕ ногӕй иугонд цӕуы..", diff --git a/src/locales/pa.json b/src/locales/pa.json index 9a38bef67..9e154e36d 100644 --- a/src/locales/pa.json +++ b/src/locales/pa.json @@ -1,7 +1,8 @@ { "@metadata": { "authors": [ - "Aalam" + "Aalam", + "Babanwalia" ] }, "index.newPad": "ਨਵਾਂ ਪੈਡ", @@ -12,7 +13,8 @@ "pad.toolbar.strikethrough.title": "ਵਿੰਨ੍ਹੋ ਵਿਨੋ", "pad.toolbar.ol.title": "ਲੜੀਵਾਰ ਲਿਸਟ", "pad.toolbar.ul.title": "ਬਿਨ-ਲੜੀਬੱਧ ਸੂਚੀ", - "pad.toolbar.indent.title": "ਹਾਸ਼ੀਏ ਤੋਂ ਦੂਰ", + "pad.toolbar.indent.title": "ਹਾਸ਼ੀਏ ਤੋਂ ਪਰ੍ਹੇ (ਟੈਬ)", + "pad.toolbar.unindent.title": "ਹਾਸ਼ੀਏ ਵੱਲ (ਸ਼ਿਫ਼ਟ+ਟੈਬ)", "pad.toolbar.undo.title": "ਵਾਪਸ (Ctrl-Z)", "pad.toolbar.redo.title": "ਪਰਤਾਓ (Ctrl-Y)", "pad.toolbar.clearAuthorship.title": "ਪਰਮਾਣਕਿਤਾ ਰੰਗ ਸਾਫ਼ ਕਰੋ", @@ -22,7 +24,7 @@ "pad.toolbar.settings.title": "ਸੈਟਿੰਗ", "pad.toolbar.embed.title": "ਇਹ ਪੈਡ ਸਾਂਝਾ ਤੇ ਇੰਬੈੱਡ ਕਰੋ", "pad.toolbar.showusers.title": "ਇਹ ਪੈਡ ਉੱਤੇ ਯੂਜ਼ਰ ਵੇਖਾਓ", - "pad.colorpicker.save": "ਸੰਭਾਲੋ", + "pad.colorpicker.save": "ਸਾਂਭੋ", "pad.colorpicker.cancel": "ਰੱਦ ਕਰੋ", "pad.loading": "…ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ", "pad.passwordRequired": "ਇਹ ਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਤੁਹਾਨੂੰ ਪਾਸਵਰਡ ਚਾਹੀਦਾ ਹੈ", @@ -31,6 +33,7 @@ "pad.settings.padSettings": "ਪੈਡ ਸੈਟਿੰਗ", "pad.settings.myView": "ਮੇਰੀ ਝਲਕ", "pad.settings.stickychat": "ਹਮੇਸ਼ਾ ਸਕਰੀਨ ਉੱਤੇ ਗੱਲ ਕਰੋ", + "pad.settings.colorcheck": "ਲੇਖਕੀ ਰੰਗ", "pad.settings.linenocheck": "ਲਾਈਨ ਨੰਬਰ", "pad.settings.rtlcheck": "ਸਮੱਗਰੀ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਪੜ੍ਹਨੀ ਹੈ?", "pad.settings.fontType": "ਫੋਂਟ ਕਿਸਮ:", @@ -47,19 +50,31 @@ "pad.importExport.exportword": "ਮਾਈਕਰੋਸਾਫਟ ਵਰਡ", "pad.importExport.exportpdf": "ਪੀਡੀਐਫ", "pad.importExport.exportopen": "ODF (ਓਪਨ ਡੌਕੂਮੈਂਟ ਫਾਰਮੈਟ)", - "pad.importExport.exportdokuwiki": "DokuWiki", + "pad.importExport.abiword.innerHTML": "ਤੁਸੀਂ ਸਿਰਫ਼ ਸਾਦੀਆਂ ਲਿਖਤੀ ਜਾਂ ਐੱਚ.ਟੀ.ਐੱਮ.ਐੱਲ. ਰੂਪ-ਰੇਖਾਵਾਂ ਤੋਂ ਦਰਾਮਦ ਕਰ ਸਕਦੇ ਹੋ। ਹੋਰ ਉੱਨਤ ਦਰਾਮਦੀ ਗੁਣਾਂ ਵਾਸਤੇ ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਐਬੀਵਰਡ ਥਾਪੋ।", "pad.modals.connected": "ਕੁਨੈਕਟ ਹੈ।", "pad.modals.reconnecting": "..ਤੁਹਾਡੇ ਪੈਡ ਨਾਲ ਮੁੜ-ਕੁਨੈਕਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ", "pad.modals.forcereconnect": "ਧੱਕੇ ਨਾਲ ਮੁੜ-ਕੁਨੈਕਟ ਕਰੋ", "pad.modals.userdup": "ਹੋਰ ਵਿੰਡੋ ਵਿੱਚ ਖੁੱਲ੍ਹਿਆ ਹੈ", + "pad.modals.userdup.explanation": "ਇਹ ਪੈਡ ਇਸ ਕੰਪਿਊਟਰ 'ਤੇ ਇੱਕ ਤੋਂ ਵੱਧ ਫਰੋਲੂ ਬਾਰੀ ਵਿੱਚ ਖੁੱਲ੍ਹਿਆ ਜਾਪਦਾ ਹੈ।", + "pad.modals.userdup.advice": "ਸਗੋਂ ਇਹ ਬਾਰੀ ਵਰਤਣ ਵਾਸਤੇ ਮੁੜ ਜੁੜੋ।", "pad.modals.unauth": "ਪਰਮਾਣਿਤ ਨਹੀਂ ਹੈ", + "pad.modals.unauth.explanation": "ਇਹ ਸਫ਼ਾ ਵੇਖਦੇ-ਵੇਖਦੇ ਤੁਹਾਨੂੰ ਮਿਲ਼ੀਆਂ ਇਜਾਜ਼ਤਾਂ ਬਦਲ ਗਈਆਂ ਹਨ। ਮੁੜ ਜੁੜਨ ਦੀ ਕੋਸ਼ਿਸ਼ ਕਰੋ।", + "pad.modals.looping.explanation": "ਇੱਕਰੂਪੀ ਸਰਵਰ ਨਾਲ਼ ਸੰਚਾਰੀ ਔਕੜਾਂ ਆ ਰਹੀਆਂ ਹਨ।", + "pad.modals.looping.cause": "ਸ਼ਾਇਦ ਤੁਸੀਂ ਕਿਸੇ ਅਢੁਕਵੀਂ ਸੁਰੱਖਿਆ ਪ੍ਰਨਾਲ਼ੀ ਜਾਂ ਪ੍ਰਾਕਸੀ ਰਾਹੀਂ ਜੁੜੇ ਹੋ।", "pad.modals.initsocketfail": "ਸਰਵਰ ਪਹੁੰਚ ਵਿੱਚ ਨਹੀਂ ਹੈ।", + "pad.modals.initsocketfail.explanation": "ਇੱਕਰੂਪੀ ਸਰਵਰ ਨਾਲ਼ ਰਾਬਤਾ ਨਹੀਂ ਬਣ ਸਕਿਆ।", + "pad.modals.initsocketfail.cause": "ਇਹ ਸ਼ਾਇਦ ਤੁਹਾਡੇ ਫਰੋਲੂ ਜਾਂ ਇੰਟਰਨੈੱਟ ਜੋੜ ਦੀਆਂ ਗੁੰਝਲਾਂ ਕਰਕੇ ਹੋ ਰਿਹਾ ਹੈ।", "pad.modals.slowcommit.explanation": "ਸਰਵਰ ਜਵਾਬ ਨਹੀਂ ਦੇ ਰਿਹਾ ਹੈ।", "pad.modals.slowcommit.cause": "ਇਹ ਨੈੱਟਵਰਕ ਕੁਨੈਕਸ਼ਨ ਨਾਲ ਸਮੱਸਿਆ ਕਰਕੇ ਹੋ ਸਕਦਾ ਹੈ।", + "pad.modals.badChangeset.explanation": "ਤੁਹਾਡੇ ਵੱਲੋਂ ਕੀਤੀ ਇੱਕ ਸੋਧ ਨੂੰ ਇੱਕਰੂਪੀ ਸਰਵਰ ਨੇ ਗ਼ੈਰ-ਕਨੂੰਨੀ ਕਰਾਰ ਦਿੱਤਾ ਹੈ।", + "pad.modals.badChangeset.cause": "ਇਹ ਸਿਸਟਮ ਦੀ ਕਿਸੇ ਗ਼ਲਤ ਨੁਹਾਰ ਜਾਂ ਕੋਈ ਹੋਰ ਅਣਸੋਚੇ ਵਤੀਰਾ ਕਰਕੇ ਵਾਪਰ ਸਕਦਾ ਹੈ। ਜੇਕਰ ਤੁਹਾਨੂੰ ਇਹ ਇੱਕ ਦੋਸ਼ ਲੱਗਦਾ ਹੈ ਤਾਂ ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਆਪਣੇ ਸਿਸਟਮ ਦੇ ਪ੍ਰਬੰਧਕ ਨਾਲ਼ ਰਾਬਤਾ ਬਣਾਉ। ਸੋਧ ਜਾਰੀ ਰੱਖਣ ਵਾਸਤੇ ਮੁੜ ਜੁੜੋ।", + "pad.modals.corruptPad.explanation": "ਜਿਸ ਪੈਡ ਤੱਕ ਤੁਸੀਂ ਪਹੁੰਚਣਾ ਚਾਹੁੰਦੇ ਹੋ, ਉਹ ਖੋਟਾ ਹੈ।", + "pad.modals.corruptPad.cause": "ਇਹ ਸਿਸਟਮ ਦੀ ਕਿਸੇ ਗ਼ਲਤ ਨੁਹਾਰ ਜਾਂ ਕੋਈ ਹੋਰ ਅਣਸੋਚੇ ਵਤੀਰਾ ਕਰਕੇ ਵਾਪਰ ਸਕਦਾ ਹੈ। ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਆਪਣੇ ਸਿਸਟਮ ਦੇ ਪ੍ਰਬੰਧਕ ਨਾਲ਼ ਰਾਬਤਾ ਬਣਾਉ।", "pad.modals.deleted": "ਹਟਾਇਆ।", "pad.modals.deleted.explanation": "ਇਹ ਪੈਡ ਹਟਾਇਆ ਜਾ ਚੁੱਕਾ ਹੈ।", "pad.modals.disconnected": "ਤੁਸੀਂ ਡਿਸ-ਕੁਨੈਕਟ ਹੋ ਚੁੱਕੇ ਹੋ।", "pad.modals.disconnected.explanation": "ਸਰਵਰ ਨਾਲ ਕੁਨੈਕਸ਼ਨ ਖਤਮ ਹੋਇਆ ਹੈ", + "pad.modals.disconnected.cause": "ਸਰਵਰ ਨਾਮੌਜੂਦ ਹੋ ਸਕਦਾ ਹੈ। ਜੇਕਰ ਇਹ ਹੁੰਦਾ ਰਹੇ ਤਾਂ ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਸੇਵਾ ਪ੍ਰਬੰਧਕ ਨੂੰ ਖ਼ਬਰ ਕਰੋ।", "pad.share": "ਇਹ ਪੈਡ ਸਾਂਝਾ ਕਰੋ", "pad.share.readonly": "ਕੇਵਲ ਪੜ੍ਹਨ ਲਈ", "pad.share.link": "ਲਿੰਕ", @@ -88,7 +103,7 @@ "timeslider.month.october": "ਅਕਤੂਬਰ", "timeslider.month.november": "ਨਵੰਬਰ", "timeslider.month.december": "ਦਸੰਬਰ", - "timeslider.unnamedauthors": "{{num}} ਬੇਨਾਮ ਲੇਖਕ", + "timeslider.unnamedauthors": "{{num}} ਬੇਨਾਮ {[plural(num) one: ਲੇਖਕ, other: ਲੇਖਕ ]}", "pad.savedrevs.marked": "ਇਹ ਰੀਵਿਜ਼ਨ ਨੂੰ ਹੁਣ ਸੰਭਾਲੇ ਹੋਏ ਰੀਵਿਜ਼ਨ ਵਜੋਂ ਮੰਨਿਆ ਗਿਆ ਹੈ", "pad.userlist.entername": "ਆਪਣਾ ਨਾਂ ਦਿਉ", "pad.userlist.unnamed": "ਬੇਨਾਮ", @@ -98,7 +113,10 @@ "pad.editbar.clearcolors": "ਪੂਰੇ ਦਸਾਤਵੇਜ਼ ਉੱਤੇ ਪਰਮਾਣਕਿਤਾ ਰੰਗ ਸਾਫ਼ ਕਰਨੇ ਹਨ?", "pad.impexp.importbutton": "ਹੁਣੇ ਇੰਪੋਰਟ ਕਰੋ", "pad.impexp.importing": "...ਇੰਪੋਰਟ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ", + "pad.impexp.confirmimport": "ਕੋਈ ਫ਼ਾਈਲ ਦਰਾਮਦ ਕਾਰਨ ਨਾਲ਼ ਪੈਡ ਦੀ ਮੌਜੂਦਾ ਲਿਖਤ ਉੱਤੇ ਲਿਖਿਆ ਜਾਵੇਗਾ। ਕੀ ਤੁਸੀਂ ਸੱਚੀਂ ਇਹ ਕਰਨਾ ਚਾਹੁੰਦੇ ਹੋ?", + "pad.impexp.convertFailed": "ਅਸੀਂ ਇਸ ਫ਼ਾਈਲ ਦੀ ਦਰਾਮਦ ਨਹੀਂ ਕਰ ਸਕੇ। ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਕੋਈ ਵੱਖਰੀ ਦਸਤਾਵੇਜ਼ੀ ਰੂਪ-ਰੇਖਾ ਵਰਤੋ ਜਾਂ ਹੱਥੀਂ ਨਕਲ-ਚੇਪੀ ਕਰੋ।", "pad.impexp.uploadFailed": "ਅੱਪਲੋਡ ਲਈ ਫੇਲ੍ਹ ਹੈ, ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ ਜੀ।", "pad.impexp.importfailed": "ਇੰਪੋਰਟ ਫੇਲ੍ਹ ਹੈ", - "pad.impexp.copypaste": "ਕਾਪੀ ਕਰੋ ਚੇਪੋ ਜੀ" + "pad.impexp.copypaste": "ਕਾਪੀ ਕਰੋ ਚੇਪੋ ਜੀ", + "pad.impexp.exportdisabled": "{{type}} ਰੂਪ-ਰੇਖਾ ਵਜੋਂ ਬਰਾਮਦ ਕਰਨਾ ਬੰਦ ਹੈ। ਵੇਰਵੇ ਵਾਸਤੇ ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਆਪਣੇ ਸਿਸਟਮ ਦੇ ਪ੍ਰਬੰਧਕ ਨਾਲ਼ ਰਾਬਤਾ ਬਣਾਉ।" } diff --git a/src/locales/pl.json b/src/locales/pl.json index 9e7be2fbe..7e68ca845 100644 --- a/src/locales/pl.json +++ b/src/locales/pl.json @@ -4,7 +4,8 @@ "Rezonansowy", "Ty221", "WTM", - "Woytecr" + "Woytecr", + "Macofe" ] }, "index.newPad": "Nowy dokument", @@ -19,7 +20,7 @@ "pad.toolbar.unindent.title": "Wcięcie (Shift + TAB)", "pad.toolbar.undo.title": "Cofnij (Ctrl-Z)", "pad.toolbar.redo.title": "Ponów (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Usuń kolory autorów", + "pad.toolbar.clearAuthorship.title": "Usuń kolory autorów (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Import/eksport z/do różnych formatów plików", "pad.toolbar.timeslider.title": "Oś czasu", "pad.toolbar.savedRevision.title": "Zapisz wersję", @@ -52,7 +53,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Możesz importować pliki tylko w formacie zwykłego tekstu lub html. Aby umożliwić bardziej zaawansowane funkcje importu, zainstaluj abiword.", "pad.modals.connected": "Połączony.", "pad.modals.reconnecting": "Ponowne łączenie z dokumentem...", diff --git a/src/locales/ps.json b/src/locales/ps.json index 760044127..1a57e76af 100644 --- a/src/locales/ps.json +++ b/src/locales/ps.json @@ -32,7 +32,6 @@ "pad.importExport.exportword": "مايکروسافټ ورډ", "pad.importExport.exportpdf": "پي ډي اېف", "pad.importExport.exportopen": "ODF (اوپن ډاکومنټ فارمټ)", - "pad.importExport.exportdokuwiki": "ډوکوويکي", "pad.modals.connected": "اړيکمن شو.", "pad.modals.slowcommit.explanation": "پالنگر ځواب نه وايي.", "pad.modals.slowcommit.cause": "دا کېدای شي د جال د اړيکتيايي ستونزو په سبب وي.", diff --git a/src/locales/pt-br.json b/src/locales/pt-br.json index a687b22a4..204d77929 100644 --- a/src/locales/pt-br.json +++ b/src/locales/pt-br.json @@ -7,7 +7,10 @@ "TheGabrielZaum", "Titoncio", "Tuliouel", - "Rafaelff" + "Rafaelff", + "Dianakc", + "Macofe", + "Rodrigo codignoli" ] }, "index.newPad": "Nova Nota", @@ -15,14 +18,14 @@ "pad.toolbar.bold.title": "Negrito (Ctrl-B)", "pad.toolbar.italic.title": "Itálico (Ctrl-I)", "pad.toolbar.underline.title": "Sublinhar (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Tachado", - "pad.toolbar.ol.title": "Lista ordenada", - "pad.toolbar.ul.title": "Lista não ordenada", + "pad.toolbar.strikethrough.title": "Tachado (Ctrl+5)", + "pad.toolbar.ol.title": "Lista ordenada (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Lista não ordenada (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Aumentar Recuo (TAB)", "pad.toolbar.unindent.title": "Diminuir Recuo (Shift+TAB)", "pad.toolbar.undo.title": "Desfazer (Ctrl-Z)", "pad.toolbar.redo.title": "Refazer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Limpar as cores de identificação de autoria", + "pad.toolbar.clearAuthorship.title": "Limpar as cores de identificação de autoria (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importar/Exportar de/para diferentes formatos de arquivo", "pad.toolbar.timeslider.title": "Linha do tempo", "pad.toolbar.savedRevision.title": "Salvar revisão", @@ -55,7 +58,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Você só pode importar de formatos de texto puro ou html. Para recursos de importação mais avançados instale o abiword.", "pad.modals.connected": "Conectado.", "pad.modals.reconnecting": "Reconectando à sua nota...", @@ -83,7 +85,7 @@ "pad.modals.disconnected.cause": "O servidor pode estar indisponível. Por favor, notifique o administrador caso isso continue.", "pad.share": "Compartilhar esta nota", "pad.share.readonly": "Somente leitura", - "pad.share.link": "Ligação", + "pad.share.link": "Link", "pad.share.emebdcode": "Incorporar o URL", "pad.chat": "Bate-papo", "pad.chat.title": "Abrir o bate-papo desta nota.", diff --git a/src/locales/pt.json b/src/locales/pt.json index 949bb7bc7..c7cfcb5cf 100644 --- a/src/locales/pt.json +++ b/src/locales/pt.json @@ -5,7 +5,8 @@ "Luckas", "Tuliouel", "Waldir", - "Imperadeiro98" + "Imperadeiro98", + "Macofe" ] }, "index.newPad": "Nova Nota", @@ -13,14 +14,14 @@ "pad.toolbar.bold.title": "Negrito (Ctrl-B)", "pad.toolbar.italic.title": "Itálico (Ctrl-I)", "pad.toolbar.underline.title": "Sublinhado (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Riscar", - "pad.toolbar.ol.title": "Lista ordenada", - "pad.toolbar.ul.title": "Lista desordenada", + "pad.toolbar.strikethrough.title": "Riscar (Ctrl+5)", + "pad.toolbar.ol.title": "Lista ordenada (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Lista desordenada (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Avançar (TAB)", "pad.toolbar.unindent.title": "Recuar (Shift+TAB)", "pad.toolbar.undo.title": "Desfazer (Ctrl-Z)", "pad.toolbar.redo.title": "Refazer (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Limpar cores de autoria", + "pad.toolbar.clearAuthorship.title": "Limpar cores de autoria (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importar/exportar de/para diferentes formatos de ficheiro", "pad.toolbar.timeslider.title": "Linha de tempo", "pad.toolbar.savedRevision.title": "Salvar revisão", @@ -53,7 +54,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.modals.connected": "Ligado.", "pad.modals.reconnecting": "Reconectando-se ao seu bloco…", "pad.modals.forcereconnect": "Forçar reconexão", @@ -71,6 +71,7 @@ "pad.modals.disconnected.cause": "O servidor pode estar indisponível. Por favor, notifique o administrador de serviço se isto continuar a acontecer.", "pad.share": "Compartilhar este pad", "pad.share.readonly": "Somente para leitura", + "pad.share.link": "Ligação", "pad.chat": "Bate-papo", "pad.chat.title": "Abrir o bate-papo para este pad.", "pad.chat.loadmessages": "Carregar mais mensagens", diff --git a/src/locales/ru.json b/src/locales/ru.json index cd030bad3..f96f2338c 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -13,14 +13,14 @@ "pad.toolbar.bold.title": "полужирный (Ctrl-B)", "pad.toolbar.italic.title": "курсив (Ctrl-I)", "pad.toolbar.underline.title": "подчёркивание (Ctrl-U)", - "pad.toolbar.strikethrough.title": "зачёркивание", - "pad.toolbar.ol.title": "Упорядоченный список", - "pad.toolbar.ul.title": "Неупорядоченный список", + "pad.toolbar.strikethrough.title": "Зачёркивание (Ctrl+5)", + "pad.toolbar.ol.title": "Упорядоченный список (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Неупорядоченный список (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Отступ (TAB)", "pad.toolbar.unindent.title": "Выступ (Shift+TAB)", "pad.toolbar.undo.title": "Отменить (Ctrl-Z)", "pad.toolbar.redo.title": "Вернуть (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Очистить цвета документа", + "pad.toolbar.clearAuthorship.title": "Очистить цвета документа (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Импорт/экспорт с использованием различных форматов файлов", "pad.toolbar.timeslider.title": "Шкала времени", "pad.toolbar.savedRevision.title": "Сохранить версию", @@ -53,7 +53,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (документ OpenOffice)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Вы можете импортировать только из обычного текста или HTML. Для более продвинутых функций импорта, пожалуйста, установите AbiWord.", "pad.modals.connected": "Подключен.", "pad.modals.reconnecting": "Повторное подключение к вашему документу", diff --git a/src/locales/sco.json b/src/locales/sco.json index efcb187a1..f7b018244 100644 --- a/src/locales/sco.json +++ b/src/locales/sco.json @@ -49,7 +49,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Ye can yinly import fae plain tex or HTML formats. Fer mair advanced import features please install abiword.", "pad.modals.connected": "Connected.", "pad.modals.reconnecting": "Reconnectin til yer pad..", diff --git a/src/locales/sk.json b/src/locales/sk.json index 8f376926d..02c5c978b 100644 --- a/src/locales/sk.json +++ b/src/locales/sk.json @@ -51,7 +51,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Importovať môžete len čistý text alebo HTML. Pre pokročilejšie funkcie importu prosím nainštalujte „Abiword“.", "pad.modals.connected": "Pripojené.", "pad.modals.reconnecting": "Opätovné pripájanie k vášmu Padu...", diff --git a/src/locales/sl.json b/src/locales/sl.json index 8e57cffa8..41a6ce764 100644 --- a/src/locales/sl.json +++ b/src/locales/sl.json @@ -10,14 +10,14 @@ "pad.toolbar.bold.title": "Krepko (Ctrl-B)", "pad.toolbar.italic.title": "Ležeče (Ctrl-I)", "pad.toolbar.underline.title": "Podčrtano (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Prečrtano", - "pad.toolbar.ol.title": "Oštevilčen seznam", - "pad.toolbar.ul.title": "Vrstični seznam", + "pad.toolbar.strikethrough.title": "Prečrtano (Ctrl+5)", + "pad.toolbar.ol.title": "Oštevilčen seznam (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Neurejen seznam (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Zamik desno (TAB)", "pad.toolbar.unindent.title": "Zamik levo (Shift+TAB)", "pad.toolbar.undo.title": "Razveljavi (Ctrl-Z)", "pad.toolbar.redo.title": "Ponovno uveljavi (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Počisti barvo avtorstva", + "pad.toolbar.clearAuthorship.title": "Počisti barvo avtorstva (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Izvozi/Uvozi različne oblike zapisov", "pad.toolbar.timeslider.title": "Drsnik zgodovine", "pad.toolbar.savedRevision.title": "Shrani predelavo", @@ -50,7 +50,6 @@ "pad.importExport.exportword": "DOC (zapis Microsoft Word)", "pad.importExport.exportpdf": "PDF (zapis Acrobat PDF)", "pad.importExport.exportopen": "ODF (zapis Open Document)", - "pad.importExport.exportdokuwiki": "DokuWiki (zapis DokuWiki)", "pad.importExport.abiword.innerHTML": "Uvoziti je mogoče le običajno neoblikovano besedilo in zapise HTML. Za naprednejše zmožnosti namestite program Abiword.", "pad.modals.connected": "Povezano.", "pad.modals.reconnecting": "Poteka povezovanje z dokumentom ...", diff --git a/src/locales/sq.json b/src/locales/sq.json index 54e760679..6374ea62b 100644 --- a/src/locales/sq.json +++ b/src/locales/sq.json @@ -9,17 +9,17 @@ "pad.toolbar.bold.title": "Të trasha (Ctrl-B)", "pad.toolbar.italic.title": "Të pjerrëta (Ctrl-I)", "pad.toolbar.underline.title": "Të nënvizuara (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Hequrvije", - "pad.toolbar.ol.title": "Listë e renditur", - "pad.toolbar.ul.title": "Listë e parenditur", - "pad.toolbar.indent.title": "Brendazi", - "pad.toolbar.unindent.title": "Jashtazi", + "pad.toolbar.strikethrough.title": "Hequrvije (Ctrl+5)", + "pad.toolbar.ol.title": "Listë e renditur (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Listë e parenditur (Ctrl+Shift+L)", + "pad.toolbar.indent.title": "Brendazi (TAB)", + "pad.toolbar.unindent.title": "Jashtazi (Shift+TAB)", "pad.toolbar.undo.title": "Zhbëje (Ctrl-Z)", "pad.toolbar.redo.title": "Ribëje (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Hiq Ngjyra Autorësish", + "pad.toolbar.clearAuthorship.title": "Hiqju Ngjyra Autorësish (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importoni/Eksportoni nga/në formate të tjera kartelash", "pad.toolbar.timeslider.title": "Rrjedha kohore", - "pad.toolbar.savedRevision.title": "Ruaje Rishikin", + "pad.toolbar.savedRevision.title": "Ruaje Rishikimin", "pad.toolbar.settings.title": "Rregullime", "pad.toolbar.embed.title": "Ndajeni me të tjerët dhe Trupëzojeni këtë bllok", "pad.toolbar.showusers.title": "Shfaq përdoruesit në këtë bllok", @@ -49,14 +49,13 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Mund të importoni vetëm prej formati tekst i thjeshtë ose html. Për veçori më të përparuara importimi, ju lutemi, instaloni Abiword-in.", "pad.modals.connected": "I lidhur.", "pad.modals.reconnecting": "Po rilidheni te blloku juaj..", "pad.modals.forcereconnect": "Rilidhje e detyruar", "pad.modals.userdup": "Hapur në një tjetër dritare", "pad.modals.userdup.explanation": "Ky bllok duket se gjendet i hapur në më shumë se një dritare shfletuesi në këtë kompjuter.", - "pad.modals.userdup.advice": "Rilidhu që të përdoret kjo dritare, më mirë.", + "pad.modals.userdup.advice": "Rilidhuni që të përdoret kjo dritare.", "pad.modals.unauth": "I paautorizuar", "pad.modals.unauth.explanation": "Ndërkohë që shihnit këtë dritare, lejet tuaja kanë ndryshuar. Provoni të rilidheni.", "pad.modals.looping.explanation": "Ka probleme komunikimi me shërbyesin e njëkohësimit.", @@ -66,14 +65,14 @@ "pad.modals.initsocketfail.cause": "Ka gjasa që kjo vjen për shkak të një problemi me shfletuesin tuaj ose lidhjen tuaj në internet.", "pad.modals.slowcommit.explanation": "Shërbyesi nuk po përgjigjet.", "pad.modals.slowcommit.cause": "Kjo mund të vijë për shkak problemesh lidhjeje me rrjetin.", - "pad.modals.badChangeset.explanation": "Një përpunim që keni bërë u shpall i paligjshëm nga shërbyesu i njëkohësimit.", + "pad.modals.badChangeset.explanation": "Një përpunim që keni bërë u vlerësua si i paligjshëm nga shërbyesi i njëkohësimit.", "pad.modals.badChangeset.cause": "Kjo mund të jetë për shkak të një formësimi të gabuar të shërbyesit ose ndonjë tjetër sjelljeje të papritur. Ju lutemi, lidhuni me përgjegjësin e shërbimit, nëse mendoni që ky është një gabim. Provoni të rilidheni që të vazhdoni përpunimin.", "pad.modals.corruptPad.explanation": "Blloku te i cili po përpiqeni të hyni është i dëmtuar.", "pad.modals.corruptPad.cause": "Kjo mund të vijë nga një formësim i gabuar shërbyesi ose ndonjë tjetër sjellje e papritur. Ju lutemi, lidhuni me përgjegjësin e shërbimit.", "pad.modals.deleted": "I fshirë.", "pad.modals.deleted.explanation": "Ky bllok është hequr.", "pad.modals.disconnected": "Jeni shkëputur.", - "pad.modals.disconnected.explanation": "U pre lidhja me shërbyesin", + "pad.modals.disconnected.explanation": "U ndërpre lidhja me shërbyesin", "pad.modals.disconnected.cause": "Shërbyesi mund të mos jetë në punë. Ju lutemi, njoftoni përgjegjësin e shërbimit, nëse kjo vazhdon të ndodhë.", "pad.share": "Ndajeni këtë bllok me të tjerët", "pad.share.readonly": "Vetëm për lexim", @@ -103,11 +102,12 @@ "timeslider.month.october": "Tetor", "timeslider.month.november": "Nëntor", "timeslider.month.december": "Dhjetor", + "timeslider.unnamedauthors": "{{num}} i paemërt {[plural(num) një: autor, tjetër: autorë ]}", "pad.savedrevs.marked": "Ky rishikim tani është shënuar si rishikim i ruajtur", "pad.userlist.entername": "Jepni emrin tuaj", "pad.userlist.unnamed": "pa emër", "pad.userlist.guest": "Vizitor", - "pad.userlist.deny": "Mohoje", + "pad.userlist.deny": "Hidheni Tej", "pad.userlist.approve": "Miratoje", "pad.editbar.clearcolors": "Të hiqen ngjyra autorësish në krejt dokumentin?", "pad.impexp.importbutton": "Importoje Tani", diff --git a/src/locales/sv.json b/src/locales/sv.json index 623def9ac..bda3cb83b 100644 --- a/src/locales/sv.json +++ b/src/locales/sv.json @@ -11,14 +11,14 @@ "pad.toolbar.bold.title": "Fet (Ctrl-B)", "pad.toolbar.italic.title": "Kursiv (Ctrl-I)", "pad.toolbar.underline.title": "Understruken (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Genomstruken", - "pad.toolbar.ol.title": "Numrerad lista", - "pad.toolbar.ul.title": "Osorterad lista", + "pad.toolbar.strikethrough.title": "Genomstruken (Ctrl+5)", + "pad.toolbar.ol.title": "Numrerad lista (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Onumrerad lista (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Öka indrag (TABB)", "pad.toolbar.unindent.title": "Minska indrag (Shift+TABB)", "pad.toolbar.undo.title": "Ångra (Ctrl-Z)", "pad.toolbar.redo.title": "Gör om (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Rensa författarfärger", + "pad.toolbar.clearAuthorship.title": "Rensa författarfärger (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Importera/exportera från/till olika filformat", "pad.toolbar.timeslider.title": "Tidsreglage", "pad.toolbar.savedRevision.title": "Spara version", @@ -51,8 +51,7 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Open Document Format)", - "pad.importExport.exportdokuwiki": "DokuWiki", - "pad.importExport.abiword.innerHTML": "Du kan endast importera från oformaterad text eller html-format. För mer avancerade importeringsfunktioner, var god installera abiword.", + "pad.importExport.abiword.innerHTML": "Du kan endast importera från oformaterad text eller HTML-format. För mer avancerade importeringsfunktioner, var god installera abiword.", "pad.modals.connected": "Ansluten.", "pad.modals.reconnecting": "Återansluter till ditt block...", "pad.modals.forcereconnect": "Tvinga återanslutning", @@ -60,7 +59,7 @@ "pad.modals.userdup.explanation": "Detta block verkar vara öppet i mer än ett fönster på denna dator.", "pad.modals.userdup.advice": "Återanslut för att använda detta fönster istället.", "pad.modals.unauth": "Inte godkänd", - "pad.modals.unauth.explanation": "Din behörighet ändrades medan du visar denna sida. Försök att återansluta.", + "pad.modals.unauth.explanation": "Din behörighet ändrades medan du visade denna sida. Försök att återansluta.", "pad.modals.looping.explanation": "Kommunikationsproblem med synkroniseringsservern har uppstått.", "pad.modals.looping.cause": "Kanske du är ansluten via en inkompatibel brandvägg eller proxy.", "pad.modals.initsocketfail": "Servern kan inte nås.", @@ -69,7 +68,7 @@ "pad.modals.slowcommit.explanation": "Servern svarar inte.", "pad.modals.slowcommit.cause": "Detta kan bero på problem med nätverksanslutningen.", "pad.modals.badChangeset.explanation": "En redigering som du gjort klassificerades som otillåten av synkroniseringsservern.", - "pad.modals.badChangeset.cause": "Detta kan bero på en felaktig konfiguration av servern eller något annat oväntad beteende. Var god kontakta tjänstadministratören om du anser att detta är ett fel. Försök ansluta igen för att fortsätta redigera.", + "pad.modals.badChangeset.cause": "Detta kan bero på en felaktig konfiguration av servern eller något annat oväntad beteende. Var god kontakta tjänsteadministratören om du upplever att detta är ett fel. Försök att ansluta igen för att fortsätta redigera.", "pad.modals.corruptPad.explanation": "Blocket du försöker komma åt är skadat.", "pad.modals.corruptPad.cause": "Detta kan bero på en felaktig konfiguration av servern eller något annat oväntad beteende. Var god kontakta tjänstadministratören.", "pad.modals.deleted": "Raderad.", @@ -84,7 +83,7 @@ "pad.chat": "Chatt", "pad.chat.title": "Öppna chatten för detta block.", "pad.chat.loadmessages": "Läs in fler meddelanden", - "timeslider.pageTitle": "Tidsreglage för {{appTitle}}", + "timeslider.pageTitle": "{{appTitle}} tidsreglage", "timeslider.toolbar.returnbutton": "Återvänd till blocket", "timeslider.toolbar.authors": "Författare:", "timeslider.toolbar.authorsList": "Inga författare", diff --git a/src/locales/te.json b/src/locales/te.json index 41341d1e3..198782062 100644 --- a/src/locales/te.json +++ b/src/locales/te.json @@ -50,7 +50,6 @@ "pad.importExport.exportword": "మైక్రోసాఫ్ట్ వర్డ్", "pad.importExport.exportpdf": "పీ డి ఎఫ్", "pad.importExport.exportopen": "ఓ డి ఎఫ్ (ఓపెన్ డాక్యుమెంట్ ఫార్మాట్)", - "pad.importExport.exportdokuwiki": "డాక్యువికి", "pad.modals.connected": "సంబంధం కుదిరింది.", "pad.modals.reconnecting": "మీ పలకకు మరల సంబంధం కలుపుతుంది...", "pad.modals.forcereconnect": "బలవంతంగానైనా సంబంధం కుదిరించు", diff --git a/src/locales/tr.json b/src/locales/tr.json index 89c1f0df3..54030fda1 100644 --- a/src/locales/tr.json +++ b/src/locales/tr.json @@ -4,7 +4,8 @@ "Emperyan", "Erdemaslancan", "Joseph", - "Meelo" + "Meelo", + "Trockya" ] }, "index.newPad": "Yeni Bloknot", @@ -12,14 +13,14 @@ "pad.toolbar.bold.title": "Kalın (Ctrl-B)", "pad.toolbar.italic.title": "Eğik (Ctrl-I)", "pad.toolbar.underline.title": "Altı Çizili (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Üstü Çizili", - "pad.toolbar.ol.title": "Sıralı liste", - "pad.toolbar.ul.title": "Sırasız Liste", + "pad.toolbar.strikethrough.title": "Üstü Çizili (Ctrl+5)", + "pad.toolbar.ol.title": "Sıralı liste (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Sırasız Liste (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Girintiyi arttır (TAB)", "pad.toolbar.unindent.title": "Girintiyi azalt (Shift+TAB)", "pad.toolbar.undo.title": "Geri Al (Ctrl-Z)", - "pad.toolbar.redo.title": "Yenile (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "Yazarlık Renklerini Temizle", + "pad.toolbar.redo.title": "Yinele (Ctrl+Y)", + "pad.toolbar.clearAuthorship.title": "Yazarlık Renklerini Temizle (Ctrl+Shift+C)", "pad.toolbar.import_export.title": "Farklı dosya biçimlerini içeri/dışarı aktar", "pad.toolbar.timeslider.title": "Zaman Çizelgesi", "pad.toolbar.savedRevision.title": "Düzeltmeyi Kaydet", @@ -52,7 +53,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (Açık Doküman Biçimi)", - "pad.importExport.exportdokuwiki": "VikiBelge", "pad.importExport.abiword.innerHTML": "Yalnızca düz metin ya da HTML biçimlerini içe aktarabilirsiniz. Daha fazla gelişmiş içe aktarım özellikleri için AbiWord'ü yükleyin.", "pad.modals.connected": "Bağlandı.", "pad.modals.reconnecting": "Bloknotunuza tekrar bağlanılıyor...", diff --git a/src/locales/uk.json b/src/locales/uk.json index 41686c5ef..79a39a334 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -53,7 +53,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF (документ OpenOffice)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Ви можете імпортувати лище формати простого тексту або html. Для більш просунутих способів імпорту встановіть abiword.", "pad.modals.connected": "З'єднано.", "pad.modals.reconnecting": "Перепідлючення до Вашого документу..", diff --git a/src/locales/vi.json b/src/locales/vi.json index 608e9645a..da0baf501 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -3,7 +3,8 @@ "authors": [ "Baonguyen21022003", "Minh Nguyen", - "Tuankiet65" + "Tuankiet65", + "Max20091" ] }, "index.newPad": "Tạo một Pad mới", @@ -11,9 +12,9 @@ "pad.toolbar.bold.title": "In đậm (Ctrl-B)", "pad.toolbar.italic.title": "In nghiêng (Ctrl-I)", "pad.toolbar.underline.title": "Gạch chân (Ctrl-U)", - "pad.toolbar.strikethrough.title": "Gạch ngang", - "pad.toolbar.ol.title": "Danh sách Có Đánh số", - "pad.toolbar.ul.title": "Danh sách Không Đánh số", + "pad.toolbar.strikethrough.title": "Gạch ngang (Ctrl+5)", + "pad.toolbar.ol.title": "Danh sách Có Đánh số (Ctrl+Shift+N)", + "pad.toolbar.ul.title": "Danh sách Không Đánh số (Ctrl+Shift+L)", "pad.toolbar.indent.title": "Tăng lề (TAB)", "pad.toolbar.unindent.title": "Giảm lề (Shift+TAB)", "pad.toolbar.undo.title": "Hoàn tác (Ctrl-Z)", @@ -51,7 +52,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "Bạn chỉ có thể nhập vào từ văn bản thuần túy hay định dạng HTML. Nếu muốn có nhiều chức năng nhập hơn xin hãy cài đặt abiword.", "pad.modals.connected": "Đã kết nối lại.", "pad.modals.reconnecting": "Kết nối lại tới pad của bạn", diff --git a/src/locales/zh-hans.json b/src/locales/zh-hans.json index 556ab8a12..104e850b3 100644 --- a/src/locales/zh-hans.json +++ b/src/locales/zh-hans.json @@ -18,14 +18,14 @@ "pad.toolbar.bold.title": "粗体(Ctrl-B)", "pad.toolbar.italic.title": "斜体 (Ctrl-I)", "pad.toolbar.underline.title": "下划线(Ctrl-U)", - "pad.toolbar.strikethrough.title": "删除线", - "pad.toolbar.ol.title": "有序列表", - "pad.toolbar.ul.title": "无序列表", + "pad.toolbar.strikethrough.title": "删除线(Ctrl+5)", + "pad.toolbar.ol.title": "有序列表(Ctrl+Shift+N)", + "pad.toolbar.ul.title": "无序列表(Ctrl+Shift+L)", "pad.toolbar.indent.title": "增加缩进(TAB)", "pad.toolbar.unindent.title": "减少缩进(Shift+TAB)", "pad.toolbar.undo.title": "撤消 (Ctrl-Z)", "pad.toolbar.redo.title": "重做 (Ctrl-Y)", - "pad.toolbar.clearAuthorship.title": "清除作者颜色", + "pad.toolbar.clearAuthorship.title": "清除作者颜色(Ctrl+Shift+C)", "pad.toolbar.import_export.title": "从不同的文件格式导入/导出", "pad.toolbar.timeslider.title": "时间轴", "pad.toolbar.savedRevision.title": "保存修订", @@ -58,7 +58,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF(开放文档格式)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "您只能导入纯文本或HTML格式。安裝abiword取得更多高级的导入功能。", "pad.modals.connected": "已连接。", "pad.modals.reconnecting": "重新连接到您的记事本...", diff --git a/src/locales/zh-hant.json b/src/locales/zh-hant.json index 0707648a2..6d79268c2 100644 --- a/src/locales/zh-hant.json +++ b/src/locales/zh-hant.json @@ -14,9 +14,9 @@ "pad.toolbar.bold.title": "粗體(Ctrl-B)", "pad.toolbar.italic.title": "斜體(Ctrl-I)", "pad.toolbar.underline.title": "底線(Ctrl-U)", - "pad.toolbar.strikethrough.title": "刪除線", - "pad.toolbar.ol.title": "有序清單", - "pad.toolbar.ul.title": "無序清單", + "pad.toolbar.strikethrough.title": "刪除線(Ctrl+5)", + "pad.toolbar.ol.title": "有序清單(Ctrl+Shift+N)", + "pad.toolbar.ul.title": "無序清單(Ctrl+Shift+L)", "pad.toolbar.indent.title": "縮排(TAB)", "pad.toolbar.unindent.title": "凸排(Shift+TAB)", "pad.toolbar.undo.title": "撤銷(Ctrl-Z)", @@ -54,7 +54,6 @@ "pad.importExport.exportword": "Microsoft Word", "pad.importExport.exportpdf": "PDF", "pad.importExport.exportopen": "ODF(開放文件格式)", - "pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.abiword.innerHTML": "您只可以純文字或html格式檔匯入。安裝abiword取得更多進階的匯入功能。", "pad.modals.connected": "已連線。", "pad.modals.reconnecting": "重新連接到您的pad...", @@ -73,7 +72,7 @@ "pad.modals.slowcommit.cause": "這可能是因為網路連線問題所造成。", "pad.modals.badChangeset.explanation": "您的一個編輯被同步伺服器類為非法。", "pad.modals.badChangeset.cause": "這可能由於伺服器的配置錯誤或遇到意外問題。若您認為這是錯誤,請聯繫伺服器管理員。如要繼續編輯,請嘗試重新連接。", - "pad.modals.corruptPad.explanation": "您試圖訪問的平板已損壞。", + "pad.modals.corruptPad.explanation": "您試圖存取的平板已損壞。", "pad.modals.corruptPad.cause": "這可能由於伺服器的配置錯誤或遇到意外問題。請聯繫伺服器管理員。", "pad.modals.deleted": "已刪除。", "pad.modals.deleted.explanation": "此pad已被移除。", @@ -94,7 +93,7 @@ "timeslider.toolbar.exportlink.title": "匯出", "timeslider.exportCurrent": "匯出當前版本為:", "timeslider.version": "版本{{version}}", - "timeslider.saved": "{{year}}年{{month}}月{{day}}日儲存", + "timeslider.saved": "{{year}}年{{month}}{{day}}日儲存", "timeslider.dateformat": "{{year}}年{{month}}月{{day}}日 {{hours}}:{{minutes}}:{{seconds}}", "timeslider.month.january": "1月", "timeslider.month.february": "2月", diff --git a/src/node/db/API.js b/src/node/db/API.js index 4a9123682..a9df2a12f 100644 --- a/src/node/db/API.js +++ b/src/node/db/API.js @@ -263,7 +263,7 @@ exports.getText = function(padID, rev, callback) { if(ERR(err, callback)) return; - data = {text: atext.text}; + var data = {text: atext.text}; callback(null, data); }) @@ -368,7 +368,7 @@ exports.getHTML = function(padID, rev, callback) if(ERR(err, callback)) return; html = "" +html; // adds HTML head html += ""; - data = {html: html}; + var data = {html: html}; callback(null, data); }); } @@ -380,7 +380,7 @@ exports.getHTML = function(padID, rev, callback) if(ERR(err, callback)) return; html = "" +html; // adds HTML head html += ""; - data = {html: html}; + var data = {html: html}; callback(null, data); }); } @@ -575,6 +575,117 @@ exports.deletePad = function(padID, callback) pad.remove(callback); }); } +/** + restoreRevision(padID, [rev]) Restores revision from past as new changeset + + Example returns: + + {code:0, message:"ok", data:null} + {code: 1, message:"padID does not exist", data: null} + */ +exports.restoreRevision = function (padID, rev, callback) +{ + var Changeset = require("ep_etherpad-lite/static/js/Changeset"); + var padMessage = require("ep_etherpad-lite/node/handler/PadMessageHandler.js"); + + //check if rev is a number + if (rev !== undefined && typeof rev != "number") + { + //try to parse the number + if (!isNaN(parseInt(rev))) + { + rev = parseInt(rev); + } + else + { + callback(new customError("rev is not a number", "apierror")); + return; + } + } + + //ensure this is not a negativ number + if (rev !== undefined && rev < 0) + { + callback(new customError("rev is a negativ number", "apierror")); + return; + } + + //ensure this is not a float value + if (rev !== undefined && !is_int(rev)) + { + callback(new customError("rev is a float value", "apierror")); + return; + } + + //get the pad + getPadSafe(padID, true, function (err, pad) + { + if (ERR(err, callback)) return; + + + //check if this is a valid revision + if (rev > pad.getHeadRevisionNumber()) + { + callback(new customError("rev is higher than the head revision of the pad", "apierror")); + return; + } + + pad.getInternalRevisionAText(rev, function (err, atext) + { + if (ERR(err, callback)) return; + + var oldText = pad.text(); + atext.text += "\n"; + function eachAttribRun(attribs, func) + { + var attribsIter = Changeset.opIterator(attribs); + var textIndex = 0; + var newTextStart = 0; + var newTextEnd = atext.text.length; + while (attribsIter.hasNext()) + { + var op = attribsIter.next(); + var nextIndex = textIndex + op.chars; + if (!(nextIndex <= newTextStart || textIndex >= newTextEnd)) + { + func(Math.max(newTextStart, textIndex), Math.min(newTextEnd, nextIndex), op.attribs); + } + textIndex = nextIndex; + } + } + + // create a new changeset with a helper builder object + var builder = Changeset.builder(oldText.length); + + // assemble each line into the builder + eachAttribRun(atext.attribs, function (start, end, attribs) + { + builder.insert(atext.text.substring(start, end), attribs); + }); + + var lastNewlinePos = oldText.lastIndexOf('\n'); + if (lastNewlinePos < 0) + { + builder.remove(oldText.length - 1, 0); + } else + { + builder.remove(lastNewlinePos, oldText.match(/\n/g).length - 1); + builder.remove(oldText.length - lastNewlinePos - 1, 0); + } + + var changeset = builder.toString(); + + //append the changeset + pad.appendRevision(changeset); + // + padMessage.updatePadClients(pad, function () + { + }); + callback(null, null); + }); + + }); +}; /** copyPad(sourceID, destinationID[, force=false]) copies a pad. If force is true, diff --git a/src/node/db/AuthorManager.js b/src/node/db/AuthorManager.js index 5ba608e98..e0f569efb 100644 --- a/src/node/db/AuthorManager.js +++ b/src/node/db/AuthorManager.js @@ -21,7 +21,6 @@ var ERR = require("async-stacktrace"); var db = require("./DB").db; -var async = require("async"); var customError = require("../utils/customError"); var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString; diff --git a/src/node/db/Pad.js b/src/node/db/Pad.js index 4670696a3..2f5860f8f 100644 --- a/src/node/db/Pad.js +++ b/src/node/db/Pad.js @@ -135,7 +135,7 @@ Pad.prototype.getRevisionDate = function getRevisionDate(revNum, callback) { Pad.prototype.getAllAuthors = function getAllAuthors() { var authors = []; - for(key in this.pool.numToAttrib) + for(var key in this.pool.numToAttrib) { if(this.pool.numToAttrib[key][0] == "author" && this.pool.numToAttrib[key][1] != "") { @@ -461,7 +461,6 @@ Pad.prototype.copy = function copy(destinationID, force, callback) { // if the pad exists, we should abort, unless forced. function(callback) { - console.log("destinationID", destinationID, force); padManager.doesPadExists(destinationID, function (err, exists) { if(ERR(err, callback)) return; @@ -470,9 +469,9 @@ Pad.prototype.copy = function copy(destinationID, force, callback) { { if (!force) { - console.log("erroring out without force"); + console.error("erroring out without force"); callback(new customError("destinationID already exists","apierror")); - console.log("erroring out without force - after"); + console.error("erroring out without force - after"); return; } else // exists and forcing @@ -521,12 +520,9 @@ Pad.prototype.copy = function copy(destinationID, force, callback) { function(callback) { var revHead = _this.head; - //console.log(revHead); for(var i=0;i<=revHead;i++) { db.get("pad:"+sourceID+":revs:"+i, function (err, rev) { - //console.log("HERE"); - if (ERR(err, callback)) return; db.set("pad:"+destinationID+":revs:"+i, rev); }); @@ -538,10 +534,8 @@ Pad.prototype.copy = function copy(destinationID, force, callback) { function(callback) { var authorIDs = _this.getAllAuthors(); - authorIDs.forEach(function (authorID) { - console.log("authors"); authorManager.addPad(authorID, destinationID); }); @@ -555,7 +549,9 @@ Pad.prototype.copy = function copy(destinationID, force, callback) { if(destGroupID) db.setSub("group:" + destGroupID, ["pads", destinationID], 1); // Initialize the new pad (will update the listAllPads cache) - padManager.getPad(destinationID, null, callback) + setTimeout(function(){ + padManager.getPad(destinationID, null, callback) // this runs too early. + },10); } // series ], function(err) @@ -690,7 +686,7 @@ Pad.prototype.isPasswordProtected = function isPasswordProtected() { Pad.prototype.addSavedRevision = function addSavedRevision(revNum, savedById, label) { //if this revision is already saved, return silently for(var i in this.savedRevisions){ - if(this.savedRevisions.revNum === revNum){ + if(this.savedRevisions[i] && this.savedRevisions[i].revNum === revNum){ return; } } diff --git a/src/node/db/SecurityManager.js b/src/node/db/SecurityManager.js index df3c38267..6fae57ffb 100644 --- a/src/node/db/SecurityManager.js +++ b/src/node/db/SecurityManager.js @@ -20,7 +20,6 @@ var ERR = require("async-stacktrace"); -var db = require("./DB").db; var async = require("async"); var authorManager = require("./AuthorManager"); var padManager = require("./PadManager"); diff --git a/src/node/db/SessionManager.js b/src/node/db/SessionManager.js index 71315adca..f8000e47e 100644 --- a/src/node/db/SessionManager.js +++ b/src/node/db/SessionManager.js @@ -351,7 +351,15 @@ function listSessionsWithDBKey (dbkey, callback) { exports.getSessionInfo(sessionID, function(err, sessionInfo) { - if(ERR(err, callback)) return; + if (err == "apierror: sessionID does not exist") + { + console.warn("Found bad session " + sessionID + " in " + dbkey + "."); + } + else if(ERR(err, callback)) + { + return; + } + sessions[sessionID] = sessionInfo; callback(); }); diff --git a/src/node/db/SessionStore.js b/src/node/db/SessionStore.js index 52a504f10..5c45ddb30 100644 --- a/src/node/db/SessionStore.js +++ b/src/node/db/SessionStore.js @@ -5,8 +5,6 @@ */ 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"); diff --git a/src/node/eejs/index.js b/src/node/eejs/index.js index 48185d80b..30f5a442f 100644 --- a/src/node/eejs/index.js +++ b/src/node/eejs/index.js @@ -71,7 +71,7 @@ exports.begin_define_block = function (name) { } exports.end_define_block = function () { - content = exports.end_capture(); + var content = exports.end_capture(); return content; } diff --git a/src/node/handler/APIHandler.js b/src/node/handler/APIHandler.js index 273a58a6a..a26dd2cfb 100644 --- a/src/node/handler/APIHandler.js +++ b/src/node/handler/APIHandler.js @@ -345,10 +345,56 @@ var version = , "getChatHistory" : ["padID", "start", "end"] , "getChatHead" : ["padID"] } +, "1.2.11": + { "createGroup" : [] + , "createGroupIfNotExistsFor" : ["groupMapper"] + , "deleteGroup" : ["groupID"] + , "listPads" : ["groupID"] + , "listAllPads" : [] + , "createDiffHTML" : ["padID", "startRev", "endRev"] + , "createPad" : ["padID", "text"] + , "createGroupPad" : ["groupID", "padName", "text"] + , "createAuthor" : ["name"] + , "createAuthorIfNotExistsFor": ["authorMapper" , "name"] + , "listPadsOfAuthor" : ["authorID"] + , "createSession" : ["groupID", "authorID", "validUntil"] + , "deleteSession" : ["sessionID"] + , "getSessionInfo" : ["sessionID"] + , "listSessionsOfGroup" : ["groupID"] + , "listSessionsOfAuthor" : ["authorID"] + , "getText" : ["padID", "rev"] + , "setText" : ["padID", "text"] + , "getHTML" : ["padID", "rev"] + , "setHTML" : ["padID", "html"] + , "getAttributePool" : ["padID"] + , "getRevisionsCount" : ["padID"] + , "getRevisionChangeset" : ["padID", "rev"] + , "getLastEdited" : ["padID"] + , "deletePad" : ["padID"] + , "copyPad" : ["sourceID", "destinationID", "force"] + , "movePad" : ["sourceID", "destinationID", "force"] + , "getReadOnlyID" : ["padID"] + , "getPadID" : ["roID"] + , "setPublicStatus" : ["padID", "publicStatus"] + , "getPublicStatus" : ["padID"] + , "setPassword" : ["padID", "password"] + , "isPasswordProtected" : ["padID"] + , "listAuthorsOfPad" : ["padID"] + , "padUsersCount" : ["padID"] + , "getAuthorName" : ["authorID"] + , "padUsers" : ["padID"] + , "sendClientsMessage" : ["padID", "msg"] + , "listAllGroups" : [] + , "checkToken" : [] + , "getChatHistory" : ["padID"] + , "getChatHistory" : ["padID", "start", "end"] + , "getChatHead" : ["padID"] + , "restoreRevision" : ["padID", "rev"] + } }; // set the latest available API version here -exports.latestApiVersion = '1.2.10'; +exports.latestApiVersion = '1.2.11'; // exports the versions so it can be used by the new Swagger endpoint exports.version = version; @@ -404,6 +450,7 @@ exports.handle = function(apiVersion, functionName, fields, req, res) if(fields["apikey"] != apikey.trim()) { + res.statusCode = 401; res.send({code: 4, message: "no or wrong API Key", data: null}); return; } diff --git a/src/node/handler/ExportHandler.js b/src/node/handler/ExportHandler.js index a748d3f2e..0a0e51f1c 100644 --- a/src/node/handler/ExportHandler.js +++ b/src/node/handler/ExportHandler.js @@ -4,6 +4,7 @@ /* * 2011 Peter 'Pita' Martischka (Primary Technology Ltd) + * 2014 John McLear (Etherpad Foundation / McLear Ltd) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -21,8 +22,7 @@ var ERR = require("async-stacktrace"); var exporthtml = require("../utils/ExportHtml"); var exporttxt = require("../utils/ExportTxt"); -var exportdokuwiki = require("../utils/ExportDokuWiki"); -var padManager = require("../db/PadManager"); +var exportEtherpad = require("../utils/ExportEtherpad"); var async = require("async"); var fs = require("fs"); var settings = require('../utils/Settings'); @@ -52,16 +52,22 @@ exports.doExport = function(req, res, padId, type) hooks.aCallFirst("exportFileName", padId, function(err, hookFileName){ // if fileName is set then set it to the padId, note that fileName is returned as an array. - if(hookFileName) fileName = hookFileName; - + if(hookFileName.length) fileName = hookFileName; //tell the browser that this is a downloadable file res.attachment(fileName + "." + type); //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 == "etherpad"){ + exportEtherpad.getPadRaw(padId, function(err, pad){ + if(!err){ + res.send(pad); + // return; + } + }); + } + else if(type == "txt") { var txt; var randNum; @@ -129,26 +135,6 @@ exports.doExport = function(req, res, padId, type) if(err && err != "stop") ERR(err); }) } - else if(type == 'dokuwiki') - { - var randNum; - var srcFile, destFile; - - async.series([ - //render the dokuwiki document - function(callback) - { - exportdokuwiki.getPadDokuWikiDocument(padId, req.params.rev, function(err, dokuwiki) - { - res.send(dokuwiki); - callback("stop"); - }); - }, - ], function(err) - { - if(err && err != "stop") throw err; - }); - } else { var html; diff --git a/src/node/handler/ImportHandler.js b/src/node/handler/ImportHandler.js index 60fa5ffb1..a511637cc 100644 --- a/src/node/handler/ImportHandler.js +++ b/src/node/handler/ImportHandler.js @@ -5,6 +5,7 @@ /* * 2011 Peter 'Pita' Martischka (Primary Technology Ltd) * 2012 Iván Eixarch + * 2014 John McLear (Etherpad Foundation / McLear Ltd) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,6 +30,7 @@ var ERR = require("async-stacktrace") , formidable = require('formidable') , os = require("os") , importHtml = require("../utils/ImportHtml") + , importEtherpad = require("../utils/ImportEtherpad") , log4js = require("log4js") , hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks.js"); @@ -53,7 +55,8 @@ exports.doImport = function(req, res, padId) var srcFile, destFile , pad , text - , importHandledByPlugin; + , importHandledByPlugin + , directDatabaseAccess; var randNum = Math.floor(Math.random()*0xFFFFFFFF); @@ -83,7 +86,7 @@ exports.doImport = function(req, res, padId) //this allows us to accept source code files like .c or .java function(callback) { var fileEnding = path.extname(srcFile).toLowerCase() - , knownFileEndings = [".txt", ".doc", ".docx", ".pdf", ".odt", ".html", ".htm"] + , knownFileEndings = [".txt", ".doc", ".docx", ".pdf", ".odt", ".html", ".htm", ".etherpad"] , fileEndingKnown = (knownFileEndings.indexOf(fileEnding) > -1); //if the file ending is known, continue as normal @@ -92,9 +95,14 @@ exports.doImport = function(req, res, padId) } //we need to rename this file with a .txt ending else { - var oldSrcFile = srcFile; - srcFile = path.join(path.dirname(srcFile),path.basename(srcFile, fileEnding)+".txt"); - fs.rename(oldSrcFile, srcFile, callback); + if(settings.allowUnknownFileEnds === true){ + var oldSrcFile = srcFile; + srcFile = path.join(path.dirname(srcFile),path.basename(srcFile, fileEnding)+".txt"); + fs.rename(oldSrcFile, srcFile, callback); + }else{ + console.warn("Not allowing unknown file type to be imported", fileEnding); + callback("uploadFailed"); + } } }, function(callback){ @@ -111,9 +119,33 @@ exports.doImport = function(req, res, padId) } }); }, + function(callback) { + var fileEnding = path.extname(srcFile).toLowerCase() + var fileIsEtherpad = (fileEnding === ".etherpad"); + + if(fileIsEtherpad){ + // we do this here so we can see if the pad has quit ea few edits + padManager.getPad(padId, function(err, _pad){ + var headCount = _pad.head; + if(headCount >= 10){ + apiLogger.warn("Direct database Import attempt of a pad that already has content, we wont be doing this") + return callback("padHasData"); + }else{ + fs.readFile(srcFile, "utf8", function(err, _text){ + directDatabaseAccess = true; + importEtherpad.setPadRaw(padId, _text, function(err){ + callback(); + }); + }); + } + }); + }else{ + callback(); + } + }, //convert file to html function(callback) { - if(!importHandledByPlugin){ + if(!importHandledByPlugin || !directDatabaseAccess){ var fileEnding = path.extname(srcFile).toLowerCase(); var fileIsHTML = (fileEnding === ".html" || fileEnding === ".htm"); if (abiword && !fileIsHTML) { @@ -136,24 +168,28 @@ exports.doImport = function(req, res, padId) }, function(callback) { - if (!abiword) { - // Read the file with no encoding for raw buffer access. - fs.readFile(destFile, function(err, buf) { - if (err) throw err; - var isAscii = true; - // Check if there are only ascii chars in the uploaded file - for (var i=0, len=buf.length; i 240) { - isAscii=false; - break; + if (!abiword){ + if(!directDatabaseAccess) { + // Read the file with no encoding for raw buffer access. + fs.readFile(destFile, function(err, buf) { + if (err) throw err; + var isAscii = true; + // Check if there are only ascii chars in the uploaded file + for (var i=0, len=buf.length; i 240) { + isAscii=false; + break; + } } - } - if (isAscii) { - callback(); - } else { - callback("uploadFailed"); - } - }); + if (isAscii) { + callback(); + } else { + callback("uploadFailed"); + } + }); + }else{ + callback(); + } } else { callback(); } @@ -170,66 +206,104 @@ exports.doImport = function(req, res, padId) //read the text function(callback) { - fs.readFile(destFile, "utf8", function(err, _text){ - if(ERR(err, callback)) return; - text = _text; - // Title needs to be stripped out else it appends it to the pad.. - text = text.replace("", "<!-- <title>"); - text = text.replace("","-->"); - - //node on windows has a delay on releasing of the file lock. - //We add a 100ms delay to work around this - if(os.type().indexOf("Windows") > -1){ - setTimeout(function() {callback();}, 100); - } else { - callback(); - } - }); + if(!directDatabaseAccess){ + fs.readFile(destFile, "utf8", function(err, _text){ + if(ERR(err, callback)) return; + text = _text; + // Title needs to be stripped out else it appends it to the pad.. + text = text.replace("", "<!-- <title>"); + text = text.replace("","-->"); + + //node on windows has a delay on releasing of the file lock. + //We add a 100ms delay to work around this + if(os.type().indexOf("Windows") > -1){ + setTimeout(function() {callback();}, 100); + } else { + callback(); + } + }); + }else{ + callback(); + } }, //change text of the pad and broadcast the changeset function(callback) { - var fileEnding = path.extname(srcFile).toLowerCase(); - if (abiword || fileEnding == ".htm" || fileEnding == ".html") { - try{ - importHtml.setPadHTML(pad, text); - }catch(e){ - apiLogger.warn("Error importing, possibly caused by malformed HTML"); + if(!directDatabaseAccess){ + var fileEnding = path.extname(srcFile).toLowerCase(); + if (abiword || fileEnding == ".htm" || fileEnding == ".html") { + try{ + importHtml.setPadHTML(pad, text); + }catch(e){ + apiLogger.warn("Error importing, possibly caused by malformed HTML"); + } + } else { + pad.setText(text); } - } else { - pad.setText(text); } - padMessageHandler.updatePadClients(pad, callback); + + // Load the Pad into memory then brodcast updates to all clients + padManager.unloadPad(padId); + padManager.getPad(padId, function(err, _pad){ + var pad = _pad; + padManager.unloadPad(padId); + + // direct Database Access means a pad user should perform a switchToPad + // and not attempt to recieve updated pad data.. + if(!directDatabaseAccess){ + padMessageHandler.updatePadClients(pad, function(){ + callback(); + }); + }else{ + callback(); + } + }); + }, //clean up temporary files function(callback) { - //for node < 0.7 compatible - var fileExists = fs.exists || path.exists; - async.parallel([ - function(callback){ - fileExists (srcFile, function(exist) { (exist)? fs.unlink(srcFile, callback): callback(); }); - }, - function(callback){ - fileExists (destFile, function(exist) { (exist)? fs.unlink(destFile, callback): callback(); }); - } - ], callback); + if(!directDatabaseAccess){ + //for node < 0.7 compatible + var fileExists = fs.exists || path.exists; + async.parallel([ + function(callback){ + fileExists (srcFile, function(exist) { (exist)? fs.unlink(srcFile, callback): callback(); }); + }, + function(callback){ + fileExists (destFile, function(exist) { (exist)? fs.unlink(destFile, callback): callback(); }); + } + ], callback); + }else{ + callback(); + } } ], function(err) { - var status = "ok"; //check for known errors and replace the status - if(err == "uploadFailed" || err == "convertFailed") + if(err == "uploadFailed" || err == "convertFailed" || err == "padHasData") { status = err; err = null; } ERR(err); - + //close the connection - res.send("", 200); + res.send( + " \ + \ + \ + " + , 200); }); } diff --git a/src/node/handler/PadMessageHandler.js b/src/node/handler/PadMessageHandler.js index e1ac994e8..3228330e3 100644 --- a/src/node/handler/PadMessageHandler.js +++ b/src/node/handler/PadMessageHandler.js @@ -37,6 +37,7 @@ var _ = require('underscore'); var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks.js"); var channels = require("channels"); var stats = require('../stats'); +var remoteAddress = require("../utils/RemoteAddress").remoteAddress; /** * A associative array that saves informations about a session @@ -93,8 +94,18 @@ exports.handleConnect = function(client) */ exports.kickSessionsFromPad = function(padID) { + if(typeof socketio.sockets['clients'] !== 'function') + return; + //skip if there is nobody on this pad - if(socketio.sockets.clients(padID).length == 0) + var roomClients = [], room = socketio.sockets.adapter.rooms[padID]; + if (room) { + for (var id in room) { + roomClients.push(socketio.sockets.adapter.nsp.connected[id]); + } + } + + if(roomClients.length == 0) return; //disconnect everyone from this pad @@ -115,14 +126,16 @@ exports.handleDisconnect = function(client) //if this connection was already etablished with a handshake, send a disconnect message to the others if(session && session.author) { - client.get('remoteAddress', function(er, ip) { - //Anonymize the IP address if IP logging is disabled - if(settings.disableIPlogging) { - ip = 'ANONYMOUS'; - } - accessLogger.info('[LEAVE] Pad "'+session.padId+'": Author "'+session.author+'" on client '+client.id+' with IP "'+ip+'" left the pad') - }) + // Get the IP address from our persistant object + var ip = remoteAddress[client.id]; + + // Anonymize the IP address if IP logging is disabled + if(settings.disableIPlogging) { + ip = 'ANONYMOUS'; + } + + accessLogger.info('[LEAVE] Pad "'+session.padId+'": Author "'+session.author+'" on client '+client.id+' with IP "'+ip+'" left the pad') //get the author color out of the db authorManager.getAuthorColorId(session.author, function(err, color) @@ -220,6 +233,8 @@ exports.handleMessage = function(client, message) } else { messageLogger.warn("Dropped message, unknown COLLABROOM Data Type " + message.data.type); } + } else if(message.type == "SWITCH_TO_PAD") { + handleSwitchToPad(client, message); } else { messageLogger.warn("Dropped message, unknown Message Type " + message.type); } @@ -233,18 +248,7 @@ exports.handleMessage = function(client, message) { // client tried to auth for the first time (first msg from the client) if(message.type == "CLIENT_READY") { - // Remember this information since we won't - // have the cookie in further socket.io messages. - // This information will be used to check if - // the sessionId of this connection is still valid - // since it could have been deleted by the API. - sessioninfos[client.id].auth = - { - sessionID: message.sessionID, - padID: message.padId, - token : message.token, - password: message.password - }; + createSessionInfo(client, message); } // Note: message.sessionID is an entirely different kind of @@ -493,14 +497,19 @@ function handleSuggestUserName(client, message) return; } - var padId = sessioninfos[client.id].padId, - clients = socketio.sockets.clients(padId); + var padId = sessioninfos[client.id].padId; + var roomClients = [], room = socketio.sockets.adapter.rooms[padId]; + if (room) { + for (var id in room) { + roomClients.push(socketio.sockets.adapter.nsp.connected[id]); + } + } //search the author and send him this message - for(var i = 0; i < clients.length; i++) { - var session = sessioninfos[clients[i].id]; + for(var i = 0; i < roomClients.length; i++) { + var session = sessioninfos[roomClients[i].id]; if(session && session.author == message.data.payload.unnamedId) { - clients[i].json.send(message); + roomClients[i].json.send(message); break; } } @@ -694,6 +703,14 @@ function handleUserChanges(data, cb) // and can be applied after "c". try { + // a changeset can be based on an old revision with the same changes in it + // prevent eplite from accepting it TODO: better send the client a NEW_CHANGES + // of that revision + if(baseRev+1 == r && c == changeset) { + client.json.send({disconnect:"badChangeset"}); + stats.meter('failedChangesets').mark(); + return callback(new Error("Won't apply USER_CHANGES, because it contains an already accepted changeset")); + } changeset = Changeset.follow(c, changeset, false, apool); }catch(e){ client.json.send({disconnect:"badChangeset"}); @@ -724,7 +741,16 @@ function handleUserChanges(data, cb) return callback(new Error("Can't apply USER_CHANGES "+changeset+" with oldLen " + Changeset.oldLen(changeset) + " to document of length " + prevText.length)); } - pad.appendRevision(changeset, thisSession.author); + try + { + pad.appendRevision(changeset, thisSession.author); + } + catch(e) + { + client.json.send({disconnect:"badChangeset"}); + stats.meter('failedChangesets').mark(); + return callback(e) + } var correctionChangeset = _correctMarkersInPad(pad.atext, pad.pool); if (correctionChangeset) { @@ -753,7 +779,13 @@ function handleUserChanges(data, cb) exports.updatePadClients = function(pad, callback) { //skip this step if noone is on this pad - var roomClients = socketio.sockets.clients(pad.id); + var roomClients = [], room = socketio.sockets.adapter.rooms[pad.id]; + if (room) { + for (var id in room) { + roomClients.push(socketio.sockets.adapter.nsp.connected[id]); + } + } + if(roomClients.length==0) return callback(); @@ -766,10 +798,8 @@ exports.updatePadClients = function(pad, callback) var revCache = {}; //go trough all sessions on this pad - async.forEach(roomClients, function(client, callback) - { + async.forEach(roomClients, function(client, callback){ var sid = client.id; - //https://github.com/caolan/async#whilst //send them all new changesets async.whilst( @@ -816,10 +846,10 @@ exports.updatePadClients = function(pad, callback) client.json.send(wireMsg); } - - sessioninfos[sid].time = currentTime; - sessioninfos[sid].rev = r; - + if(sessioninfos[sid]){ + sessioninfos[sid].time = currentTime; + sessioninfos[sid].rev = r; + } callback(null); } ], callback); @@ -875,6 +905,48 @@ function _correctMarkersInPad(atext, apool) { return builder.toString(); } +function handleSwitchToPad(client, message) +{ + // clear the session and leave the room + var currentSession = sessioninfos[client.id]; + var padId = currentSession.padId; + var roomClients = [], room = socketio.sockets.adapter.rooms[padId]; + if (room) { + for (var id in room) { + roomClients.push(socketio.sockets.adapter.nsp.connected[id]); + } + } + + for(var i = 0; i < roomClients.length; i++) { + var sinfo = sessioninfos[roomClients[i].id]; + if(sinfo && sinfo.author == currentSession.author) { + // fix user's counter, works on page refresh or if user closes browser window and then rejoins + sessioninfos[roomClients[i].id] = {}; + roomClients[i].leave(padId); + } + } + + // start up the new pad + createSessionInfo(client, message); + handleClientReady(client, message); +} + +function createSessionInfo(client, message) +{ + // Remember this information since we won't + // have the cookie in further socket.io messages. + // This information will be used to check if + // the sessionId of this connection is still valid + // since it could have been deleted by the API. + sessioninfos[client.id].auth = + { + sessionID: message.sessionID, + padID: message.padId, + token : message.token, + password: message.password + }; +} + /** * Handles a CLIENT_READY. A CLIENT_READY is the first message from the client to the server. The Client sends his token * and the pad it wants to enter. The Server answers with the inital values (clientVars) of the pad @@ -998,6 +1070,11 @@ function handleClientReady(client, message) { authorManager.getAuthor(authorId, function(err, author) { + if(!author && !err) + { + messageLogger.error("There is no author for authorId:", authorId); + return callback(); + } if(ERR(err, callback)) return; historicalAuthorData[authorId] = {name: author.name, colorId: author.colorId}; // Filter author attribs (e.g. don't send author's pads to all clients) callback(); @@ -1015,7 +1092,13 @@ function handleClientReady(client, message) return callback(); //Check if this author is already on the pad, if yes, kick the other sessions! - var roomClients = socketio.sockets.clients(padIds.padId); + var roomClients = [], room = socketio.sockets.adapter.rooms[pad.id]; + if (room) { + for (var id in room) { + roomClients.push(socketio.sockets.adapter.nsp.connected[id]); + } + } + for(var i = 0; i < roomClients.length; i++) { var sinfo = sessioninfos[roomClients[i].id]; if(sinfo && sinfo.author == author) { @@ -1032,19 +1115,19 @@ function handleClientReady(client, message) sessioninfos[client.id].readonly = padIds.readonly; //Log creation/(re-)entering of a pad - client.get('remoteAddress', function(er, ip) { - //Anonymize the IP address if IP logging is disabled - if(settings.disableIPlogging) { - ip = 'ANONYMOUS'; - } + var ip = remoteAddress[client.id]; - if(pad.head > 0) { - accessLogger.info('[ENTER] Pad "'+padIds.padId+'": Client '+client.id+' with IP "'+ip+'" entered the pad'); - } - else if(pad.head == 0) { - accessLogger.info('[CREATE] Pad "'+padIds.padId+'": Client '+client.id+' with IP "'+ip+'" created the pad'); - } - }) + //Anonymize the IP address if IP logging is disabled + if(settings.disableIPlogging) { + ip = 'ANONYMOUS'; + } + + if(pad.head > 0) { + accessLogger.info('[ENTER] Pad "'+padIds.padId+'": Client '+client.id+' with IP "'+ip+'" entered the pad'); + } + else if(pad.head == 0) { + accessLogger.info('[CREATE] Pad "'+padIds.padId+'": Client '+client.id+' with IP "'+ip+'" created the pad'); + } //If this is a reconnect, we don't have to send the client the ClientVars again if(message.reconnect == true) @@ -1165,7 +1248,14 @@ function handleClientReady(client, message) client.broadcast.to(padIds.padId).json.send(messageToTheOtherUsers); //Run trough all sessions of this pad - async.forEach(socketio.sockets.clients(padIds.padId), function(roomClient, callback) + var roomClients = [], room = socketio.sockets.adapter.rooms[pad.id]; + if (room) { + for (var id in room) { + roomClients.push(socketio.sockets.adapter.nsp.connected[id]); + } + } + + async.forEach(roomClients, function(roomClient, callback) { var author; @@ -1561,8 +1651,16 @@ function composePadChangesets(padId, startNum, endNum, callback) * Get the number of users in a pad */ exports.padUsersCount = function (padID, callback) { + + var roomClients = [], room = socketio.sockets.adapter.rooms[padID]; + if (room) { + for (var id in room) { + roomClients.push(socketio.sockets.adapter.nsp.connected[id]); + } + } + callback(null, { - padUsersCount: socketio.sockets.clients(padID).length + padUsersCount: roomClients.length }); } @@ -1572,7 +1670,14 @@ exports.padUsersCount = function (padID, callback) { exports.padUsers = function (padID, callback) { var result = []; - async.forEach(socketio.sockets.clients(padID), function(roomClient, callback) { + var roomClients = [], room = socketio.sockets.adapter.rooms[padID]; + if (room) { + for (var id in room) { + roomClients.push(socketio.sockets.adapter.nsp.connected[id]); + } + } + + async.forEach(roomClients, function(roomClient, callback) { var s = sessioninfos[roomClient.id]; if(s) { authorManager.getAuthor(s.author, function(err, author) { diff --git a/src/node/handler/SocketIORouter.js b/src/node/handler/SocketIORouter.js index b3e046d2c..0a7361f42 100644 --- a/src/node/handler/SocketIORouter.js +++ b/src/node/handler/SocketIORouter.js @@ -24,6 +24,7 @@ var log4js = require('log4js'); var messageLogger = log4js.getLogger("message"); var securityManager = require("../db/SecurityManager"); var readOnlyManager = require("../db/ReadOnlyManager"); +var remoteAddress = require("../utils/RemoteAddress").remoteAddress; var settings = require('../utils/Settings'); /** @@ -56,11 +57,15 @@ exports.setSocketIO = function(_socket) { socket.sockets.on('connection', function(client) { + + // Broken: See http://stackoverflow.com/questions/4647348/send-message-to-specific-client-with-socket-io-and-node-js + // Fixed by having a persistant object, ideally this would actually be in the database layer + // TODO move to database layer if(settings.trustProxy && client.handshake.headers['x-forwarded-for'] !== undefined){ - client.set('remoteAddress', client.handshake.headers['x-forwarded-for']); + remoteAddress[client.id] = client.handshake.headers['x-forwarded-for']; } else{ - client.set('remoteAddress', client.handshake.address.address); + remoteAddress[client.id] = client.handshake.address; } var clientAuthorized = false; diff --git a/src/node/hooks/express.js b/src/node/hooks/express.js index c6573c800..e858b8008 100644 --- a/src/node/hooks/express.js +++ b/src/node/hooks/express.js @@ -56,7 +56,7 @@ exports.restartServer = function () { console.log( "SSL -- server key file: " + settings.ssl.key ); console.log( "SSL -- Certificate Authority's certificate file: " + settings.ssl.cert ); - options = { + var options = { key: fs.readFileSync( settings.ssl.key ), cert: fs.readFileSync( settings.ssl.cert ) }; diff --git a/src/node/hooks/express/adminplugins.js b/src/node/hooks/express/adminplugins.js index d8f19bba9..8e372f1c0 100644 --- a/src/node/hooks/express/adminplugins.js +++ b/src/node/hooks/express/adminplugins.js @@ -1,10 +1,8 @@ -var path = require('path'); var eejs = require('ep_etherpad-lite/node/eejs'); var installer = require('ep_etherpad-lite/static/js/pluginfw/installer'); var plugins = require('ep_etherpad-lite/static/js/pluginfw/plugins'); var _ = require('underscore'); var semver = require('semver'); -var async = require('async'); exports.expressCreateServer = function (hook_name, args, cb) { args.app.get('/admin/plugins', function(req, res) { @@ -14,7 +12,6 @@ exports.expressCreateServer = function (hook_name, args, cb) { search_results: {}, errors: [], }; - res.send( eejs.require("ep_etherpad-lite/templates/admin/plugins.html", render_args) ); }); args.app.get('/admin/plugins/info', function(req, res) { @@ -25,7 +22,8 @@ exports.expressCreateServer = function (hook_name, args, cb) { exports.socketio = function (hook_name, args, cb) { var io = args.io.of("/pluginfw/installer"); io.on('connection', function (socket) { - if (!socket.handshake.session.user || !socket.handshake.session.user.is_admin) return; + + if (!socket.conn.request.session || !socket.conn.request.session.user || !socket.conn.request.session.user.is_admin) return; socket.on("getInstalled", function (query) { // send currently installed plugins @@ -107,4 +105,4 @@ function sortPluginList(plugins, property, /*ASC?*/dir) { // a must be equal to b return 0; }) -} \ No newline at end of file +} diff --git a/src/node/hooks/express/adminsettings.js b/src/node/hooks/express/adminsettings.js index 2a48d2899..4986f093c 100644 --- a/src/node/hooks/express/adminsettings.js +++ b/src/node/hooks/express/adminsettings.js @@ -1,7 +1,5 @@ -var path = require('path'); var eejs = require('ep_etherpad-lite/node/eejs'); var settings = require('ep_etherpad-lite/node/utils/Settings'); -var installer = require('ep_etherpad-lite/static/js/pluginfw/installer'); var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks"); var fs = require('fs'); @@ -22,7 +20,8 @@ exports.expressCreateServer = function (hook_name, args, cb) { exports.socketio = function (hook_name, args, cb) { var io = args.io.of("/settings"); io.on('connection', function (socket) { - if (!socket.handshake.session.user || !socket.handshake.session.user.is_admin) return; + + if (!socket.conn.request.session || !socket.conn.request.session.user || !socket.conn.request.session.user.is_admin) return; socket.on("load", function (query) { fs.readFile('settings.json', 'utf8', function (err,data) { diff --git a/src/node/hooks/express/importexport.js b/src/node/hooks/express/importexport.js index f5a3e5a19..f3f051636 100644 --- a/src/node/hooks/express/importexport.js +++ b/src/node/hooks/express/importexport.js @@ -5,7 +5,7 @@ var importHandler = require('../../handler/ImportHandler'); exports.expressCreateServer = function (hook_name, args, cb) { args.app.get('/p/:pad/:rev?/export/:type', function(req, res, next) { - var types = ["pdf", "doc", "txt", "html", "odt", "dokuwiki"]; + var types = ["pdf", "doc", "txt", "html", "odt", "etherpad"]; //send a 404 if we don't support this filetype if (types.indexOf(req.params.type) == -1) { next(); diff --git a/src/node/hooks/express/padreadonly.js b/src/node/hooks/express/padreadonly.js index 9a0a52bfb..d60d38633 100644 --- a/src/node/hooks/express/padreadonly.js +++ b/src/node/hooks/express/padreadonly.js @@ -10,7 +10,6 @@ exports.expressCreateServer = function (hook_name, args, cb) { { var html; var padId; - var pad; async.series([ //translate the read only pad to a padId diff --git a/src/node/hooks/express/socketio.js b/src/node/hooks/express/socketio.js index 524bab3d9..b70aa50ed 100644 --- a/src/node/hooks/express/socketio.js +++ b/src/node/hooks/express/socketio.js @@ -1,6 +1,5 @@ -var log4js = require('log4js'); -var socketio = require('socket.io'); var settings = require('../../utils/Settings'); +var socketio = require('socket.io'); var socketIORouter = require("../../handler/SocketIORouter"); var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks"); var webaccess = require("ep_etherpad-lite/node/hooks/express/webaccess"); @@ -11,12 +10,19 @@ var connect = require('connect'); exports.expressCreateServer = function (hook_name, args, cb) { //init socket.io and redirect all requests to the MessageHandler - var io = socketio.listen(args.server); + // there shouldn't be a browser that isn't compatible to all + // transports in this list at once + // e.g. XHR is disabled in IE by default, so in IE it should use jsonp-polling + var io = socketio({ + transports: settings.socketTransportProtocols + }).listen(args.server); /* Require an express session cookie to be present, and load the * session. See http://www.danielbaulig.de/socket-ioexpress for more * info */ - io.set('authorization', function (data, accept) { + + io.use(function(socket, accept) { + var data = socket.request; if (!data.headers.cookie) return accept('No session cookie transmitted.', false); // Use connect's cookie parser, because it knows how to parse signed cookies @@ -36,35 +42,17 @@ exports.expressCreateServer = function (hook_name, args, cb) { }); }); - // there shouldn't be a browser that isn't compatible to all - // transports in this list at once - // e.g. XHR is disabled in IE by default, so in IE it should use jsonp-polling - io.set('transports', settings.socketTransportProtocols ); - - var socketIOLogger = log4js.getLogger("socket.io"); - io.set('logger', { - debug: function (str) - { - socketIOLogger.debug.apply(socketIOLogger, arguments); - }, - info: function (str) - { - socketIOLogger.info.apply(socketIOLogger, arguments); - }, - warn: function (str) - { - socketIOLogger.warn.apply(socketIOLogger, arguments); - }, - error: function (str) - { - socketIOLogger.error.apply(socketIOLogger, arguments); - }, - }); + // var socketIOLogger = log4js.getLogger("socket.io"); + // Debug logging now has to be set at an environment level, this is stupid. + // https://github.com/Automattic/socket.io/wiki/Migrating-to-1.0 + // This debug logging environment is set in Settings.js //minify socket.io javascript - if(settings.minify) - io.enable('browser client minification'); - + // Due to a shitty decision by the SocketIO team minification is + // no longer available, details available at: + // http://stackoverflow.com/questions/23981741/minify-socket-io-socket-io-js-with-1-0 + // if(settings.minify) io.enable('browser client minification'); + //Initalize the Socket.IO Router socketIORouter.setSocketIO(io); socketIORouter.addComponent("pad", padMessageHandler); diff --git a/src/node/hooks/express/static.js b/src/node/hooks/express/static.js index 7d654c1b2..c6a227451 100644 --- a/src/node/hooks/express/static.js +++ b/src/node/hooks/express/static.js @@ -1,11 +1,8 @@ -var path = require('path'); var minify = require('../../utils/Minify'); var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins"); var CachingMiddleware = require('../../utils/caching_middleware'); var settings = require("../../utils/Settings"); var Yajsml = require('yajsml'); -var fs = require("fs"); -var ERR = require("async-stacktrace"); var _ = require("underscore"); exports.expressCreateServer = function (hook_name, args, cb) { diff --git a/src/node/hooks/express/swagger.js b/src/node/hooks/express/swagger.js index e8daa61ce..b9308dee0 100644 --- a/src/node/hooks/express/swagger.js +++ b/src/node/hooks/express/swagger.js @@ -1,4 +1,3 @@ -var log4js = require('log4js'); var express = require('express'); var apiHandler = require('../../handler/APIHandler'); var apiCaller = require('./apicalls').apiCaller; @@ -356,7 +355,17 @@ exports.expressCreateServer = function (hook_name, args, cb) { args.app.use(basePath, subpath); - swagger.setAppHandler(subpath); + //hack! + var swagger_temp = swagger + swagger = swagger.createNew(subpath); + swagger.params = swagger_temp.params + swagger.queryParam = swagger_temp.queryParam + swagger.pathParam = swagger_temp.pathParam + swagger.bodyParam = swagger_temp.bodyParam + swagger.formParam = swagger_temp.formParam + swagger.headerParam = swagger_temp.headerParam + swagger.error = swagger_temp.error + //swagger.setAppHandler(subpath); swagger.addModels(swaggerModels); diff --git a/src/node/hooks/express/webaccess.js b/src/node/hooks/express/webaccess.js index 6998853f2..b798f2c78 100644 --- a/src/node/hooks/express/webaccess.js +++ b/src/node/hooks/express/webaccess.js @@ -2,7 +2,6 @@ var express = require('express'); var log4js = require('log4js'); var httpLogger = log4js.getLogger("http"); var settings = require('../../utils/Settings'); -var randomString = require('ep_etherpad-lite/static/js/pad_utils').randomString; var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); var ueberStore = require('../../db/SessionStore'); var stats = require('ep_etherpad-lite/node/stats') diff --git a/src/node/hooks/i18n.js b/src/node/hooks/i18n.js index 62631b937..678156596 100644 --- a/src/node/hooks/i18n.js +++ b/src/node/hooks/i18n.js @@ -1,7 +1,6 @@ var languages = require('languages4translatewiki') , fs = require('fs') , path = require('path') - , express = require('express') , _ = require('underscore') , npm = require('npm') , plugins = require('ep_etherpad-lite/static/js/pluginfw/plugins.js').plugins diff --git a/src/node/utils/Abiword.js b/src/node/utils/Abiword.js index 5f12bd975..1d9ac5d30 100644 --- a/src/node/utils/Abiword.js +++ b/src/node/utils/Abiword.js @@ -18,7 +18,6 @@ * limitations under the License. */ -var util = require('util'); var spawn = require('child_process').spawn; var async = require("async"); var settings = require("./Settings"); diff --git a/src/node/utils/ExportDokuWiki.js b/src/node/utils/ExportDokuWiki.js deleted file mode 100644 index f5d2d177f..000000000 --- a/src/node/utils/ExportDokuWiki.js +++ /dev/null @@ -1,350 +0,0 @@ -/** - * Copyright 2011 Adrian Lang - * - * 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"); - -function getPadDokuWiki(pad, revNum, callback) -{ - var atext = pad.atext; - var dokuwiki; - async.waterfall([ - // fetch revision atext - - - function (callback) - { - if (revNum != undefined) - { - pad.getInternalRevisionAText(revNum, function (err, revisionAtext) - { - atext = revisionAtext; - callback(err); - }); - } - else - { - callback(null); - } - }, - - // convert atext to dokuwiki text - - function (callback) - { - dokuwiki = getDokuWikiFromAtext(pad, atext); - callback(null); - }], - // run final callback - - - function (err) - { - callback(err, dokuwiki); - }); -} - -function getDokuWikiFromAtext(pad, atext) -{ - var apool = pad.apool(); - var textLines = atext.text.slice(0, -1).split('\n'); - var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text); - - var tags = ['======', '=====', '**', '//', '__', 'del>']; - var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough']; - var anumMap = {}; - - props.forEach(function (propName, i) - { - var propTrueNum = apool.putAttrib([propName, true], true); - if (propTrueNum >= 0) - { - anumMap[propTrueNum] = i; - } - }); - - function getLineDokuWiki(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, - // Just bold Bold and italics Just italics - // becomes - // Just bold Bold and italics Just italics - var taker = Changeset.stringIterator(text); - var assem = Changeset.stringAssembler(); - - function emitOpenTag(i) - { - if (tags[i].indexOf('>') !== -1) { - assem.append('<'); - } - assem.append(tags[i]); - } - - function emitCloseTag(i) - { - if (tags[i].indexOf('>') !== -1) { - assem.append(' 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 - } - } - } - - for (var i = propVals.length - 1; i >= 0; i--) - { - if (propVals[i] === LEAVE) - { - emitCloseTag(i); - propVals[i] = false; - } - else if (propVals[i] === STAY) - { - emitCloseTag(i); - } - } - for (var i = 0; i < propVals.length; i++) - { - if (propVals[i] === ENTER || propVals[i] === STAY) - { - emitOpenTag(i); - 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); - - assem.append(_escapeDokuWiki(s)); - } // end iteration over spans in line - for (var i = propVals.length - 1; i >= 0; i--) - { - if (propVals[i]) - { - emitCloseTag(i); - propVals[i] = false; - } - } - } // end processNextChars - if (urls) - { - urls.forEach(function (urlData) - { - var startIndex = urlData[0]; - var url = urlData[1]; - var urlLength = url.length; - processNextChars(startIndex - idx); - assem.append('[['); - - // Do not use processNextChars since a link does not contain syntax and - // needs no escaping - var iter = Changeset.opIterator(Changeset.subattribution(attribs, idx, idx + urlLength)); - idx += urlLength; - assem.append(taker.take(iter.next().chars)); - - assem.append(']]'); - }); - } - processNextChars(text.length - idx); - - return assem.toString() + "\n"; - } // end getLineDokuWiki - var pieces = []; - - for (var i = 0; i < textLines.length; i++) - { - var line = _analyzeLine(textLines[i], attribLines[i], apool); - var lineContent = getLineDokuWiki(line.text, line.aline); - - if (line.listLevel && lineContent) - { - if (line.listTypeName == "number") - { - pieces.push(new Array(line.listLevel + 1).join(' ') + ' - '); - } else { - pieces.push(new Array(line.listLevel + 1).join(' ') + '* '); - } - } - pieces.push(lineContent); - } - - 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.getPadDokuWikiDocument = function (padId, revNum, callback) -{ - padManager.getPad(padId, function (err, pad) - { - if (err) - { - callback(err); - return; - } - - getPadDokuWiki(pad, revNum, callback); - }); -}; - -function _escapeDokuWiki(s) -{ - s = s.replace(/(\/\/|\*\*|__)/g, '%%$1%%'); - return s; -} - -// 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_SPACE = /\s/; -var _REGEX_URLCHAR = new RegExp('(' + /[-:@a-zA-Z0-9_.,~%+\/\\?=&#;()$]/.source + '|' + _REGEX_WORDCHAR.source + ')'); -var _REGEX_URL = new RegExp(/(?:(?:https?|s?ftp|ftps|file|smb|afp|nfs|(x-)?man|gopher|txmt):\/\/|mailto:)/.source + _REGEX_URLCHAR.source + '*(?![:.,;])' + _REGEX_URLCHAR.source, 'g'); - -// returns null if no URLs, or [[startIndex1, url1], [startIndex2, url2], ...] - - -function _findURLs(text) -{ - _REGEX_URL.lastIndex = 0; - var urls = null; - var execResult; - while ((execResult = _REGEX_URL.exec(text))) - { - urls = (urls || []); - var startIndex = execResult.index; - var url = execResult[0]; - urls.push([startIndex, url]); - } - - return urls; -} diff --git a/src/node/utils/ExportEtherpad.js b/src/node/utils/ExportEtherpad.js new file mode 100644 index 000000000..36df452da --- /dev/null +++ b/src/node/utils/ExportEtherpad.js @@ -0,0 +1,68 @@ +/** + * 2014 John McLear (Etherpad Foundation / McLear 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 db = require("../db/DB").db; +var ERR = require("async-stacktrace"); + +exports.getPadRaw = function(padId, callback){ + async.waterfall([ + function(cb){ + + // Get the Pad available content keys + db.findKeys("pad:"+padId+"*", null, function(err,records){ + if(!err){ + cb(err, records); + } + }) + }, + function(records, cb){ + var data = {}; + + async.forEachSeries(Object.keys(records), function(key, r){ + + // For each piece of info about a pad. + db.get(records[key], function(err, entry){ + data[records[key]] = entry; + + // Get the Pad Authors + if(entry.pool && entry.pool.numToAttrib){ + var authors = entry.pool.numToAttrib; + async.forEachSeries(Object.keys(authors), function(k, c){ + if(authors[k][0] === "author"){ + var authorId = authors[k][1]; + + // Get the author info + db.get("globalAuthor:"+authorId, function(e, authorEntry){ + if(!e) data["globalAuthor:"+authorId] = authorEntry; + }); + + } + // console.log("authorsK", authors[k]); + c(null); + }); + } + r(null); // callback; + }); + }, function(err){ + cb(err, data); + }) + } + ], function(err, data){ + callback(null, data); + }); +} diff --git a/src/node/utils/ExportHelper.js b/src/node/utils/ExportHelper.js index 136896f06..3297c6d36 100644 --- a/src/node/utils/ExportHelper.js +++ b/src/node/utils/ExportHelper.js @@ -18,12 +18,7 @@ * 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()); diff --git a/src/node/utils/ExportHtml.js b/src/node/utils/ExportHtml.js index 01920da79..c882e0ef6 100644 --- a/src/node/utils/ExportHtml.js +++ b/src/node/utils/ExportHtml.js @@ -78,6 +78,14 @@ function getHTMLFromAtext(pad, atext, authorColors) var tags = ['h1', 'h2', 'strong', 'em', 'u', 's']; var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough']; + + hooks.aCallAll("exportHtmlAdditionalTags", pad, function(err, newProps){ + newProps.forEach(function (propName, i){ + tags.push(propName); + props.push(propName); + }); + }); + // holds a map of used styling attributes (*1, *2, etc) in the apool // and maps them to an index in props // *3:2 -> the attribute *3 means strong @@ -297,10 +305,12 @@ function getHTMLFromAtext(pad, atext, authorColors) // want to deal gracefully with blank lines. // => keeps track of the parents level of indentation var lists = []; // e.g. [[1,'bullet'], [3,'bullet'], ...] + var listLevels = [] for (var i = 0; i < textLines.length; i++) { var line = _analyzeLine(textLines[i], attribLines[i], apool); var lineContent = getLineHTML(line.text, line.aline); + listLevels.push(line.listLevel) if (line.listLevel)//If we are inside a list { @@ -320,13 +330,27 @@ function getHTMLFromAtext(pad, atext, authorColors) if (whichList >= lists.length)//means we are on a deeper level of indentation than the previous line { + if(lists.length > 0){ + pieces.push('') + } lists.push([line.listLevel, line.listTypeName]); + + // if there is a previous list we need to open x tags, where x is the difference of the levels + // if there is no previous list we need to open x tags, where x is the wanted level + var toOpen = lists.length > 1 ? line.listLevel - lists[lists.length - 2][0] - 1 : line.listLevel - 1 + if(line.listTypeName == "number") { + if(toOpen > 0){ + pieces.push(new Array(toOpen + 1).join('
    ')) + } pieces.push('
    1. ', lineContent || '
      '); } else { + if(toOpen > 0){ + pieces.push(new Array(toOpen + 1).join('
        ')) + } pieces.push('
        • ', lineContent || '
          '); } } @@ -355,37 +379,40 @@ function getHTMLFromAtext(pad, atext, authorColors) pieces.push('

          '); } }*/ - else//means we are getting closer to the lowest level of indentation + else//means we are getting closer to the lowest level of indentation or are at the same level { - while (whichList < lists.length - 1) - { + var toClose = lists.length > 0 ? listLevels[listLevels.length - 2] - line.listLevel : 0 + if( toClose > 0){ + pieces.push('
        • ') if(lists[lists.length - 1][1] == "number") { - pieces.push('
    '); + pieces.push(new Array(toClose+1).join('
')) + pieces.push('
  • ', lineContent || '
    '); } else { - pieces.push('
  • '); + pieces.push(new Array(toClose+1).join('')) + pieces.push('
  • ', lineContent || '
    '); } - lists.length--; + lists = lists.slice(0,whichList+1) + } else { + pieces.push('
  • ', lineContent || '
    '); } - pieces.push('
  • ', lineContent || '
    '); } } - else//outside any list + else//outside any list, need to close line.listLevel of lists { - while (lists.length > 0)//if was in a list: close it before - { - if(lists[lists.length - 1][1] == "number") - { + if(lists.length > 0){ + if(lists[lists.length - 1][1] == "number"){ pieces.push('
  • '); - } - else - { + pieces.push(new Array(listLevels[listLevels.length - 2]).join('')) + } else { pieces.push(''); + pieces.push(new Array(listLevels[listLevels.length - 2]).join('')) } - lists.length--; } + lists = [] + var lineContentFromHook = hooks.callAllStr("getLineHTMLForExport", { line: line, @@ -425,37 +452,120 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback) { if(ERR(err, callback)) return; - var head = - (noDocType ? '' : '\n') + - '\n' + (noDocType ? '' : '\n' + - '' + Security.escapeHTML(padId) + '\n' + - '\n' + - '\n' + '\n') + - ''; + var stylesForExportCSS = ""; + // Include some Styles into the Head for Export + hooks.aCallAll("stylesForExport", padId, function(err, stylesForExport){ + stylesForExport.forEach(function(css){ + stylesForExportCSS += css; + }); + // Core inclusion of head etc. + var head = + (noDocType ? '' : '\n') + + '\n' + (noDocType ? '' : '\n' + + '' + Security.escapeHTML(padId) + '\n' + + '\n' + + '\n' + '\n') + + ''; + var foot = '\n\n'; + + getPadHTML(pad, revNum, function (err, html) + { + if(ERR(err, callback)) return; + callback(null, head + html + foot); + }); }); }); }; - // 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_SPACE = /\s/; diff --git a/src/node/utils/ExportTxt.js b/src/node/utils/ExportTxt.js index f0b62743a..a6bec4a58 100644 --- a/src/node/utils/ExportTxt.js +++ b/src/node/utils/ExportTxt.js @@ -22,9 +22,6 @@ 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 @@ -82,7 +79,6 @@ function getTXTFromAtext(pad, atext, authorColors) 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 = ""; @@ -110,7 +106,6 @@ function getTXTFromAtext(pad, atext, authorColors) // Just bold Bold and italics Just italics var taker = Changeset.stringIterator(text); var assem = Changeset.stringAssembler(); - var openTags = []; var idx = 0; @@ -250,7 +245,6 @@ function getTXTFromAtext(pad, atext, authorColors) // 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); diff --git a/src/node/utils/ImportEtherpad.js b/src/node/utils/ImportEtherpad.js new file mode 100644 index 000000000..8daeb5363 --- /dev/null +++ b/src/node/utils/ImportEtherpad.js @@ -0,0 +1,55 @@ +/** + * 2014 John McLear (Etherpad Foundation / McLear 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 log4js = require('log4js'); +var async = require("async"); +var db = require("../db/DB").db; + +exports.setPadRaw = function(padId, records, callback){ + records = JSON.parse(records); + + async.eachSeries(Object.keys(records), function(key, cb){ + var value = records[key] + + // we know its an author + if(value.padIDs){ + // rewrite author pad ids + value.padIDs[padId] = 1; + var newKey = key; + + }else{ + // we can split it to look to see if its pad data + var oldPadId = key.split(":"); + + // we know its pad data.. + if(oldPadId[0] === "pad"){ + + // so set the new pad id for the author + oldPadId[1] = padId; + + // and create the value + var newKey = oldPadId.join(":"); // create the new key + } + + } + // Write the value to the server + db.set(newKey, value); + + cb(); + }, function(){ + callback(null, true); + }); +} diff --git a/src/node/utils/ImportHtml.js b/src/node/utils/ImportHtml.js index abba2ac19..59802f9bf 100644 --- a/src/node/utils/ImportHtml.js +++ b/src/node/utils/ImportHtml.js @@ -14,25 +14,22 @@ * limitations under the License. */ -var jsdom = require('jsdom-nocontextifiy').jsdom; var log4js = require('log4js'); - - var Changeset = require("ep_etherpad-lite/static/js/Changeset"); var contentcollector = require("ep_etherpad-lite/static/js/contentcollector"); +var cheerio = require("cheerio"); function setPadHTML(pad, html, callback) { var apiLogger = log4js.getLogger("ImportHtml"); - // Parse the incoming HTML with jsdom - try{ - var doc = jsdom(html.replace(/>\n+<')); - }catch(e){ - apiLogger.warn("Error importing, possibly caused by malformed HTML"); - var doc = jsdom("
    Error during import, possibly malformed HTML
    "); - } + var $ = cheerio.load(html); + // Appends a line break, used by Etherpad to ensure a caret is available + // below the last line of an import + $('body').append("

    "); + + var doc = $('html')[0]; apiLogger.debug('html:'); apiLogger.debug(html); @@ -40,7 +37,7 @@ function setPadHTML(pad, html, callback) // using the content collector object var cc = contentcollector.makeContentCollector(true, null, pad.pool); try{ // we use a try here because if the HTML is bad it will blow up - cc.collectContent(doc.childNodes[0]); + cc.collectContent(doc); }catch(e){ apiLogger.warn("HTML was not properly formed", e); return; // We don't process the HTML because it was bad.. diff --git a/src/node/utils/Minify.js b/src/node/utils/Minify.js index 58d08b30e..7b868307d 100644 --- a/src/node/utils/Minify.js +++ b/src/node/utils/Minify.js @@ -28,7 +28,7 @@ var jsp = require("uglify-js").parser; var pro = require("uglify-js").uglify; var path = require('path'); var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins"); -var RequireKernel = require('require-kernel'); +var RequireKernel = require('etherpad-require-kernel'); var urlutil = require('url'); var ROOT_DIR = path.normalize(__dirname + "/../../static/"); @@ -261,7 +261,6 @@ function getAceFile(callback) { // them into the file. async.forEach(founds, function (item, callback) { var filename = item.match(/"([^"]*)"/)[1]; - var request = require('request'); var baseURI = 'http://localhost:' + settings.port; var resourceURI = baseURI + path.normalize(path.join('/static/', filename)); diff --git a/src/node/utils/RemoteAddress.js b/src/node/utils/RemoteAddress.js new file mode 100644 index 000000000..86a4a5b26 --- /dev/null +++ b/src/node/utils/RemoteAddress.js @@ -0,0 +1 @@ +exports.remoteAddress = {}; diff --git a/src/node/utils/Settings.js b/src/node/utils/Settings.js index c455617b0..af7ede811 100644 --- a/src/node/utils/Settings.js +++ b/src/node/utils/Settings.js @@ -129,6 +129,11 @@ exports.minify = true; */ exports.abiword = null; +/** + * Should we support none natively supported file types on import? + */ +exports.allowUnknownFileEnds = true; + /** * The log level of log4js */ @@ -228,6 +233,7 @@ exports.reloadSettings = function reloadSettings() { log4js.configure(exports.logconfig);//Configure the logging appenders log4js.setGlobalLogLevel(exports.loglevel);//set loglevel + process.env['DEBUG'] = 'socket.io:' + exports.loglevel; // Used by SocketIO for Debug log4js.replaceConsole(); if(!exports.sessionKey){ // If the secretKey isn't set we also create yet another unique value here diff --git a/src/node/utils/caching_middleware.js b/src/node/utils/caching_middleware.js index d30dc398b..971343561 100644 --- a/src/node/utils/caching_middleware.js +++ b/src/node/utils/caching_middleware.js @@ -19,7 +19,6 @@ var Buffer = require('buffer').Buffer; var fs = require('fs'); var path = require('path'); var zlib = require('zlib'); -var util = require('util'); var settings = require('./Settings'); var semver = require('semver'); diff --git a/src/node/utils/tar.json b/src/node/utils/tar.json index 70001f8f2..05d764a79 100644 --- a/src/node/utils/tar.json +++ b/src/node/utils/tar.json @@ -2,6 +2,7 @@ "pad.js": [ "pad.js" , "pad_utils.js" + , "browser.js" , "pad_cookie.js" , "pad_editor.js" , "pad_editbar.js" @@ -24,6 +25,7 @@ , "colorutils.js" , "draggable.js" , "pad_utils.js" + , "browser.js" , "pad_cookie.js" , "pad_editor.js" , "pad_editbar.js" @@ -42,6 +44,7 @@ ] , "ace2_inner.js": [ "ace2_inner.js" + , "browser.js" , "AttributePool.js" , "Changeset.js" , "ChangesetUtils.js" @@ -58,6 +61,7 @@ ] , "ace2_common.js": [ "ace2_common.js" + , "browser.js" , "jquery.js" , "rjquery.js" , "$async.js" diff --git a/src/node/utils/toolbar.js b/src/node/utils/toolbar.js index a4ee202c9..a5d30f960 100644 --- a/src/node/utils/toolbar.js +++ b/src/node/utils/toolbar.js @@ -4,7 +4,6 @@ var _ = require("underscore") , tagAttributes , tag - , defaultButtons , Button , ButtonsGroup , Separator @@ -99,8 +98,8 @@ _.extend(Button.prototype, { "data-key": this.attributes.command, }; return tag("li", liAttributes, - tag("a", { "class": this.grouping }, - tag("span", { "class": " "+ this.attributes.class, "data-l10n-id": this.attributes.localizationId }) + tag("a", { "class": this.grouping, "data-l10n-id": this.attributes.localizationId }, + tag("span", { "class": " "+ this.attributes.class }) ) ); } @@ -122,8 +121,7 @@ _.extend(SelectButton.prototype, Button.prototype, { }, select: function (attributes) { - var self = this - , options = []; + var options = []; _.each(this.options, function (opt) { var a = _.extend({ @@ -203,13 +201,13 @@ module.exports = { settings: defaultButtonAttributes("settings"), embed: defaultButtonAttributes("embed"), showusers: defaultButtonAttributes("showusers"), - + timeslider_export: { command: "import_export", localizationId: "timeslider.toolbar.exportlink.title", class: "buttonicon buttonicon-import_export" }, - + timeslider_returnToPad: { command: "timeslider_returnToPad", localizationId: "timeslider.toolbar.returnbutton", diff --git a/src/package.json b/src/package.json index 18556aad4..b92477d66 100644 --- a/src/package.json +++ b/src/package.json @@ -12,35 +12,37 @@ ], "dependencies" : { "yajsml" : "1.1.6", - "request" : "2.9.100", - "require-kernel" : "1.0.5", - "resolve" : "0.2.x", - "socket.io" : "0.9.x", - "ueberDB" : ">=0.2.2", - "express" : "3.1.0", - "async" : "0.1.x", + "request" : ">=2.48.0", + "etherpad-require-kernel" : ">=1.0.7", + "resolve" : ">=1.0.0", + "socket.io" : ">=1.2.0", + "ueberDB" : ">=0.2.9", + "express" : ">3.1.0 <3.9.0", + "async" : ">=0.9.0", "connect" : "2.7.x", "clean-css" : "0.3.2", - "uglify-js" : "1.2.5", - "formidable" : "1.0.9", - "log4js" : "0.6.6", + "uglify-js" : ">=2.4.15", + "formidable" : ">=1.0.15", + "log4js" : ">=0.6.21", "nodemailer" : "0.3.x", - "jsdom-nocontextifiy" : "0.2.10", - "async-stacktrace" : "0.0.2", - "npm" : "1.4.x", - "ejs" : "0.6.1", - "graceful-fs" : "1.1.5", - "slide" : "1.1.3", - "semver" : "1.0.13", + "cheerio" : ">=0.18.0", + "async-stacktrace" : ">=0.0.2", + "npm" : ">=2.1.x", + "ejs" : ">=1.0.0", + "graceful-fs" : ">=3.0.4", + "slide" : ">=1.1.6", + "semver" : ">=2.3.0", "security" : "1.0.0", - "tinycon" : "0.0.1", - "underscore" : "1.3.1", - "unorm" : "1.0.0", - "languages4translatewiki" : "0.1.3", - "swagger-node-express" : "1.2.3", + "tinycon" : ">=0.0.1", + "underscore" : "1.5.1", + "unorm" : ">=1.3.3", + "languages4translatewiki" : ">=0.1.3", + "swagger-node-express" : ">=2.1.0", "channels" : "0.0.x", - "jsonminify" : "0.2.2", - "measured" : "0.1.3" + "jsonminify" : ">=0.2.3", + "measured" : ">=0.1.6", + "mocha" : ">=2.0.1", + "supertest" : ">=0.15.0" }, "bin": { "etherpad-lite": "./node/server.js" }, "devDependencies": { @@ -52,5 +54,5 @@ "repository" : { "type" : "git", "url" : "http://github.com/ether/etherpad-lite.git" }, - "version" : "1.4.1" + "version" : "1.5.0" } diff --git a/src/static/css/iframe_editor.css b/src/static/css/iframe_editor.css index b88db7a1d..1f247e59a 100644 --- a/src/static/css/iframe_editor.css +++ b/src/static/css/iframe_editor.css @@ -28,6 +28,14 @@ ul.list-bullet5 { margin-left: 7.5em; } ul.list-bullet6 { margin-left: 9em; } ul.list-bullet7 { margin-left: 10.5em; } ul.list-bullet8 { margin-left: 12em; } +ul.list-bullet9 { margin-left: 13.5em; } +ul.list-bullet10 { margin-left: 15em; } +ul.list-bullet11 { margin-left: 16.5em; } +ul.list-bullet12 { margin-left: 18em; } +ul.list-bullet13 { margin-left: 19.5em; } +ul.list-bullet14 { margin-left: 21em; } +ul.list-bullet15 { margin-left: 22.5em; } +ul.list-bullet16 { margin-left: 24em; } ul { list-style-type: disc; } ul.list-bullet1 { list-style-type: disc; } @@ -38,6 +46,14 @@ ul.list-bullet5 { list-style-type: circle; } ul.list-bullet6 { list-style-type: square; } ul.list-bullet7 { list-style-type: disc; } ul.list-bullet8 { list-style-type: circle; } +ul.list-bullet9 { list-style-type: disc; } +ul.list-bullet10 { list-style-type: circle; } +ul.list-bullet11 { list-style-type: square; } +ul.list-bullet12 { list-style-type: disc; } +ul.list-bullet13 { list-style-type: circle; } +ul.list-bullet14 { list-style-type: square; } +ul.list-bullet15 { list-style-type: disc; } +ul.list-bullet16 { list-style-type: circle; } ul.list-indent1 { margin-left: 1.5em; } ul.list-indent2 { margin-left: 3em; } @@ -47,15 +63,19 @@ ul.list-indent5 { margin-left: 7.5em; } ul.list-indent6 { margin-left: 9em; } ul.list-indent7 { margin-left: 10.5em; } ul.list-indent8 { margin-left: 12em; } +ul.list-indent9 { margin-left: 13.5em; } +ul.list-indent10 { margin-left: 15em; } +ul.list-indent11 { margin-left: 16.5em; } +ul.list-indent12 { margin-left: 18em; } +ul.list-indent13 { margin-left: 19.5em; } +ul.list-indent14 { margin-left: 21em; } +ul.list-indent15 { margin-left: 22.5em; } +ul.list-indent16 { margin-left: 24em; } -ul.list-indent1 { list-style-type: none; } -ul.list-indent2 { list-style-type: none; } -ul.list-indent3 { list-style-type: none; } -ul.list-indent4 { list-style-type: none; } -ul.list-indent5 { list-style-type: none; } -ul.list-indent6 { list-style-type: none; } -ul.list-indent7 { list-style-type: none; } -ul.list-indent8 { list-style-type: none; } +ul.list-indent1, ul.list-indent2, ul.list-indent3, ul.list-indent4, ul.list-indent5, +ul.list-indent6, ul.list-indent7, ul.list-indent8, ul.list-indent9, ul.list-indent10, +ul.list-indent11, ul.list-indent12, ul.list-indent13, +ul.list-indent14, ul.list-indent15, ul.list-indent16 { list-style-type: none; } body { margin: 0; @@ -184,6 +204,14 @@ ol.list-number5{ text-indent: 40px; } ol.list-number6{ text-indent: 50px; } ol.list-number7{ text-indent: 60px; } ol.list-number8{ text-indent: 70px; } +ol.list-number9{ text-indent: 80px; } +ol.list-number10{ text-indent: 90px; } +ol.list-number11{ text-indent: 100px; } +ol.list-number12{ text-indent: 110px; } +ol.list-number13{ text-indent: 120px; } +ol.list-number14{ text-indent: 130px; } +ol.list-number15{ text-indent: 140px; } +ol.list-number16{ text-indent: 150px; } /* Add styling to the first item in a list */ @@ -195,6 +223,14 @@ ol.list-number8{ text-indent: 70px; } .list-start-number6 { counter-reset: sixth; } .list-start-number7 { counter-reset: seventh; } .list-start-number8 { counter-reset: eighth; } +.list-start-number9 { counter-reset: ninth; } +.list-start-number10 { counter-reset: tenth; } +.list-start-number11 { counter-reset: eleventh; } +.list-start-number12 { counter-reset: twelth; } +.list-start-number13 { counter-reset: thirteenth; } +.list-start-number14 { counter-reset: fourteenth; } +.list-start-number15 { counter-reset: fifteenth; } +.list-start-number16 { counter-reset: sixteenth; } /* The behavior for incrementing and the prefix */ .list-number1 li:before { @@ -233,6 +269,47 @@ ol.list-number8{ text-indent: 70px; } } .list-number8 li:before { - content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(eighth) ". " ; + content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) ". " ; counter-increment: eighth 1; } + +.list-number9 li:before { + content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) "." counter(ninth) ". "; + counter-increment: ninth 1; +} + +.list-number10 li:before { + content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) "." counter(ninth) "." counter(tenth) ". "; + counter-increment: tenth 1; +} + +.list-number11 li:before { + content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) ". "; + counter-increment: eleventh 1; +} + +.list-number12 li:before { + content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) "." counter(twelth) ". "; + counter-increment: twelth 1; +} + +.list-number13 li:before { + content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(seventh) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) "." counter(twelth) "." counter(thirteenth) ". "; + counter-increment: thirteenth 1; +} + +.list-number14 li:before { + content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) "." counter(twelth) "." counter(thirteenth) "." counter(fourteenth) ". "; + counter-increment: fourteenth 1; +} + +.list-number15 li:before { + content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) "." counter(twelth) "." counter(thirteenth) "." counter(fourteenth) "." counter(fifteenth) ". "; + counter-increment: fifteenth 1; +} + +.list-number16 li:before { + content: counter(first) "." counter(second) "." counter(third) "." counter(fourth) "." counter(fifth) "." counter(sixth) "." counter(eighth) "." counter(ninth) "." counter(tenth) "." counter(eleventh) "." counter(twelth) "." counter(thirteenth) "." counter(fourteenth) "." counter(fifteenth) "." counter(sixteenth) ". "; + counter-increment: fixteenth 1; +} + diff --git a/src/static/css/pad.css b/src/static/css/pad.css index 4053ebbad..4ba9f5750 100644 --- a/src/static/css/pad.css +++ b/src/static/css/pad.css @@ -59,7 +59,7 @@ a img { height: 32px; } .toolbar ul { - position: relative; + position: absolute; list-style: none; padding-right: 3px; padding-left: 1px; @@ -67,12 +67,14 @@ a img { overflow: hidden; float: left } -.toolbar ul.menu_right { - float: right -} .toolbar ul li { float: left; margin-left: 2px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + height:32px; } .toolbar ul li.separator { border: inherit; @@ -80,6 +82,7 @@ a img { visibility: hidden; width: 0px; padding: 5px; + height:22px; } .toolbar ul li a:hover { text-decoration: none; @@ -103,6 +106,17 @@ a img { -moz-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; box-shadow: 0 0 8px rgba(0,0,0,.1) inset; } +.toolbar ul li .activeButton { + background: #eee; + background: -webkit-linear-gradient(#ddd, #fff); + background: -moz-linear-gradient(#ddd, #fff); + background: -o-linear-gradient(#ddd, #fff); + background: -ms-linear-gradient(#ddd, #fff); + background: linear-gradient(#ddd, #fff); + -webkit-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; + -moz-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; + box-shadow: 0 0 8px rgba(0,0,0,.1) inset; +} .toolbar ul li a { background: #fff; background: -webkit-linear-gradient(#fff, #f0f0f0); @@ -160,15 +174,28 @@ a img { border: 1px solid #ccc; outline: none; } -#usericon a { +.toolbar ul.menu_left { + left:0px; + right:250px; +} + +.toolbar ul.menu_right { + right:0px; +} + +li[data-key=showusers] > a { min-width: 30px; text-align: left; } -#usericon a #online_count { +li[data-key=showusers] > a #online_count { color: #777; - font-size: 10px; + font-size: 11px; position: relative; top: 2px; + padding-left: 2px; +} +#editbar{ + display:none; } #editorcontainer { position: absolute; @@ -209,6 +236,41 @@ a img { padding:10px; } +.loadingAnimation{ + -webkit-animation: loadingAnimation 2s infinite linear; + animation: loadingAnimation 2s infinite linear; + font-family: "fontawesome-etherpad"; + font-size:24px; + z-index:150; + width:25px; + height:25px; +} + +.loadingAnimation:before{ + content: "\e80e"; +} + +@-webkit-keyframes loadingAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} +@keyframes loadingAnimation { + 0% { + -webkit-transform: rotate(0deg); + transform: rotate(0deg); + } + 100% { + -webkit-transform: rotate(359deg); + transform: rotate(359deg); + } +} + #editorcontainerbox { position: absolute; bottom: 0; @@ -386,6 +448,12 @@ table#otheruserstable { height: 13px; overflow: hidden; margin: 0 4px; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; } .usertdswatch { width: 1% @@ -596,38 +664,49 @@ table#otheruserstable { margin-top: 4px; background-repeat: no-repeat; padding-left: 25px; - background-image: url("../../static/img/etherpad_lite_icons.png"); color: #333; text-decoration: none; padding-bottom:2px; + display:inline; + padding-left:5px; + font-family: "Arial"; } -#exporthtml { - background-position: 0px -299px +.exportlink{ + font-family: "fontawesome-etherpad"; + display:block; + margin:5px; + color:#666; } -#exportplain { - background-position: 0px -395px +#exporthtmla:before { + content: "\e826"; } -#exportword { - background-position: 0px -275px +#exportplaina:before { + content: "\e802"; } -#exportpdf { - background-position: 0px -371px +#exportworda:before { + content: "\e804"; } -#exportopen { - background-position: 0px -347px +#exportpdfa:before { + content: "\e803"; } -#exportdokuwiki { - background-position: 0px -459px +#exportetherpada:before { + content: "\e806"; +} +#exportopena:before { + content: "\e805"; } /* hidden element */ #importstatusball, -#importarrow, #importmessagesuccess, #importmessageabiword { display: none; } +.throbbold{ + font-weight:bold; +} + #importmessageabiword { color: #900; font-size: small; @@ -637,9 +716,6 @@ table#otheruserstable { margin-top: 12px; padding:2px 4px 2px 4px; } -#importstatusball { - height: 50px -} #chatthrob { display: none; position: absolute; @@ -664,64 +740,68 @@ table#otheruserstable { .buttonicon { width: 16px; height: 16px; - background-image: url('../../static/img/etherpad_lite_icons.png'); - background-repeat: no-repeat; display: inline-block; vertical-align: middle; + + font-family: "fontawesome-etherpad"; + font-size: 15px; + font-style: normal; + font-weight: normal; + color: #666; } -.buttonicon-bold { - background-position: 0px -116px +.buttonicon-bold:before { + content: "\e81c"; } -.buttonicon-italic { - background-position: 0px 0px +.buttonicon-italic:before { + content: "\e81d"; } -.buttonicon-underline { - background-position: 0px -236px +.buttonicon-underline:before { + content: "\e817"; } -.buttonicon-strikethrough { - background-position: 0px -200px +.buttonicon-strikethrough:before { + content: "\e818"; } -.buttonicon-insertorderedlist { - background-position: 0px -477px +.buttonicon-insertorderedlist:before { + content: "\e816"; } -.buttonicon-insertunorderedlist { - background-position: 0px -34px +.buttonicon-insertunorderedlist:before { + content: "\e815"; } -.buttonicon-indent { - background-position: 0px -52px +.buttonicon-indent:before { + content: "\e814"; } -.buttonicon-outdent { - background-position: 0px -134px +.buttonicon-outdent:before { + content: "\e813"; } -.buttonicon-undo { - background-position: 0px -255px +.buttonicon-undo:before { + content: "\e823"; } -.buttonicon-redo { - background-position: 0px -166px +.buttonicon-redo:before { + content: "\e824"; } -.buttonicon-clearauthorship { - background-position: 0px -86px +.buttonicon-clearauthorship:before { + content: "\e80d"; } -.buttonicon-settings { - background-position: 0px -436px +.buttonicon-settings:before { + content: "\e833"; } -.buttonicon-import_export { - background-position: 0px -68px +.buttonicon-import_export:before { + content: "\e834"; } -.buttonicon-embed { - background-position: 0px -18px +.buttonicon-embed:before { + content: "\e827"; } -.buttonicon-history { - background-position: 0px -218px +.buttonicon-history:before { + content: "\e837"; } -.buttonicon-chat { - background-position: 0px -102px; +.buttonicon-chat:before { + content: "\e829"; } -.buttonicon-showusers { - background-position: 0px -183px; +.buttonicon-showusers:before { + content: "\e808"; } -.buttonicon-savedRevision { - background-position: 0px -493px +.buttonicon-savedRevision:before { + content: "\e835"; } #focusprotector { z-index: 100; @@ -736,9 +816,6 @@ table#otheruserstable { opacity: 0.01; display: none; } -#online_count { - color: #888; -} .rtl { direction: RTL } @@ -812,9 +889,10 @@ input[type=checkbox] { } .column { float: left; + width:50%; } #settings, -#importexport, +#import_export, #embed, #connectivity, #users { @@ -836,13 +914,17 @@ input[type=checkbox] { border-left: 1px solid #ccc !important; width: 185px !important; } -@media screen and (max-width: 600px) { - .toolbar ul li.separator { - display: none; - } - .toolbar ul li a { - padding: 4px 1px - } +@media screen and (max-width: 600px) { + .toolbar ul li.separator { + display: none; + } + .toolbar ul li a { + padding: 4px 1px + } + .toolbar ul.menu_left { + left:0px; + right:150px; + } } @media all and (max-width: 400px){ #gritter-notice-wrapper{ @@ -854,7 +936,7 @@ input[type=checkbox] { left:0px; right:0px; color:#000; - } + } .gritter-close { display:block !important; left: auto !important; @@ -882,15 +964,19 @@ input[type=checkbox] { .gritter-item-wrapper > div{ background: none; } - #editorcontainer { + #editorcontainer { top: 68px; } - #editbar { + #editbar { height: 62px; } - .toolbar ul.menu_right { - float: left; - margin-top:2px; + .toolbar ul.menu_left { + left:0px; + right:100px; + } + + .toolbar ul.menu_right { + right:0px; } .popup { width:100%; @@ -900,17 +986,23 @@ input[type=checkbox] { } @media only screen and (min-device-width: 320px) and (max-device-width: 720px) { #users { - top: 36px; - bottom: 40px; - border-radius: none; + top: auto; + right:0px !important; + bottom: 33px; + border-radius: 0px !important; } #mycolorpicker { left: -73px; + top:auto !important; + bottom:33px !important; /* #mycolorpicker: width -#users: width */; } #editorcontainer { margin-bottom: 33px } + .toolbar ul.menu_left { + right:0px; + } .toolbar ul.menu_right { background: #f7f7f7; background: -webkit-linear-gradient(#f7f7f7, #f1f1f1 80%); @@ -919,6 +1011,7 @@ input[type=checkbox] { background: -ms-linear-gradient(#f7f7f7, #f1f1f1 80%); background: linear-gradient(#f7f7f7, #f1f1f1 80%); width: 100%; + right:0px !important; overflow: hidden; height: 32px; position: fixed; @@ -938,8 +1031,16 @@ input[type=checkbox] { .toolbar ul li a.selected { background: none !important } - #chaticon, #timesliderlink { - display: none !important + li[data-key="showusers"] > a { + + margin-top:-10px; + padding-top:2px !important; + line-height:20px; + vertical-align:top !important; + } + #chaticon { + position:absolute; + right:48px; } .popup { -webkit-border-radius: 0; @@ -952,11 +1053,11 @@ input[type=checkbox] { width: 100%; } #settings, - #importexport, + #import_export, #connectivity, #embed { + top:auto; left: 0; - top: 0; bottom: 33px; right: 0; } @@ -966,6 +1067,14 @@ input[type=checkbox] { #online_count { line-height: 24px } + #chatbox{ + position:absolute; + bottom:33px; + } + #gritter-notice-wrapper{ + bottom:43px !important; + right:10px !important; + } } #passwordRequired{ @@ -980,6 +1089,10 @@ input[type=checkbox] { display:none; } +#noCookie{ + display:none; +} + /* gritter stuff */ #gritter-notice-wrapper { position:fixed; @@ -987,6 +1100,7 @@ input[type=checkbox] { right:20px; width:301px; z-index:9999; + background-color:#666; } #gritter-notice-wrapper.bottom-right { top: auto; @@ -1000,14 +1114,12 @@ input[type=checkbox] { } .gritter-top { - background:url(../../static/img/gritter.png) no-repeat left -30px; height:10px; } .hover .gritter-top { background-position:right -30px; } .gritter-bottom { - background:url(../../static/img/gritter.png) no-repeat left bottom; height:8px; margin:0; } @@ -1016,7 +1128,6 @@ input[type=checkbox] { } .gritter-item { display:block; - background:url(../../static/img/gritter.png) no-repeat left -40px; color:#eee; padding:2px 11px 8px 11px; font-size: 11px; @@ -1034,7 +1145,6 @@ input[type=checkbox] { position:absolute; top:5px; left:3px; - background:url('../../static/img/gritter.png') no-repeat left top; cursor:pointer; width:30px; height:30px; @@ -1069,16 +1179,43 @@ input[type=checkbox] { .gritter-light .gritter-title { text-shadow: none; } - /* End of gritter stuff */ -.activeButton{ - background: #eee; - background: -webkit-linear-gradient(#ddd, #fff); - background: -moz-linear-gradient(#ddd, #fff); - background: -o-linear-gradient(#ddd, #fff); - background: -ms-linear-gradient(#ddd, #fff); - background: linear-gradient(#ddd, #fff); - -webkit-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; - -moz-box-shadow: 0 0 8px rgba(0,0,0,.1) inset; - box-shadow: 0 0 8px rgba(0,0,0,.1) inset; + +@font-face { + font-family: "fontawesome-etherpad"; + src:url("../font/fontawesome-etherpad.eot"); + src:url("../font/fontawesome-etherpad.eot?#iefix") format("embedded-opentype"), + url("../font/fontawesome-etherpad.woff") format("woff"), + url("../font/fontawesome-etherpad.ttf") format("truetype"), + url("../font/fontawesome-etherpad.svg#fontawesome-etherpad") format("svg"); + font-weight: normal; + font-style: normal; + } + +[data-icon]:before { + font-family: "fontawesome-etherpad" !important; + content: attr(data-icon); + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + speak: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +[class^="icon-"]:before, +[class*=" icon-"]:before { + font-family: "fontawesome-etherpad" !important; + font-style: normal !important; + font-weight: normal !important; + font-variant: normal !important; + text-transform: none !important; + speak: none; + line-height: 1; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + diff --git a/src/static/css/timeslider.css b/src/static/css/timeslider.css index f97d4f2b1..4c84a7fcc 100644 --- a/src/static/css/timeslider.css +++ b/src/static/css/timeslider.css @@ -14,14 +14,14 @@ top: 0; } #timeslider-left { - background-image: url(../../static/img/timeslider_left.png); + background-color:#fff; height: 63px; left: 0; position: absolute; width: 134px; } #timeslider-right { - background-image: url(../../static/img/timeslider_right.png); + background-color:#fff; height: 63px; position: absolute; right: 0; @@ -29,7 +29,6 @@ width: 155px; } #timeslider { - background-image: url(../../static/img/timeslider_background.png); height: 63px; margin: 0 9px; -webkit-touch-callout: none; @@ -38,6 +37,8 @@ -moz-user-select: none; -ms-user-select: none; user-select: none; + background-color:#fff; + /* bgcolor is reuqired so you can't see pad content behind it */ } #timeslider #timeslider-slider { height: 61px; @@ -50,7 +51,7 @@ -webkit-user-select: none; -moz-user-select: none; user-select: none; - background-image: url(../../static/img/crushed_current_location.png); + background-color: #666; cursor: pointer; height: 61px; left: 0; @@ -63,66 +64,97 @@ -moz-user-select: none; user-select: none; cursor: pointer; - height: 35px; + height: 60px; margin-left: 5px; margin-right: 150px; position: relative; - top: 20px; + top: 0px; } + #playpause_button, #playpause_button_icon { - height: 47px; + height: 44px; position: absolute; - width: 47px; + width: 44px; + text-align:center; + vertical-align:middle; } #playpause_button { - background-image: url(../../static/img/crushed_button_undepressed.png); right: 77px; top: 9px; + height:50px; + height:50px; + background: background-linear-gradient( #F7F7F7, #F1F1F1 80%) repeat scroll 0 0 transparent; + border-radius:24px; + cursor:hand; } +#playpause_button_icon:before { + line-height:44px; + padding-left:2px; + font-family: fontawesome-etherpad; + content: "\e82c"; + font-size:24px; + color:#666; +} + #playpause_button_icon { - background-image: url(../../static/img/play.png); left: 0; top: 0; + border-radius:48px; + border: solid 1px #666; } -.pause#playpause_button_icon { - background-image: url(../../static/img/pause.png) +.pause:before { + line-height:44px; + padding-left:2px; + font-family: fontawesome-etherpad; + content: "\e82e" !important; + font-size:24px; + color:#666; + padding-left:0 !important; } #leftstar, #rightstar, #leftstep, #rightstep { - background: url(../../static/img/stepper_buttons.png) 0 0 no-repeat; - height: 21px; + background-color: white; overflow: hidden; position: absolute; } -#leftstar { - background-position: 0 -44px; - right: 34px; - top: 8px; - width: 30px; + +.stepper{ + font-family: fontawesome-etherpad; + border-radius:2px; + border: #666 solid 1px; + line-height:18px; + text-align:center; + height:22px; + color:#666; } -#rightstar { - background-position: -29px -44px; - right: 5px; - top: 8px; - width: 29px; + +stepper:active{ + color:#000; } + #leftstep { - background-position: 0 -22px; - right: 34px; + right: 38px; top: 20px; - width: 30px; + width: 25px; } +#leftstep:before{ + content: '\e821'; + vertical-align:middle; +} +#rightstep:before{ + content: "\e822"; + vertical-align:middle; +} + #rightstep { - background-position: -29px -22px; - right: 5px; + right: 12px; top: 20px; - width: 30px; + width: 25px; } #timeslider .star { - background-image: url(../../static/img/star.png); cursor: pointer; height: 16px; position: absolute; @@ -130,7 +162,9 @@ width: 15px; } #timeslider #timer { - color: #fff; + background: linear-gradient(#F7F7F7, #F1F1F1 80%) repeat scroll 0% 0% transparent; + padding:2px; + border-radius:2px; font-family: Arial, sans-serif; font-size: 11px; left: 7px; @@ -154,22 +188,33 @@ -ms-user-select: none; user-select: none; } -#editbarright { - float: right +.editbarright { + float: right; + text-align: right; + height: 30px !important; +} +.toolbar ul{ + position:relative; + float:right; + height:30px; } #settings, -#importexport, +#import_export, #embed, #connectivity, #users { top: 62px; } -#importexport .popup { - width: 185px +#import_export .popup { + width: 183px; + border-top: none; + border-right: none; + border-radius: 0 0 0 6px; } -#importexport { - top: 118px; +#import_export { + top: 115px; width: 185px; + position: fixed; } .timeslider-bar { background: #f7f7f7; @@ -186,7 +231,6 @@ border-bottom: none; float: right; width: 170px; - width: initial; } .timeslider-bar h1 { margin: 5px @@ -287,16 +331,3 @@ OL { .list-number6 { list-style-type: lower-roman } -/* IE 6/7 fixes */ -* HTML #ui-slider-handle { - background-image: url(../../static/img/current_location.gif) -} -* HTML #timeslider .star { - background-image: url(../../static/img/star.gif) -} -* HTML #playpause_button_icon { - background-image: url(../../static/img/play.gif) -} -* HTML .pause#playpause_button_icon { - background-image: url(../../static/img/pause.gif) -} diff --git a/src/static/font/config.json b/src/static/font/config.json new file mode 100644 index 000000000..34231cca5 --- /dev/null +++ b/src/static/font/config.json @@ -0,0 +1,346 @@ +{ + "name": "fontawesome-etherpad", + "css_prefix_text": "icon-", + "css_use_suffix": false, + "hinting": true, + "units_per_em": 1000, + "ascent": 850, + "glyphs": [ + { + "uid": "bf882b30900da12fca090d9796bc3030", + "css": "mail", + "code": 59402, + "src": "fontawesome" + }, + { + "uid": "474656633f79ea2f1dad59ff63f6bf07", + "css": "star", + "code": 59446, + "src": "fontawesome" + }, + { + "uid": "d17030afaecc1e1c22349b99f3c4992a", + "css": "star-empty", + "code": 59445, + "src": "fontawesome" + }, + { + "uid": "8b80d36d4ef43889db10bc1f0dc9a862", + "css": "user", + "code": 59401, + "src": "fontawesome" + }, + { + "uid": "31972e4e9d080eaa796290349ae6c1fd", + "css": "users", + "code": 59400, + "src": "fontawesome" + }, + { + "uid": "0f99ab40ab0b4d64a74f2d0deeb03e42", + "css": "videocam", + "code": 59403, + "src": "fontawesome" + }, + { + "uid": "381da2c2f7fd51f8de877c044d7f439d", + "css": "picture", + "code": 59404, + "src": "fontawesome" + }, + { + "uid": "7fd683b2c518ceb9e5fa6757f2276faa", + "css": "eye-off", + "code": 59405, + "src": "fontawesome" + }, + { + "uid": "7034e4d22866af82bef811f52fb1ba46", + "css": "code", + "code": 59431, + "src": "fontawesome" + }, + { + "uid": "7277ded7695b2a307a5f9d50097bb64c", + "css": "print", + "code": 59393, + "src": "fontawesome" + }, + { + "uid": "dcedf50ab1ede3283d7a6c70e2fe32f3", + "css": "chat", + "code": 59432, + "src": "fontawesome" + }, + { + "uid": "9c1376672bb4f1ed616fdd78a23667e9", + "css": "comment-empty", + "code": 59433, + "src": "fontawesome" + }, + { + "uid": "f48ae54adfb27d8ada53d0fd9e34ee10", + "css": "trash-empty", + "code": 59434, + "src": "fontawesome" + }, + { + "uid": "1b5a5d7b7e3c71437f5a26befdd045ed", + "css": "doc", + "code": 59394, + "src": "fontawesome" + }, + { + "uid": "9daa1fdf0838118518a7e22715e83abc", + "css": "file-pdf", + "code": 59395, + "src": "fontawesome" + }, + { + "uid": "310ffd629da85142bc8669f010556f2d", + "css": "file-word", + "code": 59396, + "src": "fontawesome" + }, + { + "uid": "f761c3bbe16ba2d332914ecb28e7a042", + "css": "file-excel", + "code": 59397, + "src": "fontawesome" + }, + { + "uid": "edcd4022de8d8df266ef7c42d2658ca5", + "css": "file-powerpoint", + "code": 59398, + "src": "fontawesome" + }, + { + "uid": "3c961c1a8d874815856fc6637dc5a13c", + "css": "file-image", + "code": 59399, + "src": "fontawesome" + }, + { + "uid": "26613a2e6bc41593c54bead46f8c8ee3", + "css": "file-code", + "code": 59430, + "src": "fontawesome" + }, + { + "uid": "e99461abfef3923546da8d745372c995", + "css": "cog", + "code": 59443, + "src": "fontawesome" + }, + { + "uid": "19c50c52858a81de58f9db488aba77bc", + "css": "mic", + "code": 59435, + "src": "fontawesome" + }, + { + "uid": "598a5f2bcf3521d1615de8e1881ccd17", + "css": "clock", + "code": 59447, + "src": "fontawesome" + }, + { + "uid": "bc71f4c6e53394d5ba46b063040014f1", + "css": "cw", + "code": 59428, + "src": "fontawesome" + }, + { + "uid": "f9c3205df26e7778abac86183aefdc99", + "css": "ccw", + "code": 59427, + "src": "fontawesome" + }, + { + "uid": "a73c5deb486c8d66249811642e5d719a", + "css": "arrows-cw", + "code": 59429, + "src": "fontawesome" + }, + { + "uid": "6020aff067fc3c119cdd75daa5249220", + "css": "exchange", + "code": 59444, + "src": "fontawesome" + }, + { + "uid": "ce06b5805120d0c2f8d60cd3f1a4fdb5", + "css": "play", + "code": 59436, + "src": "fontawesome" + }, + { + "uid": "b624a1e512819d410ddbee84e6918b9d", + "css": "stop", + "code": 59437, + "src": "fontawesome" + }, + { + "uid": "0b28050bac9d3facf2f0226db643ece0", + "css": "pause", + "code": 59438, + "src": "fontawesome" + }, + { + "uid": "c47efa0e3e74f6ba4c2562c1258fff1f", + "css": "to-end", + "code": 59426, + "src": "fontawesome" + }, + { + "uid": "12052b30d23a1a70d6b32962d5464cae", + "css": "to-start", + "code": 59425, + "src": "fontawesome" + }, + { + "uid": "f9cbf7508cd04145ade2800169959eef", + "css": "font", + "code": 59419, + "src": "fontawesome" + }, + { + "uid": "02cca871bb69da75e8ee286b7055832c", + "css": "bold", + "code": 59420, + "src": "fontawesome" + }, + { + "uid": "a8cb1c217f02b073db3670c061cc54d2", + "css": "italic", + "code": 59421, + "src": "fontawesome" + }, + { + "uid": "0c708edd8fae2376b3370aa56d40cf9e", + "css": "header", + "code": 59422, + "src": "fontawesome" + }, + { + "uid": "c009d417f87d6a27bb5a1cefd30b6cbd", + "css": "text-height", + "code": 59423, + "src": "fontawesome" + }, + { + "uid": "13a971bcccd2dda26d4d4eccd8593f8a", + "css": "text-width", + "code": 59424, + "src": "fontawesome" + }, + { + "uid": "f4f0e849b805be1f6d76b65581cb3b8b", + "css": "align-left", + "code": 59392, + "src": "fontawesome" + }, + { + "uid": "ae6336c46d73af999fe7460c089abb4d", + "css": "align-center", + "code": 59407, + "src": "fontawesome" + }, + { + "uid": "e1e7306b47c3c5e6faecce9d32571381", + "css": "align-right", + "code": 59408, + "src": "fontawesome" + }, + { + "uid": "25a81737628d1e654a30ad412d7d6dd7", + "css": "align-justify", + "code": 59409, + "src": "fontawesome" + }, + { + "uid": "48b87105bd38c20315f1b705b8c7b38c", + "css": "list", + "code": 59410, + "src": "fontawesome" + }, + { + "uid": "594e9271c08ff732c04b3bf3117b9040", + "css": "indent-left", + "code": 59411, + "src": "fontawesome" + }, + { + "uid": "4d2dfc45d8176b1f26aed973fa84a91e", + "css": "indent-right", + "code": 59412, + "src": "fontawesome" + }, + { + "uid": "a2a74f5e7b7d9ba054897d8c795a326a", + "css": "list-bullet", + "code": 59413, + "src": "fontawesome" + }, + { + "uid": "f6766a8b042c2453a4e153af03294383", + "css": "list-numbered", + "code": 59414, + "src": "fontawesome" + }, + { + "uid": "61c242c9e2134d5864d7fdd57b3c9289", + "css": "strike", + "code": 59416, + "src": "fontawesome" + }, + { + "uid": "d4a4a38a40b728f46dad1de4ac950231", + "css": "underline", + "code": 59415, + "src": "fontawesome" + }, + { + "uid": "4e88371fb8857dacc1f66afe6314e426", + "css": "superscript", + "code": 59417, + "src": "fontawesome" + }, + { + "uid": "3d1c929dbc966992185ce749548c1b2c", + "css": "subscript", + "code": 59418, + "src": "fontawesome" + }, + { + "uid": "9396b2d8849e0213a0f11c5fd7fcc522", + "css": "tasks", + "code": 59442, + "src": "fontawesome" + }, + { + "uid": "0bda4bc779d4c32623dec2e43bd67ee8", + "css": "gauge", + "code": 59439, + "src": "fontawesome" + }, + { + "uid": "cda0cdcfd38f5f1d9255e722dad42012", + "css": "spinner", + "code": 59406, + "src": "fontawesome" + }, + { + "uid": "fa9a0b7e788c2d78e24cef1de6b70e80", + "css": "brush", + "code": 59440, + "src": "fontawesome" + }, + { + "uid": "be13b8c668eb18839d5d53107725f1de", + "css": "slideshare", + "code": 59441, + "src": "fontawesome" + } + ] +} \ No newline at end of file diff --git a/src/static/font/fontawesome-etherpad.eot b/src/static/font/fontawesome-etherpad.eot new file mode 100644 index 000000000..fb6516862 Binary files /dev/null and b/src/static/font/fontawesome-etherpad.eot differ diff --git a/src/static/font/fontawesome-etherpad.svg b/src/static/font/fontawesome-etherpad.svg new file mode 100644 index 000000000..4033c4d16 --- /dev/null +++ b/src/static/font/fontawesome-etherpad.svg @@ -0,0 +1,67 @@ + + + +Copyright (C) 2014 by original authors @ fontello.com + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/static/font/fontawesome-etherpad.ttf b/src/static/font/fontawesome-etherpad.ttf new file mode 100644 index 000000000..f2fe398ec Binary files /dev/null and b/src/static/font/fontawesome-etherpad.ttf differ diff --git a/src/static/font/fontawesome-etherpad.woff b/src/static/font/fontawesome-etherpad.woff new file mode 100644 index 000000000..98de9c3e6 Binary files /dev/null and b/src/static/font/fontawesome-etherpad.woff differ diff --git a/src/static/img/backgrad.gif b/src/static/img/backgrad.gif deleted file mode 100644 index 8fee1a5b7..000000000 Binary files a/src/static/img/backgrad.gif and /dev/null differ diff --git a/src/static/img/connectingbar.gif b/src/static/img/connectingbar.gif deleted file mode 100644 index 5e54d6946..000000000 Binary files a/src/static/img/connectingbar.gif and /dev/null differ diff --git a/src/static/img/crushed_button_depressed.png b/src/static/img/crushed_button_depressed.png deleted file mode 100644 index d75dcce28..000000000 Binary files a/src/static/img/crushed_button_depressed.png and /dev/null differ diff --git a/src/static/img/crushed_button_undepressed.png b/src/static/img/crushed_button_undepressed.png deleted file mode 100644 index d86e3f397..000000000 Binary files a/src/static/img/crushed_button_undepressed.png and /dev/null differ diff --git a/src/static/img/crushed_current_location.png b/src/static/img/crushed_current_location.png deleted file mode 100644 index 76e08359e..000000000 Binary files a/src/static/img/crushed_current_location.png and /dev/null differ diff --git a/src/static/img/etherpad_lite_icons.png b/src/static/img/etherpad_lite_icons.png deleted file mode 100644 index 27867d428..000000000 Binary files a/src/static/img/etherpad_lite_icons.png and /dev/null differ diff --git a/src/static/img/fileicons.gif b/src/static/img/fileicons.gif deleted file mode 100644 index c03b6031a..000000000 Binary files a/src/static/img/fileicons.gif and /dev/null differ diff --git a/src/static/img/gritter.png b/src/static/img/gritter.png deleted file mode 100644 index 0ca3bc0a0..000000000 Binary files a/src/static/img/gritter.png and /dev/null differ diff --git a/src/static/img/leftarrow.png b/src/static/img/leftarrow.png deleted file mode 100644 index 1bec12882..000000000 Binary files a/src/static/img/leftarrow.png and /dev/null differ diff --git a/src/static/img/loading.gif b/src/static/img/loading.gif deleted file mode 100644 index bb42be591..000000000 Binary files a/src/static/img/loading.gif and /dev/null differ diff --git a/src/static/img/pause.png b/src/static/img/pause.png deleted file mode 100644 index 657782c0f..000000000 Binary files a/src/static/img/pause.png and /dev/null differ diff --git a/src/static/img/play.png b/src/static/img/play.png deleted file mode 100644 index 19afe034f..000000000 Binary files a/src/static/img/play.png and /dev/null differ diff --git a/src/static/img/roundcorner_left.gif b/src/static/img/roundcorner_left.gif deleted file mode 100644 index 000de7525..000000000 Binary files a/src/static/img/roundcorner_left.gif and /dev/null differ diff --git a/src/static/img/roundcorner_right.gif b/src/static/img/roundcorner_right.gif deleted file mode 100644 index 97acfbf2e..000000000 Binary files a/src/static/img/roundcorner_right.gif and /dev/null differ diff --git a/src/static/img/star.png b/src/static/img/star.png deleted file mode 100644 index e0c7099e5..000000000 Binary files a/src/static/img/star.png and /dev/null differ diff --git a/src/static/img/stepper_buttons.png b/src/static/img/stepper_buttons.png deleted file mode 100644 index e011a4516..000000000 Binary files a/src/static/img/stepper_buttons.png and /dev/null differ diff --git a/src/static/img/timeslider_background.png b/src/static/img/timeslider_background.png deleted file mode 100644 index 851af4e80..000000000 Binary files a/src/static/img/timeslider_background.png and /dev/null differ diff --git a/src/static/img/timeslider_left.png b/src/static/img/timeslider_left.png deleted file mode 100644 index 48a9b0e17..000000000 Binary files a/src/static/img/timeslider_left.png and /dev/null differ diff --git a/src/static/img/timeslider_right.png b/src/static/img/timeslider_right.png deleted file mode 100644 index 1a1b2685b..000000000 Binary files a/src/static/img/timeslider_right.png and /dev/null differ diff --git a/src/static/js/AttributeManager.js b/src/static/js/AttributeManager.js index 2d523f6aa..a11f6cef6 100644 --- a/src/static/js/AttributeManager.js +++ b/src/static/js/AttributeManager.js @@ -96,6 +96,32 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({ return ''; }, + /* + Gets all attributes on a line + @param lineNum: the number of the line to set the attribute for + */ + getAttributesOnLine: function(lineNum){ + // get attributes of first char of line + var aline = this.rep.alines[lineNum]; + var attributes = [] + if (aline) + { + var opIter = Changeset.opIterator(aline) + , op + if (opIter.hasNext()) + { + op = opIter.next() + if(!op.attribs) return [] + + Changeset.eachAttribNumber(op.attribs, function(n) { + attributes.push([this.rep.apool.getAttribKey(n), this.rep.apool.getAttribValue(n)]) + }.bind(this)) + return attributes; + } + } + return []; + }, + /* Sets a specified attribute on a line @param lineNum: the number of the line to set the attribute for @@ -134,14 +160,21 @@ AttributeManager.prototype = _(AttributeManager.prototype).extend({ */ removeAttributeOnLine: function(lineNum, attributeName, attributeValue){ - var loc = [0,0]; var builder = Changeset.builder(this.rep.lines.totalWidth()); var hasMarker = this.lineHasMarker(lineNum); + var attribs + attribs = this.getAttributesOnLine(lineNum).map(function(attrib) { + if(attrib[0] === attributeName) return [attributeName, null] + return attrib + }) + if(hasMarker){ ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 0])); - ChangesetUtils.buildRemoveRange(this.rep, builder, loc, (loc = [lineNum, 1])); + // If length == 4, there's [author, lmkr, insertorder, + the attrib being removed] thus we can remove the marker entirely + if(attribs.length <= 4) ChangesetUtils.buildRemoveRange(this.rep, builder, loc, (loc = [lineNum, 1])) + else ChangesetUtils.buildKeepRange(this.rep, builder, loc, (loc = [lineNum, 1]), attribs, this.rep.apool); } return this.applyChangeset(builder); diff --git a/src/static/js/Changeset.js b/src/static/js/Changeset.js index 355bef4a9..32da887df 100644 --- a/src/static/js/Changeset.js +++ b/src/static/js/Changeset.js @@ -507,6 +507,10 @@ exports.opAssembler = function () { */ exports.stringIterator = function (str) { var curIndex = 0; + var newLines = str.split("\n").length - 1 + function getnewLines(){ + return newLines + } function assertRemaining(n) { exports.assert(n <= remaining(), "!(", n, " <= ", remaining(), ")"); @@ -515,6 +519,7 @@ exports.stringIterator = function (str) { function take(n) { assertRemaining(n); var s = str.substr(curIndex, n); + newLines -= s.split("\n").length - 1 curIndex += n; return s; } @@ -537,7 +542,8 @@ exports.stringIterator = function (str) { take: take, skip: skip, remaining: remaining, - peek: peek + peek: peek, + newlines: getnewLines }; }; @@ -903,11 +909,15 @@ exports.pack = function (oldLen, newLen, opsStr, bank) { * @params str {string} String to which a Changeset should be applied */ exports.applyToText = function (cs, str) { + var totalNrOfLines = str.split("\n").length; + var removedLines = 0; var unpacked = exports.unpack(cs); exports.assert(str.length == unpacked.oldLen, "mismatched apply: ", str.length, " / ", unpacked.oldLen); var csIter = exports.opIterator(unpacked.ops); var bankIter = exports.stringIterator(unpacked.charBank); var strIter = exports.stringIterator(str); + var newlines = 0 + var newlinefail = false var assem = exports.stringAssembler(); while (csIter.hasNext()) { var op = csIter.next(); @@ -916,15 +926,25 @@ exports.applyToText = function (cs, str) { assem.append(bankIter.take(op.chars)); break; case '-': + removedLines += op.lines; + newlines = strIter.newlines() strIter.skip(op.chars); + if(!(newlines - strIter.newlines() == 0) && (newlines - strIter.newlines() != op.lines)){ + newlinefail = true + } break; case '=': + newlines = strIter.newlines() assem.append(strIter.take(op.chars)); + if(!(newlines - strIter.newlines() == op.lines)){ + newlinefail = true + } break; } } + exports.assert(totalNrOfLines >= removedLines,"cannot remove ", removedLines, " lines from text with ", totalNrOfLines, " lines"); assem.append(strIter.take(strIter.remaining())); - return assem.toString(); + return [assem.toString(),newlinefail]; }; /** @@ -1595,8 +1615,12 @@ exports.makeAText = function (text, attribs) { * @param pool {AttribPool} Attribute Pool to add to */ exports.applyToAText = function (cs, atext, pool) { + var text = exports.applyToText(cs, atext.text) + if(text[1]){ + throw new Error() + } return { - text: exports.applyToText(cs, atext.text), + text: text[0], attribs: exports.applyToAttribution(cs, atext.attribs, pool) }; }; diff --git a/src/static/js/ace2_inner.js b/src/static/js/ace2_inner.js index 07a9b971d..86f69bab9 100644 --- a/src/static/js/ace2_inner.js +++ b/src/static/js/ace2_inner.js @@ -28,7 +28,6 @@ $ = jQuery = require('./rjquery').$; _ = require("./underscore"); var isNodeText = Ace2Common.isNodeText, - browser = $.browser, getAssoc = Ace2Common.getAssoc, setAssoc = Ace2Common.setAssoc, isTextNode = Ace2Common.isTextNode, @@ -36,7 +35,7 @@ var isNodeText = Ace2Common.isNodeText, htmlPrettyEscape = Ace2Common.htmlPrettyEscape, noop = Ace2Common.noop; var hooks = require('./pluginfw/hooks'); - + var browser = require('./browser').browser; function Ace2Inner(){ @@ -58,7 +57,7 @@ function Ace2Inner(){ var isSetUp = false; var THE_TAB = ' '; //4 - var MAX_LIST_LEVEL = 8; + var MAX_LIST_LEVEL = 16; var LINE_NUMBER_PADDING_RIGHT = 4; var LINE_NUMBER_PADDING_LEFT = 4; @@ -152,7 +151,6 @@ function Ace2Inner(){ var dmesg = noop; window.dmesg = noop; - var scheduler = parent; // hack for opera required var textFace = 'monospace'; @@ -597,6 +595,13 @@ function Ace2Inner(){ fixView(); }); }, 0); + + // Chrome can't handle the truth.. If CSS rule white-space:pre-wrap + // is true then any paste event will insert two lines.. + if(browser.chrome){ + $("#innerdocbody").css({"white-space":"normal"}); + } + } function setStyled(newVal) @@ -2308,6 +2313,25 @@ function Ace2Inner(){ function getAttributeOnSelection(attributeName){ if (!(rep.selStart && rep.selEnd)) return; + + // get the previous/next characters formatting when we have nothing selected + // To fix this we just change the focus area, we don't actually check anything yet. + if(rep.selStart[1] == rep.selEnd[1]){ + // if we're at the beginning of a line bump end forward so we get the right attribute + if(rep.selStart[1] == 0 && rep.selEnd[1] == 0){ + rep.selEnd[1] = 1; + } + if(rep.selStart[1] < 0){ + rep.selStart[1] = 0; + } + var line = rep.lines.atIndex(rep.selStart[0]); + // if we're at the end of the line bmp the start back 1 so we get hte attribute + if(rep.selEnd[1] == line.text.length){ + rep.selStart[1] = rep.selStart[1] -1; + } + } + + // Do the detection var selectionAllHasIt = true; var withIt = Changeset.makeAttribsString('+', [ [attributeName, 'true'] @@ -2333,7 +2357,7 @@ function Ace2Inner(){ if(rep.selStart[1] == rep.selEnd[1] && rep.selStart[1] == rep.lines.atIndex(n).text.length){ return false; // If we're at the end of a line we treat it as having no formatting } - if(rep.selStart[1] == 0 && rep.selEnd[1] == 0){ + if(rep.selStart[1] == 0 && rep.selEnd[1] == 0){ rep.selEnd[1] == 1; } if(rep.selEnd[1] == -1){ @@ -3333,7 +3357,7 @@ function Ace2Inner(){ if (listType) { var text = rep.lines.atIndex(lineNum).text; - listType = /([a-z]+)([12345678])/.exec(listType); + listType = /([a-z]+)([0-9]+)/.exec(listType); var type = listType[1]; var level = Number(listType[2]); @@ -3385,7 +3409,7 @@ function Ace2Inner(){ var level = 0; if (listType) { - listType = /([a-z]+)([12345678])/.exec(listType); + listType = /([a-z]+)([0-9]+)/.exec(listType); if (listType) { t = listType[1]; @@ -3601,6 +3625,26 @@ function Ace2Inner(){ return; } + // Is caret potentially hidden by the chat button? + var myselection = document.getSelection(); // get the current caret selection + var caretOffsetTop = myselection.focusNode.parentNode.offsetTop | myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214 + + if(myselection.focusNode.wholeText){ // Is there any content? If not lineHeight will report wrong.. + var lineHeight = myselection.focusNode.parentNode.offsetHeight; // line height of populated links + }else{ + var lineHeight = myselection.focusNode.offsetHeight; // line height of blank lines + } + var heightOfChatIcon = parent.parent.$('#chaticon').height(); // height of the chat icon button + lineHeight = (lineHeight *2) + heightOfChatIcon; + var viewport = getViewPortTopBottom(); + var viewportHeight = viewport.bottom - viewport.top - lineHeight; + var relCaretOffsetTop = caretOffsetTop - viewport.top; // relative Caret Offset Top to viewport + if (viewportHeight < relCaretOffsetTop){ + parent.parent.$("#chaticon").css("opacity",".3"); // make chaticon opacity low when user types near it + }else{ + parent.parent.$("#chaticon").css("opacity","1"); // make chaticon opacity back to full (so fully visible) + } + //dmesg("keyevent type: "+type+", which: "+which); // Don't take action based on modifier keys going up and down. // Modifier keys do not generate "keypress" events. @@ -3674,7 +3718,7 @@ function Ace2Inner(){ }, 0); specialHandled = true; } - if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "s" && (evt.metaKey || evt.ctrlKey)) /* Do a saved revision on ctrl S */ + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "s" && (evt.metaKey || evt.ctrlKey) && !evt.altKey) /* Do a saved revision on ctrl S */ { evt.preventDefault(); var originalBackground = parent.parent.$('#revisionlink').css("background") @@ -3741,6 +3785,36 @@ function Ace2Inner(){ toggleAttributeOnSelection('underline'); specialHandled = true; } + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "5" && (evt.metaKey || evt.ctrlKey)) + { + // cmd-5 (strikethrough) + fastIncorp(13); + evt.preventDefault(); + toggleAttributeOnSelection('strikethrough'); + specialHandled = true; + } + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "l" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey) + { + // cmd-shift-L (unorderedlist) + fastIncorp(9); + evt.preventDefault(); + doInsertUnorderedList() + specialHandled = true; + } + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "n" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey) + { + // cmd-shift-N (orderedlist) + fastIncorp(9); + evt.preventDefault(); + doInsertOrderedList() + specialHandled = true; + } + if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "c" && (evt.metaKey || evt.ctrlKey) && evt.shiftKey) { + // cmd-shift-C (clearauthorship) + fastIncorp(9); + evt.preventDefault(); + CMDS.clearauthorship(); + } if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "h" && (evt.ctrlKey)) { // cmd-H (backspace) @@ -3792,7 +3866,7 @@ function Ace2Inner(){ } updateBrowserSelectionFromRep(); 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 | myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214 + var caretOffsetTop = myselection.focusNode.parentNode.offsetTop || myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214 // top.console.log(caretOffsetTop); setScrollY(caretOffsetTop); // set the scrollY offset of the viewport on the document @@ -3801,7 +3875,7 @@ function Ace2Inner(){ /* 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 .. Sorry if this is ugly, blame Chrome's weird handling of viewports after new content is added*/ - if((evt.which == 37 || evt.which == 38 || evt.which == 39 || evt.which == 40) && $.browser.chrome){ + if((evt.which == 37 || evt.which == 38 || evt.which == 39 || evt.which == 40) && browser.chrome){ var viewport = getViewPortTopBottom(); 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 || myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214 @@ -3818,7 +3892,7 @@ function Ace2Inner(){ // top.console.log(caretOffsetTop, viewport.top, caretOffsetTopBottom, viewport.bottom); var caretIsNotVisible = (caretOffsetTop < viewport.top || caretOffsetTopBottom >= viewport.bottom); // Is the Caret Visible to the user? // Expect some weird behavior caretOffsetTopBottom is greater than viewport.bottom on a keypress down - var offsetTopSamePlace = caretOffsetTop == viewport.top; // sometimes moving key left & up leaves the caret at the same point as the viewport.top, technically the caret is visible but it's not fully visible so we should move to it + var offsetTopSamePlace = caretOffsetTop == viewport.top; // sometimes moving key left & up leaves the caret at the same point as the viewport.top, technically the caret is visible but it's not fully visible so we should move to it if(offsetTopSamePlace && (evt.which == 37 || evt.which == 38)){ var newY = caretOffsetTop; setScrollY(newY); @@ -4999,6 +5073,7 @@ function Ace2Inner(){ { if(listType == ''){ documentAttributeManager.removeAttributeOnLine(lineNum, listAttributeName); + documentAttributeManager.removeAttributeOnLine(lineNum, 'start'); }else{ documentAttributeManager.setAttributeOnLine(lineNum, listAttributeName, listType); } @@ -5020,7 +5095,7 @@ function Ace2Inner(){ { return null; } - type = /([a-z]+)[12345678]/.exec(type); + type = /([a-z]+)[0-9+]/.exec(type); if(type[1] == "indent") { return null; @@ -5029,7 +5104,7 @@ function Ace2Inner(){ //2-find the first line of the list while(lineNum-1 >= 0 && (type=getLineListType(lineNum-1))) { - type = /([a-z]+)[12345678]/.exec(type); + type = /([a-z]+)[0-9+]/.exec(type); if(type[1] == "indent") break; lineNum--; @@ -5038,7 +5113,7 @@ function Ace2Inner(){ //3-renumber every list item of the same level from the beginning, level 1 //IMPORTANT: never skip a level because there imbrication may be arbitrary var builder = Changeset.builder(rep.lines.totalWidth()); - loc = [0,0]; + var loc = [0,0]; function applyNumberList(line, level) { //init @@ -5049,7 +5124,7 @@ function Ace2Inner(){ while(listType = getLineListType(line)) { //apply new num - listType = /([a-z]+)([12345678])/.exec(listType); + listType = /([a-z]+)([0-9+])/.exec(listType); curLevel = Number(listType[2]); if(isNaN(curLevel) || listType[0] == "indent") { @@ -5117,7 +5192,7 @@ function Ace2Inner(){ { var t = ''; var level = 0; - var listType = /([a-z]+)([12345678])/.exec(getLineListType(n)); + var listType = /([a-z]+)([0-9]+)/.exec(getLineListType(n)); if (listType) { t = listType[1]; diff --git a/src/static/js/admin/plugins.js b/src/static/js/admin/plugins.js index e6c7a1224..8a4c732e5 100644 --- a/src/static/js/admin/plugins.js +++ b/src/static/js/admin/plugins.js @@ -10,7 +10,8 @@ $(document).ready(function () { resource = baseURL.substring(1) + "socket.io"; //connect - socket = io.connect(url, {resource : resource}).of("/pluginfw/installer"); + var room = url + "pluginfw/installer"; + socket = io.connect(room, {resource : resource}); function search(searchTerm, limit) { if(search.searchTerm != searchTerm) { diff --git a/src/static/js/admin/settings.js b/src/static/js/admin/settings.js index fb3f2e973..8a4473d6a 100644 --- a/src/static/js/admin/settings.js +++ b/src/static/js/admin/settings.js @@ -9,7 +9,8 @@ $(document).ready(function () { resource = baseURL.substring(1) + "socket.io"; //connect - socket = io.connect(url, {resource : resource}).of("/settings"); + var room = url + "settings"; + socket = io.connect(room, {resource : resource}); socket.on('settings', function (settings) { diff --git a/src/static/js/broadcast.js b/src/static/js/broadcast.js index d4bda1110..a25d889b9 100644 --- a/src/static/js/broadcast.js +++ b/src/static/js/broadcast.js @@ -27,6 +27,7 @@ var Changeset = require('./Changeset'); var linestylefilter = require('./linestylefilter').linestylefilter; var colorutils = require('./colorutils').colorutils; var _ = require('./underscore'); +var hooks = require('./pluginfw/hooks'); // These parameters were global, now they are injected. A reference to the // Timeslider controller would probably be more appropriate. @@ -66,7 +67,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro } // for IE - if ($.browser.msie) + if (browser.msie) { try { @@ -384,22 +385,10 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro } if (changeset) applyChangeset(changeset, path.rev, true, timeDelta); - - if (BroadcastSlider.getSliderLength() > 10000) - { - var start = (Math.floor((newRevision) / 10000) * 10000); // revision 0 to 10 - changesetLoader.queueUp(start, 100); - } - - if (BroadcastSlider.getSliderLength() > 1000) - { - var start = (Math.floor((newRevision) / 1000) * 1000); // (start from -1, go to 19) + 1 - changesetLoader.queueUp(start, 10); - } - - start = (Math.floor((newRevision) / 100) * 100); - - changesetLoader.queueUp(start, 1, update); + // Loading changeset history for new revision + loadChangesetsForRevision(newRevision, update); + // Loading changeset history for old revision (to make diff between old and new revision) + loadChangesetsForRevision(padContents.currentRevision - 1); } var authors = _.map(padContents.getActiveAuthors(), function(name){ @@ -407,6 +396,24 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro }); BroadcastSlider.setAuthors(authors); } + + function loadChangesetsForRevision(revision, callback) { + if (BroadcastSlider.getSliderLength() > 10000) + { + var start = (Math.floor((revision) / 10000) * 10000); // revision 0 to 10 + changesetLoader.queueUp(start, 100); + } + + if (BroadcastSlider.getSliderLength() > 1000) + { + var start = (Math.floor((revision) / 1000) * 1000); // (start from -1, go to 19) + 1 + changesetLoader.queueUp(start, 10); + } + + start = (Math.floor((revision) / 100) * 100); + + changesetLoader.queueUp(start, 1, callback); + } changesetLoader = { running: false, @@ -482,7 +489,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro var astart = start + i * granularity - 1; // rev -1 is a blank single line var aend = start + (i + 1) * granularity - 1; // totalRevs is the most recent revision if (aend > data.actualEndNum - 1) aend = data.actualEndNum - 1; - debugLog("adding changeset:", astart, aend); + //debugLog("adding changeset:", astart, aend); var forwardcs = Changeset.moveOpsToNewPool(data.forwardsChangesets[i], pool, padContents.apool); var backwardcs = Changeset.moveOpsToNewPool(data.backwardsChangesets[i], pool, padContents.apool); revisionInfo.addChangeset(astart, aend, forwardcs, backwardcs, data.timeDeltas[i]); @@ -528,6 +535,7 @@ function loadBroadcastJS(socket, sendSocketMsg, fireWhenAllScriptsAreLoaded, Bro var savedRev = obj.savedRev; BroadcastSlider.addSavedRevision(savedRev.revNum, savedRev); } + hooks.callAll('handleClientTimesliderMessage_' + obj.type, {payload: obj}); } else if(obj.type == "CHANGESET_REQ") { diff --git a/src/static/js/broadcast_slider.js b/src/static/js/broadcast_slider.js index 8179b7b5f..7f0e48bc8 100644 --- a/src/static/js/broadcast_slider.js +++ b/src/static/js/broadcast_slider.js @@ -29,6 +29,9 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) { var BroadcastSlider; + // Hack to ensure timeslider i18n values are in + $("[data-key='timeslider_returnToPad'] > a > span").html(html10n.get("timeslider.toolbar.returnbutton")); + (function() { // wrap this code in its own namespace var sliderLength = 1000; @@ -177,23 +180,26 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) var colorsAnonymous = []; _.each(authors, function(author) { - var authorColor = clientVars.colorPalette[author.colorId] || author.colorId; - if (author.name) + if(author) { - if (numNamed !== 0) authorsList.append(', '); - - $('') - .text(author.name || "unnamed") - .css('background-color', authorColor) - .addClass('author') - .appendTo(authorsList); + var authorColor = clientVars.colorPalette[author.colorId] || author.colorId; + if (author.name) + { + if (numNamed !== 0) authorsList.append(', '); + + $('') + .text(author.name || "unnamed") + .css('background-color', authorColor) + .addClass('author') + .appendTo(authorsList); - numNamed++; - } - else - { - numAnonymous++; - if(authorColor) colorsAnonymous.push(authorColor); + numNamed++; + } + else + { + numAnonymous++; + if(authorColor) colorsAnonymous.push(authorColor); + } } }); if (numAnonymous > 0) @@ -334,7 +340,6 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) $("#ui-slider-bar").mousedown(function(evt) { - setSliderPosition(Math.floor((evt.clientX - $("#ui-slider-bar").offset().left) * sliderLength / 742)); $("#ui-slider-handle").css('left', (evt.clientX - $("#ui-slider-bar").offset().left)); $("#ui-slider-handle").trigger(evt); }); @@ -380,16 +385,16 @@ function loadBroadcastSliderJS(fireWhenAllScriptsAreLoaded) { var self = this; - $(self).css('background-image', 'url(/static/img/crushed_button_depressed.png)'); + // $(self).css('background-image', 'url(/static/img/crushed_button_depressed.png)'); $(self).mouseup(function(evt2) { - $(self).css('background-image', 'url(/static/img/crushed_button_undepressed.png)'); + // $(self).css('background-image', 'url(/static/img/crushed_button_undepressed.png)'); $(self).unbind('mouseup'); BroadcastSlider.playpause(); }); $(document).mouseup(function(evt2) { - $(self).css('background-image', 'url(/static/img/crushed_button_undepressed.png)'); + // $(self).css('background-image', 'url(/static/img/crushed_button_undepressed.png)'); $(document).unbind('mouseup'); }); }); diff --git a/src/static/js/browser.js b/src/static/js/browser.js new file mode 100644 index 000000000..f763963e1 --- /dev/null +++ b/src/static/js/browser.js @@ -0,0 +1,240 @@ +/*! + * Bowser - a browser detector + * https://github.com/ded/bowser + * MIT License | (c) Dustin Diaz 2014 + */ + +!function (name, definition) { + if (typeof module != 'undefined' && module.exports) module.exports['browser'] = definition() + else if (typeof define == 'function' && define.amd) define(definition) + else this[name] = definition() +}('bowser', function () { + /** + * See useragents.js for examples of navigator.userAgent + */ + + var t = true + + function detect(ua) { + + function getFirstMatch(regex) { + var match = ua.match(regex); + return (match && match.length > 1 && match[1]) || ''; + } + + var iosdevice = getFirstMatch(/(ipod|iphone|ipad)/i).toLowerCase() + , likeAndroid = /like android/i.test(ua) + , android = !likeAndroid && /android/i.test(ua) + , versionIdentifier = getFirstMatch(/version\/(\d+(\.\d+)?)/i) + , tablet = /tablet/i.test(ua) + , mobile = !tablet && /[^-]mobi/i.test(ua) + , result + + if (/opera|opr/i.test(ua)) { + result = { + name: 'Opera' + , opera: t + , version: versionIdentifier || getFirstMatch(/(?:opera|opr)[\s\/](\d+(\.\d+)?)/i) + } + } + else if (/windows phone/i.test(ua)) { + result = { + name: 'Windows Phone' + , windowsphone: t + , msie: t + , version: getFirstMatch(/iemobile\/(\d+(\.\d+)?)/i) + } + } + else if (/msie|trident/i.test(ua)) { + result = { + name: 'Internet Explorer' + , msie: t + , version: getFirstMatch(/(?:msie |rv:)(\d+(\.\d+)?)/i) + } + } + else if (/chrome|crios|crmo/i.test(ua)) { + result = { + name: 'Chrome' + , chrome: t + , version: getFirstMatch(/(?:chrome|crios|crmo)\/(\d+(\.\d+)?)/i) + } + } + else if (iosdevice) { + result = { + name : iosdevice == 'iphone' ? 'iPhone' : iosdevice == 'ipad' ? 'iPad' : 'iPod' + } + // WTF: version is not part of user agent in web apps + if (versionIdentifier) { + result.version = versionIdentifier + } + } + else if (/sailfish/i.test(ua)) { + result = { + name: 'Sailfish' + , sailfish: t + , version: getFirstMatch(/sailfish\s?browser\/(\d+(\.\d+)?)/i) + } + } + else if (/seamonkey\//i.test(ua)) { + result = { + name: 'SeaMonkey' + , seamonkey: t + , version: getFirstMatch(/seamonkey\/(\d+(\.\d+)?)/i) + } + } + else if (/firefox|iceweasel/i.test(ua)) { + result = { + name: 'Firefox' + , firefox: t + , version: getFirstMatch(/(?:firefox|iceweasel)[ \/](\d+(\.\d+)?)/i) + } + if (/\((mobile|tablet);[^\)]*rv:[\d\.]+\)/i.test(ua)) { + result.firefoxos = t + } + } + else if (/silk/i.test(ua)) { + result = { + name: 'Amazon Silk' + , silk: t + , version : getFirstMatch(/silk\/(\d+(\.\d+)?)/i) + } + } + else if (android) { + result = { + name: 'Android' + , version: versionIdentifier + } + } + else if (/phantom/i.test(ua)) { + result = { + name: 'PhantomJS' + , phantom: t + , version: getFirstMatch(/phantomjs\/(\d+(\.\d+)?)/i) + } + } + else if (/blackberry|\bbb\d+/i.test(ua) || /rim\stablet/i.test(ua)) { + result = { + name: 'BlackBerry' + , blackberry: t + , version: versionIdentifier || getFirstMatch(/blackberry[\d]+\/(\d+(\.\d+)?)/i) + } + } + else if (/(web|hpw)os/i.test(ua)) { + result = { + name: 'WebOS' + , webos: t + , version: versionIdentifier || getFirstMatch(/w(?:eb)?osbrowser\/(\d+(\.\d+)?)/i) + }; + /touchpad\//i.test(ua) && (result.touchpad = t) + } + else if (/bada/i.test(ua)) { + result = { + name: 'Bada' + , bada: t + , version: getFirstMatch(/dolfin\/(\d+(\.\d+)?)/i) + }; + } + else if (/tizen/i.test(ua)) { + result = { + name: 'Tizen' + , tizen: t + , version: getFirstMatch(/(?:tizen\s?)?browser\/(\d+(\.\d+)?)/i) || versionIdentifier + }; + } + else if (/safari/i.test(ua)) { + result = { + name: 'Safari' + , safari: t + , version: versionIdentifier + } + } + else result = {} + + // set webkit or gecko flag for browsers based on these engines + if (/(apple)?webkit/i.test(ua)) { + result.name = result.name || "Webkit" + result.webkit = t + if (!result.version && versionIdentifier) { + result.version = versionIdentifier + } + } else if (!result.opera && /gecko\//i.test(ua)) { + result.name = result.name || "Gecko" + result.gecko = t + result.version = result.version || getFirstMatch(/gecko\/(\d+(\.\d+)?)/i) + } + + // set OS flags for platforms that have multiple browsers + if (android || result.silk) { + result.android = t + } else if (iosdevice) { + result[iosdevice] = t + result.ios = t + } + + // OS version extraction + var osVersion = ''; + if (iosdevice) { + osVersion = getFirstMatch(/os (\d+([_\s]\d+)*) like mac os x/i); + osVersion = osVersion.replace(/[_\s]/g, '.'); + } else if (android) { + osVersion = getFirstMatch(/android[ \/-](\d+(\.\d+)*)/i); + } else if (result.windowsphone) { + osVersion = getFirstMatch(/windows phone (?:os)?\s?(\d+(\.\d+)*)/i); + } else if (result.webos) { + osVersion = getFirstMatch(/(?:web|hpw)os\/(\d+(\.\d+)*)/i); + } else if (result.blackberry) { + osVersion = getFirstMatch(/rim\stablet\sos\s(\d+(\.\d+)*)/i); + } else if (result.bada) { + osVersion = getFirstMatch(/bada\/(\d+(\.\d+)*)/i); + } else if (result.tizen) { + osVersion = getFirstMatch(/tizen[\/\s](\d+(\.\d+)*)/i); + } + if (osVersion) { + result.osversion = osVersion; + } + + // device type extraction + var osMajorVersion = osVersion.split('.')[0]; + if (tablet || iosdevice == 'ipad' || (android && (osMajorVersion == 3 || (osMajorVersion == 4 && !mobile))) || result.silk) { + result.tablet = t + } else if (mobile || iosdevice == 'iphone' || iosdevice == 'ipod' || android || result.blackberry || result.webos || result.bada) { + result.mobile = t + } + + // Graded Browser Support + // http://developer.yahoo.com/yui/articles/gbs + if ((result.msie && result.version >= 10) || + (result.chrome && result.version >= 20) || + (result.firefox && result.version >= 20.0) || + (result.safari && result.version >= 6) || + (result.opera && result.version >= 10.0) || + (result.ios && result.osversion && result.osversion.split(".")[0] >= 6) || + (result.blackberry && result.version >= 10.1) + ) { + result.a = t; + } + else if ((result.msie && result.version < 10) || + (result.chrome && result.version < 20) || + (result.firefox && result.version < 20.0) || + (result.safari && result.version < 6) || + (result.opera && result.version < 10.0) || + (result.ios && result.osversion && result.osversion.split(".")[0] < 6) + ) { + result.c = t + } else result.x = t + + return result + } + + var bowser = detect(typeof navigator !== 'undefined' ? navigator.userAgent : '') + + + /* + * Set our detect method to the main bowser object so we can + * reuse it to test other user agents. + * This is needed to implement future tests. + */ + bowser._detect = detect; + + return bowser +}); diff --git a/src/static/js/changesettracker.js b/src/static/js/changesettracker.js index f3efc4074..fe362c4b7 100644 --- a/src/static/js/changesettracker.js +++ b/src/static/js/changesettracker.js @@ -179,7 +179,7 @@ function makeChangesetTracker(scheduler, apool, aceCallbacksProvider) // We need to replace all author attribs with thisSession.author, in case they copy/pasted or otherwise inserted other peoples changes if(apool.numToAttrib){ for (var attr in apool.numToAttrib){ - if (apool.numToAttrib[attr][0] == 'author' && apool.numToAttrib[attr][1] == authorId) authorAttr = Number(attr).toString(36) + if (apool.numToAttrib[attr][0] == 'author' && apool.numToAttrib[attr][1] == authorId) var authorAttr = Number(attr).toString(36) } // Replace all added 'author' attribs with the value of the current user diff --git a/src/static/js/chat.js b/src/static/js/chat.js index 65fc8dd94..4cbbbaa78 100644 --- a/src/static/js/chat.js +++ b/src/static/js/chat.js @@ -41,7 +41,7 @@ var chat = (function() if(!isStuck || fromInitialCall) { // Stick it to padcookie.setPref("chatAlwaysVisible", true); $('#chatbox').addClass("stickyChat"); - $('#chattext').css({"top":"0px"}); + $('#titlesticky').hide(); $('#editorcontainer').css({"right":"192px"}); $('.stickyChat').css("top",$('#editorcontainer').offset().top+"px"); isStuck = true; @@ -49,18 +49,25 @@ var chat = (function() padcookie.setPref("chatAlwaysVisible", false); $('.stickyChat').css("top", "auto"); $('#chatbox').removeClass("stickyChat"); - $('#chattext').css({"top":"25px"}); + $('#titlesticky').show(); $('#editorcontainer').css({"right":"0px"}); isStuck = false; } }, hide: function () { - $("#chatcounter").text("0"); - $("#chaticon").show(); - $("#chatbox").hide(); - $.gritter.removeAll(); - $("#gritter-notice-wrapper").show(); + // decide on hide logic based on chat window being maximized or not + if ($('#options-stickychat').prop('checked')) { + chat.stickToScreen(); + $('#options-stickychat').prop('checked', false); + } + else { + $("#chatcounter").text("0"); + $("#chaticon").show(); + $("#chatbox").hide(); + $.gritter.removeAll(); + $("#gritter-notice-wrapper").show(); + } }, scrollDown: function() { diff --git a/src/static/js/collab_client.js b/src/static/js/collab_client.js index 146ec51b5..6089f1972 100644 --- a/src/static/js/collab_client.js +++ b/src/static/js/collab_client.js @@ -82,7 +82,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) {} }; - if ($.browser.mozilla) + if (browser.mozilla) { // Prevent "escape" from taking effect and canceling a comet connection; // doesn't work if focus is on an iframe. @@ -152,6 +152,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) // apply msgQueue changeset. if (msgQueue.length != 0) { + var msg; while (msg = msgQueue.shift()) { var newRev = msg.newRev; rev=newRev; @@ -274,7 +275,7 @@ function getCollabClient(ace2editor, serverVars, initialUserInfo, options, _pad) // When inInternationalComposition, msg pushed msgQueue. if (msgQueue.length > 0 || editor.getInInternationalComposition()) { - if (msgQueue.length > 0) oldRev = msgQueue[msgQueue.length - 1].newRev; + if (msgQueue.length > 0) var oldRev = msgQueue[msgQueue.length - 1].newRev; else oldRev = rev; if (newRev != (oldRev + 1)) diff --git a/src/static/js/contentcollector.js b/src/static/js/contentcollector.js index ee0a1c27a..e90783ae0 100644 --- a/src/static/js/contentcollector.js +++ b/src/static/js/contentcollector.js @@ -32,7 +32,7 @@ var _ = require('./underscore'); function sanitizeUnicode(s) { - return UNorm.nfc(s).replace(/[\uffff\ufffe\ufeff\ufdd0-\ufdef\ud800-\udfff]/g, '?'); + return UNorm.nfc(s); } function makeContentCollector(collectStyles, browser, apool, domInterface, className2Author) @@ -54,10 +54,14 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class }, nodeNumChildren: function(n) { + if(n.childNodes == null) return 0; return n.childNodes.length; }, nodeChild: function(n, i) { + if(n.childNodes.item == null){ + return n.childNodes[i]; + } return n.childNodes.item(i); }, nodeProp: function(n, p) @@ -66,6 +70,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class }, nodeAttr: function(n, a) { + if(n.getAttribute == null) return null; return n.getAttribute(a); }, optNodeInnerHTML: function(n) @@ -89,7 +94,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class function textify(str) { return sanitizeUnicode( - str.replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' ')); + str.replace(/\n/g, '').replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' ')); } function getAssoc(node, name) @@ -513,9 +518,28 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class } if (tname == "ul" || tname == "ol") { - var type; + if(node.attribs){ + var type = node.attribs.class; + }else{ + var type = null; + } var rr = cls && /(?:^| )list-([a-z]+[12345678])\b/.exec(cls); - type = rr && rr[1] || (tname == "ul" ? "bullet" : "number") + String(Math.min(_MAX_LIST_LEVEL, (state.listNesting || 0) + 1)); + // lists do not need to have a type, so before we make a wrong guess, check if we find a better hint within the node's children + if(!rr && !type){ + for (var i in node.children){ + if(node.children[i] && node.children[i].name=='ul'){ + type = node.children[i].attribs.class + if(type){ + break + } + } + } + } + if(rr && rr[1]){ + type = rr[1] + } else { + type = (tname == "ul" ? (type.match("indent") || node.attribs.class && node.attribs.class.match("indent") ? "indent" : "bullet") : "number") + String(Math.min(_MAX_LIST_LEVEL, (state.listNesting || 0) + 1)); + } oldListTypeOrNull = (_enterList(state, type) || 'none'); } else if ((tname == "div" || tname == "p") && cls && cls.match(/(?:^| )ace-line\b/)) @@ -663,7 +687,7 @@ function makeContentCollector(collectStyles, browser, apool, domInterface, class { //var semiloc = oldString.lastIndexOf(';', lineLimit-1); //var lengthToTake = (semiloc >= 0 ? (semiloc+1) : lineLimit); - lengthToTake = lineLimit; + var lengthToTake = lineLimit; newStrings.push(oldString.substring(0, lengthToTake)); oldString = oldString.substring(lengthToTake); newAttribStrings.push(Changeset.subattribution(oldAttribString, 0, lengthToTake)); diff --git a/src/static/js/farbtastic.js b/src/static/js/farbtastic.js index 114c4d727..8a61627d2 100644 --- a/src/static/js/farbtastic.js +++ b/src/static/js/farbtastic.js @@ -170,7 +170,7 @@ $._farbtastic = function (container, options) { // New color color2 = fb.pack(fb.HSLToRGB([d2, 1, 0.5])); if (i > 0) { - if ($.browser.msie) { + if (browser.msie) { // IE's gradient calculations mess up the colors. Correct along the diagonals. var corr = (1 + Math.min(Math.abs(Math.tan(angle1)), Math.abs(Math.tan(Math.PI / 2 - angle1)))) / n; color1 = fb.pack(fb.HSLToRGB([d1 - 0.15 * corr, 1, 0.5])); @@ -254,7 +254,7 @@ $._farbtastic = function (container, options) { fb.ctxMask.drawImage(buffer, 0, 0, sz + 1, sz + 1, -sq, -sq, sq * 2, sq * 2); } // Method #2: drawing commands (old Canvas). - else if (!$.browser.msie) { + else if (!browser.msie) { // Render directly at half-resolution var sz = Math.floor(size / 2); calculateMask(sz, sz, function (x, y, c, a) { diff --git a/src/static/js/html10n.js b/src/static/js/html10n.js index 49a0a80dc..19cf9de18 100644 --- a/src/static/js/html10n.js +++ b/src/static/js/html10n.js @@ -23,28 +23,16 @@ window.html10n = (function(window, document, undefined) { // fix console - var console = window.console - function interceptConsole(method){ - if (!console) return function() {} - - var original = console[method] - - // do sneaky stuff - if (original.bind){ - // Do this for normal browsers - return original.bind(console) - }else{ - return function() { - // Do this for IE - var message = Array.prototype.slice.apply(arguments).join(' ') - original(message) - } + (function() { + var noop = function() {}; + var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; + var console = (window.console = window.console || {}); + for (var i = 0; i < names.length; ++i) { + if (!console[names[i]]) { + console[names[i]] = noop; } - } - var consoleLog = interceptConsole('log') - , consoleWarn = interceptConsole('warn') - , consoleError = interceptConsole('warn') - + } + }()); // fix Array#forEach in IE // taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach @@ -148,7 +136,7 @@ window.html10n = (function(window, document, undefined) { for (var i=0, n=this.resources.length; i < n; i++) { this.fetch(this.resources[i], lang, function(e) { reqs++; - if(e) consoleWarn(e) + if(e) console.warn(e) if (reqs < n) return;// Call back once all reqs are completed cb && cb() @@ -647,7 +635,7 @@ window.html10n = (function(window, document, undefined) { // return a function that gives the plural form name for a given integer var index = locales2rules[lang.replace(/-.*$/, '')]; if (!(index in pluralRules)) { - consoleWarn('plural form unknown for [' + lang + ']'); + console.warn('plural form unknown for [' + lang + ']'); return function() { return 'other'; }; } return pluralRules[index]; @@ -727,7 +715,7 @@ window.html10n = (function(window, document, undefined) { var i = 0 , n = list.length iterator(list[i], i, function each(err) { - if(err) consoleLog(err) + if(err) console.error(err) i++ if (i < n) return iterator(list[i],i, each); cb() @@ -750,8 +738,8 @@ window.html10n = (function(window, document, undefined) { html10n.get = function(id, args) { var translations = html10n.translations - if(!translations) return consoleWarn('No translations available (yet)') - if(!translations[id]) return consoleWarn('Could not find string '+id) + if(!translations) return console.warn('No translations available (yet)') + if(!translations[id]) return console.warn('Could not find string '+id) // apply macros var str = translations[id] @@ -781,7 +769,7 @@ window.html10n = (function(window, document, undefined) { } else if (arg in translations) { sub = translations[arg] } else { - consoleWarn('Could not find argument {{' + arg + '}}') + console.warn('Could not find argument {{' + arg + '}}') return str } @@ -840,7 +828,7 @@ window.html10n = (function(window, document, undefined) { str.id = node.getAttribute('data-l10n-id') if (!str.id) return - if(!translations[str.id]) return consoleWarn('Couldn\'t find translation key '+str.id) + if(!translations[str.id]) return console.warn('Couldn\'t find translation key '+str.id) // get args if(window.JSON) { @@ -849,7 +837,7 @@ window.html10n = (function(window, document, undefined) { try{ str.args = eval(node.getAttribute('data-l10n-args')) }catch(e) { - consoleWarn('Couldn\'t parse args for '+str.id) + console.warn('Couldn\'t parse args for '+str.id) } } @@ -887,7 +875,7 @@ window.html10n = (function(window, document, undefined) { } } if (!found) { - consoleWarn('Unexpected error: could not translate element content for key '+str.id, node) + console.warn('Unexpected error: could not translate element content for key '+str.id, node) } } } diff --git a/src/static/js/jquery_browser.js b/src/static/js/jquery_browser.js deleted file mode 100644 index 0d61e0ddd..000000000 --- a/src/static/js/jquery_browser.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - 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; - } -})(); \ No newline at end of file diff --git a/src/static/js/linestylefilter.js b/src/static/js/linestylefilter.js index cb1ee1d50..675f19d02 100644 --- a/src/static/js/linestylefilter.js +++ b/src/static/js/linestylefilter.js @@ -34,7 +34,6 @@ var linestylefilter = {}; var _ = require('./underscore'); var AttributeManager = require('./AttributeManager'); - linestylefilter.ATTRIB_CLASSES = { 'bold': 'tag:b', 'italic': 'tag:i', @@ -59,6 +58,13 @@ linestylefilter.getAuthorClassName = function(author) linestylefilter.getLineStyleFilter = function(lineLength, aline, textAndClassFunc, apool) { + // Plugin Hook to add more Attrib Classes + hooks.aCallAll('aceAttribClasses', linestylefilter.ATTRIB_CLASSES, function(err, ATTRIB_CLASSES){ + if(ATTRIB_CLASSES.length >= 1){ + linestylefilter.ATTRIB_CLASSES = ATTRIB_CLASSES[0]; + } + }); + if (lineLength == 0) return textAndClassFunc; var nextAfterAuthorColors = textAndClassFunc; diff --git a/src/static/js/pad.js b/src/static/js/pad.js index 73fcd3d6b..ff62f86cc 100644 --- a/src/static/js/pad.js +++ b/src/static/js/pad.js @@ -43,7 +43,6 @@ var padsavedrevs = require('./pad_savedrevs'); var paduserlist = require('./pad_userlist').paduserlist; var padutils = require('./pad_utils').padutils; var colorutils = require('./colorutils').colorutils; - var createCookie = require('./pad_utils').createCookie; var readCookie = require('./pad_utils').readCookie; var randomString = require('./pad_utils').randomString; @@ -51,6 +50,8 @@ var gritter = require('./gritter').gritter; var hooks = require('./pluginfw/hooks'); +var receivedClientVars = false; + function createCookie(name, value, days, path){ /* Warning Internet Explorer doesn't use this it uses the one from pad_utils.js */ if (days) { @@ -67,7 +68,7 @@ function createCookie(name, value, days, path){ /* Warning Internet Explorer doe } //Check if the browser is IE and if so make sure the full path is set in the cookie - if(navigator.appName=='Microsoft Internet Explorer'){ + if((navigator.appName == 'Microsoft Internet Explorer') || ((navigator.appName == 'Netscape') && (new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null))){ document.cookie = name + "=" + value + expires + "; path="+document.location; } else{ @@ -160,6 +161,49 @@ function savePassword() return false; } +function sendClientReady(isReconnect, messageType) +{ + messageType = typeof messageType !== 'undefined' ? messageType : 'CLIENT_READY'; + var padId = document.location.pathname.substring(document.location.pathname.lastIndexOf("/") + 1); + padId = decodeURIComponent(padId); // unescape neccesary due to Safari and Opera interpretation of spaces + + if(!isReconnect) + { + var titleArray = document.title.split('|'); + var title = titleArray[titleArray.length - 1]; + document.title = padId.replace(/_+/g, ' ') + " | " + title; + } + + var token = readCookie("token"); + if (token == null) + { + token = "t." + randomString(); + createCookie("token", token, 60); + } + + var sessionID = decodeURIComponent(readCookie("sessionID")); + var password = readCookie("password"); + + var msg = { + "component": "pad", + "type": messageType, + "padId": padId, + "sessionID": sessionID, + "password": password, + "token": token, + "protocolVersion": 2 + }; + + //this is a reconnect, lets tell the server our revisionnumber + if(isReconnect == true) + { + msg.client_rev=pad.collabClient.getCurrentRevisionNumber(); + msg.reconnect=true; + } + + socket.json.send(msg); +} + function handshake() { var loc = document.location; @@ -171,49 +215,13 @@ function handshake() var resource = exports.baseURL.substring(1) + "socket.io"; //connect socket = pad.socket = io.connect(url, { - resource: resource, + // Allow deployers to host Etherpad on a non-root path + 'path': exports.baseURL + "socket.io", + 'resource': resource, 'max reconnection attempts': 3, 'sync disconnect on unload' : false }); - function sendClientReady(isReconnect) - { - var padId = document.location.pathname.substring(document.location.pathname.lastIndexOf("/") + 1); - padId = decodeURIComponent(padId); // unescape neccesary due to Safari and Opera interpretation of spaces - - if(!isReconnect) - document.title = padId.replace(/_+/g, ' ') + " | " + document.title; - - var token = readCookie("token"); - if (token == null) - { - token = "t." + randomString(); - createCookie("token", token, 60); - } - - var sessionID = decodeURIComponent(readCookie("sessionID")); - var password = readCookie("password"); - - var msg = { - "component": "pad", - "type": "CLIENT_READY", - "padId": padId, - "sessionID": sessionID, - "password": password, - "token": token, - "protocolVersion": 2 - }; - - //this is a reconnect, lets tell the server our revisionnumber - if(isReconnect == true) - { - msg.client_rev=pad.collabClient.getCurrentRevisionNumber(); - msg.reconnect=true; - } - - socket.json.send(msg); - }; - var disconnectTimeout; socket.once('connect', function () { @@ -228,7 +236,7 @@ function handshake() } pad.collabClient.setChannelState("CONNECTED"); - sendClientReady(true); + pad.sendClientReady(true); }); socket.on('disconnect', function (reason) { @@ -246,7 +254,6 @@ function handshake() } }); - var receivedClientVars = false; var initalized = false; socket.on('message', function(obj) @@ -286,7 +293,7 @@ function handshake() } //if we haven't recieved the clientVars yet, then this message should it be - else if (!receivedClientVars) + else if (!receivedClientVars && obj.type == "CLIENT_VARS") { //log the message if (window.console) console.log(obj); @@ -386,7 +393,6 @@ var pad = { diagnosticInfo: {}, initTime: 0, clientTimeOffset: null, - preloadedImages: false, padOptions: {}, // these don't require init; clientVars should all go through here @@ -426,6 +432,30 @@ var pad = { { return pad.myUserInfo.name; }, + sendClientReady: function(isReconnect, messageType) + { + messageType = typeof messageType !== 'undefined' ? messageType : 'CLIENT_READY'; + sendClientReady(isReconnect, messageType); + }, + switchToPad: function(padId) + { + var options = document.location.href.split('?')[1]; + var newHref = "/p/" + padId; + if (options != null) + newHref = newHref + '?' + options; + + if(window.history && window.history.pushState) + { + $('#chattext p').remove(); //clear the chat messages + window.history.pushState("", "", newHref); + receivedClientVars = false; + sendClientReady(false, 'SWITCH_TO_PAD'); + } + else // fallback + { + window.location.href = newHref; + } + }, sendClientMessage: function(msg) { pad.collabClient.sendClientMessage(msg); @@ -442,6 +472,16 @@ var pad = { if (typeof customStart == "function") customStart(); getParams(); handshake(); + + // To use etherpad you have to allow cookies. + // This will check if the creation of a test-cookie has success. + // Otherwise it shows up a message to the user. + createCookie("test", "test"); + if (!readCookie("test")) + { + $('#loading').hide(); + $('#noCookie').show(); + } }); }, _afterHandshake: function() @@ -454,13 +494,13 @@ var pad = { pad.initTime = +(new Date()); pad.padOptions = clientVars.initialOptions; - if ((!$.browser.msie) && (!($.browser.mozilla && $.browser.version.indexOf("1.8.") == 0))) + if ((!browser.msie) && (!(browser.mozilla && browser.version.indexOf("1.8.") == 0))) { document.domain = document.domain; // for comet } // for IE - if ($.browser.msie) + if (browser.msie) { try { @@ -525,6 +565,15 @@ var pad = { if(padcookie.getPref("showAuthorshipColors") == false){ pad.changeViewOption('showAuthorColors', false); } + if(padcookie.getPref("showLineNumbers") == false){ + pad.changeViewOption('showLineNumbers', false); + } + if(padcookie.getPref("rtlIsTrue") == true){ + pad.changeViewOption('rtlIsTrue', true); + } + if(padcookie.getPref("useMonospaceFont") == true){ + pad.changeViewOption('useMonospaceFont', true); + } hooks.aCallAll("postAceInit", {ace: padeditor.ace, pad: pad}); } }, @@ -575,6 +624,7 @@ var pad = { for (var k in opts.view) { pad.padOptions.view[k] = opts.view[k]; + padcookie.setPref(k, opts.view[k]); } padeditor.setViewOptions(pad.padOptions.view); } @@ -728,23 +778,8 @@ var pad = { }, handleIsFullyConnected: function(isConnected, isInitialConnect) { - // load all images referenced from CSS, one at a time, - // starting one second after connection is first established. - if (isConnected && !pad.preloadedImages) - { - window.setTimeout(function() - { - if (!pad.preloadedImages) - { - pad.preloadImages(); - pad.preloadedImages = true; - } - }, 1000); - } - pad.determineChatVisibility(isConnected && !isInitialConnect); pad.determineAuthorshipColorsVisibility(); - }, determineChatVisibility: function(asNowConnectedFeedback){ var chatVisCookie = padcookie.getPref('chatAlwaysVisible'); @@ -837,34 +872,6 @@ var pad = { { pad.collabClient.addHistoricalAuthors(data); } - }, - preloadImages: function() - { - var images = ["../static/img/connectingbar.gif"]; - - function loadNextImage() - { - if (images.length == 0) - { - return; - } - var img = new Image(); - img.src = images.shift(); - if (img.complete) - { - scheduleLoadNextImage(); - } - else - { - $(img).bind('error load onreadystatechange', scheduleLoadNextImage); - } - } - - function scheduleLoadNextImage() - { - window.setTimeout(loadNextImage, 0); - } - scheduleLoadNextImage(); } }; @@ -937,4 +944,3 @@ exports.handshake = handshake; exports.pad = pad; exports.init = init; exports.alertBar = alertBar; - diff --git a/src/static/js/pad_editbar.js b/src/static/js/pad_editbar.js index 859632171..e874614f3 100644 --- a/src/static/js/pad_editbar.js +++ b/src/static/js/pad_editbar.js @@ -140,15 +140,25 @@ var padeditbar = (function() init: function() { var self = this; self.dropdowns = []; - + // Listen for resize events (sucks but needed as iFrame ace_inner has to be position absolute + // A CSS fix for this would be nice but I'm not sure how we'd do it. + $(window).resize(function(){ + self.redrawHeight(); + }); + $("#editbar .editbarbutton").attr("unselectable", "on"); // for IE $("#editbar").removeClass("disabledtoolbar").addClass("enabledtoolbar"); $("#editbar [data-key]").each(function () { + $(this).unbind("click"); (new ToolbarItem($(this))).bind(function (command, item) { self.triggerCommand(command, item); }); }); + $('#editbar').show(); + + this.redrawHeight(); + registerDefaultCommands(self); hooks.callAll("postToolbarInit", { @@ -170,6 +180,16 @@ var padeditbar = (function() this.commands[cmd] = callback; return this; }, + redrawHeight: function(){ + var editbarHeight = $('.menu_left').height() + 1 + "px"; + var containerTop = $('.menu_left').height() + 6 + "px"; + $('#editbar').css("height", editbarHeight); + + $('#editorcontainer').css("top", containerTop); + if($('#options-stickychat').is(":checked")){ + $('#chatbox').css("top", $('#editorcontainer').offset().top + "px"); + }; + }, registerDropdownCommand: function (cmd, dropdown) { dropdown = dropdown || cmd; self.dropdowns.push(dropdown) @@ -206,7 +226,7 @@ var padeditbar = (function() if(module.css('display') != "none") { - $("#" + self.dropdowns[i] + "link").removeClass("selected"); + $("li[data-key=" + self.dropdowns[i] + "] > a").removeClass("selected"); module.slideUp("fast", cb); returned = true; } @@ -223,12 +243,12 @@ var padeditbar = (function() if(module.css('display') != "none") { - $("#" + self.dropdowns[i] + "link").removeClass("selected"); + $("li[data-key=" + self.dropdowns[i] + "] > a").removeClass("selected"); module.slideUp("fast"); } else if(self.dropdowns[i]==moduleName) { - $("#" + self.dropdowns[i] + "link").addClass("selected"); + $("li[data-key=" + self.dropdowns[i] + "] > a").addClass("selected"); module.slideDown("fast", cb); } } @@ -271,7 +291,7 @@ var padeditbar = (function() toolbar.registerDropdownCommand("showusers", "users"); toolbar.registerDropdownCommand("settings"); toolbar.registerDropdownCommand("connectivity"); - toolbar.registerDropdownCommand("import_export", "importexport"); + toolbar.registerDropdownCommand("import_export"); toolbar.registerDropdownCommand("embed"); toolbar.registerCommand("embed", function () { diff --git a/src/static/js/pad_impexp.js b/src/static/js/pad_impexp.js index aa48ad779..77f1eb289 100644 --- a/src/static/js/pad_impexp.js +++ b/src/static/js/pad_impexp.js @@ -35,32 +35,10 @@ var padimpexp = (function() function fileInputUpdated() { + $('#importsubmitinput').addClass('throbbold'); $('#importformfilediv').addClass('importformenabled'); $('#importsubmitinput').removeAttr('disabled'); - $('#importmessagefail').fadeOut("fast"); - $('#importarrow').show(); - $('#importarrow').animate( - { - paddingLeft: "0px" - }, 500).animate( - { - paddingLeft: "10px" - }, 150, 'swing').animate( - { - paddingLeft: "0px" - }, 150, 'swing').animate( - { - paddingLeft: "10px" - }, 150, 'swing').animate( - { - paddingLeft: "0px" - }, 150, 'swing').animate( - { - paddingLeft: "10px" - }, 150, 'swing').animate( - { - paddingLeft: "0px" - }, 150, 'swing'); + $('#importmessagefail').fadeOut('fast'); } function fileInputSubmit() @@ -131,6 +109,8 @@ var padimpexp = (function() msg = html10n.get("pad.impexp.convertFailed"); } else if(status === "uploadFailed"){ msg = html10n.get("pad.impexp.uploadFailed"); + } else if(status === "padHasData"){ + msg = html10n.get("pad.impexp.padHasData"); } function showError(fade) @@ -220,8 +200,8 @@ var padimpexp = (function() // build the export links $("#exporthtmla").attr("href", pad_root_path + "/export/html"); + $("#exportetherpada").attr("href", pad_root_path + "/export/etherpad"); $("#exportplaina").attr("href", pad_root_path + "/export/txt"); - $("#exportdokuwikia").attr("href", pad_root_path + "/export/dokuwiki"); // activate action to import in the form $("#importform").attr('action', pad_root_url + "/import"); @@ -257,13 +237,13 @@ var padimpexp = (function() $('#importform').submit(fileInputSubmit); $('.disabledexport').click(cantExport); }, - handleFrameCall: function(status) + handleFrameCall: function(directDatabaseAccess, status) { if (status !== "ok") { importFailed(status); } - + if(directDatabaseAccess) pad.switchToPad(clientVars.padId); importDone(); }, disable: function() diff --git a/src/static/js/pad_userlist.js b/src/static/js/pad_userlist.js index ebb057c82..d306256a2 100644 --- a/src/static/js/pad_userlist.js +++ b/src/static/js/pad_userlist.js @@ -468,6 +468,8 @@ var paduserlist = (function() self.setMyUserInfo(myInitialUserInfo); + if($('#online_count').length === 0) $('#editbar [data-key=showusers] > a').append('1'); + $("#otheruserstable tr").remove(); if (pad.getUserIsGuest()) @@ -602,13 +604,8 @@ var paduserlist = (function() online++; } } - var $btn = $("#editbar [data-key=showusers] > a") - , $counter = $('#online_count', $btn) - if(!$counter.length) { - $counter = $('') - $btn.append($counter) - } - $counter.text(online); + + $('#online_count').text(online); return online; }, @@ -733,7 +730,7 @@ var paduserlist = (function() $("#myswatch").css({'background-color': myUserInfo.colorId}); - if ($.browser.msie && parseInt($.browser.version) <= 8) { + if (browser.msie && parseInt(browser.version) <= 8) { $("li[data-key=showusers] > a").css({'box-shadow': 'inset 0 0 30px ' + myUserInfo.colorId,'background-color': myUserInfo.colorId}); } else diff --git a/src/static/js/pad_utils.js b/src/static/js/pad_utils.js index bab6aa432..ff60ca7c6 100644 --- a/src/static/js/pad_utils.js +++ b/src/static/js/pad_utils.js @@ -55,7 +55,7 @@ function createCookie(name, value, days, path){ /* Used by IE */ } //Check if the browser is IE and if so make sure the full path is set in the cookie - if(navigator.appName=='Microsoft Internet Explorer'){ + if((navigator.appName == 'Microsoft Internet Explorer') || ((navigator.appName == 'Netscape') && (new RegExp("Trident/.*rv:([0-9]{1,}[\.0-9]{0,})").exec(navigator.userAgent) != null))){ document.cookie = name + "=" + value + expires + "; path=/"; /* Note this bodge fix for IE is temporary until auth is rewritten */ } else{ @@ -482,7 +482,7 @@ var padutils = { }, bindCheckboxChange: function(node, func) { - $(node).bind("click change", func); + $(node).change(func); }, encodeUserId: function(userId) { @@ -515,12 +515,13 @@ function setupGlobalExceptionHandler() { globalExceptionHandler = function test (msg, url, linenumber) { var errorId = randomString(20); + var userAgent = padutils.escapeHtml(navigator.userAgent); if ($("#editorloadingbox").attr("display") != "none"){ //show javascript errors to the user $("#editorloadingbox").css("padding", "10px"); $("#editorloadingbox").css("padding-top", "45px"); $("#editorloadingbox").html("
    An error occured
    The error was reported with the following id: '" + errorId + "'

    Please press and hold Ctrl and press F5 to reload this page, if the problem persists please send this error message to your webmaster:
    '" - + "ErrorId: " + errorId + "
    URL: " + window.location.href + "
    UserAgent: " + navigator.userAgent + "
    " + msg + " in " + url + " at line " + linenumber + "'
    "); + + "ErrorId: " + errorId + "
    URL: " + window.location.href + "
    UserAgent: " + userAgent + "
    " + msg + " in " + url + " at line " + linenumber + "'"); } //send javascript errors to the server diff --git a/src/static/js/pluginfw/hooks.js b/src/static/js/pluginfw/hooks.js index a8ac413f6..cf5fcc4eb 100644 --- a/src/static/js/pluginfw/hooks.js +++ b/src/static/js/pluginfw/hooks.js @@ -41,7 +41,7 @@ exports.syncMapFirst = function (lst, fn) { exports.mapFirst = function (lst, fn, cb) { var i = 0; - next = function () { + var next = function () { if (i >= lst.length) return cb(undefined); fn(lst[i++], function (err, result) { if (err) return cb(err); diff --git a/src/static/js/pluginfw/installer.js b/src/static/js/pluginfw/installer.js index 9f7ac939f..90bd9aa27 100644 --- a/src/static/js/pluginfw/installer.js +++ b/src/static/js/pluginfw/installer.js @@ -1,6 +1,7 @@ var plugins = require("ep_etherpad-lite/static/js/pluginfw/plugins"); var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks"); var npm = require("npm"); +var request = require("request"); var npmIsLoaded = false; var withNpm = function (npmfn) { @@ -60,17 +61,20 @@ exports.availablePlugins = null; var cacheTimestamp = 0; exports.getAvailablePlugins = function(maxCacheAge, cb) { - withNpm(function (er) { + request("http://etherpad.org/plugins.json", function(er, response, plugins){ if (er) return cb && cb(er); if(exports.availablePlugins && maxCacheAge && Math.round(+new Date/1000)-cacheTimestamp <= maxCacheAge) { return cb && cb(null, exports.availablePlugins) } - npm.commands.search(['ep_'], /*silent?*/true, function(er, results) { - if(er) return cb && cb(er); - exports.availablePlugins = results; - cacheTimestamp = Math.round(+new Date/1000); - cb && cb(null, results) - }) + try { + plugins = JSON.parse(plugins); + } catch (err) { + console.error('error parsing plugins.json:', err); + plugins = []; + } + exports.availablePlugins = plugins; + cacheTimestamp = Math.round(+new Date/1000); + cb && cb(null, plugins) }); }; diff --git a/src/static/js/rjquery.js b/src/static/js/rjquery.js index d9d1ed163..1c0d98e64 100644 --- a/src/static/js/rjquery.js +++ b/src/static/js/rjquery.js @@ -1,10 +1,5 @@ // Proviedes a require'able version of jQuery without leaking $ and jQuery; - require('./jquery'); var jq = window.$.noConflict(true); - -//added the old browser recognition -jq.browser = require('./jquery_browser').browser; - -exports.jQuery = exports.$ = jq; \ No newline at end of file +exports.jQuery = exports.$ = jq; diff --git a/src/templates/admin/index.html b/src/templates/admin/index.html index 750a4b52e..f6e9e29ef 100644 --- a/src/templates/admin/index.html +++ b/src/templates/admin/index.html @@ -10,7 +10,7 @@