resolve merge conflict

This commit is contained in:
John McLear 2013-02-20 22:37:27 +00:00
commit 4a98ec3c23
25 changed files with 658 additions and 186 deletions

View File

@ -3,7 +3,15 @@
* NEW: Plugins can now provide their own frontend tests * NEW: Plugins can now provide their own frontend tests
* NEW: Improved server-side logging * NEW: Improved server-side logging
* NEW: Admin dashboard mobile device support and new hooks for Admin dashboard * NEW: Admin dashboard mobile device support and new hooks for Admin dashboard
* NEW: Get current API version from API
* Fix: Text Export indentation now supports multiple indentations
* Fix: Bugfix getChatHistory API method * Fix: Bugfix getChatHistory API method
* Fix: Stop Chrome losing caret after paste is texted
* Fix: Make colons on end of line create 4 spaces on indent
* Fix: Make indent when on middle of the line stop creating list
* Fix: Stop long strings breaking the UX by moving focus away from beginning of line
* Fix: padUsersCount no longer hangs server
* Fix: Issue with two part locale specs not working
* Fix: Make plugin search case insensitive * Fix: Make plugin search case insensitive
* Fix: Indentation and bullets on text export * Fix: Indentation and bullets on text export
* Fix: Resolve various warnings on dependencies during install * Fix: Resolve various warnings on dependencies during install

View File

@ -28,7 +28,7 @@ documented codebase makes it easier for developers to improve the code and contr
Etherpad Lite is designed to be easily embeddable and provides a [HTTP API](https://github.com/ether/etherpad-lite/wiki/HTTP-API) Etherpad Lite is designed to be easily embeddable and provides a [HTTP API](https://github.com/ether/etherpad-lite/wiki/HTTP-API)
that allows your web application to manage pads, users and groups. It is recommended to use the [available client implementations](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) in order to interact with this API. There is also a [jQuery plugin](https://github.com/johnyma22/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website. that allows your web application to manage pads, users and groups. It is recommended to use the [available client implementations](https://github.com/ether/etherpad-lite/wiki/HTTP-API-client-libraries) in order to interact with this API. There is also a [jQuery plugin](https://github.com/ether/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website.
There's also a full-featured plugin framework, allowing you to easily add your own features. There's also a full-featured plugin framework, allowing you to easily add your own features.
Finally, Etherpad Lite comes with translations into tons of different languages! Finally, Etherpad Lite comes with translations into tons of different languages!
@ -108,7 +108,7 @@ You know all this and just want to know how you can help?
Look at the [TODO list](https://github.com/ether/etherpad-lite/wiki/TODO) and our [Issue tracker](https://github.com/ether/etherpad-lite/issues). (Please consider using [jshint](http://www.jshint.com/about/), if you plan to contribute code.) Look at the [TODO list](https://github.com/ether/etherpad-lite/wiki/TODO) and our [Issue tracker](https://github.com/ether/etherpad-lite/issues). (Please consider using [jshint](http://www.jshint.com/about/), if you plan to contribute code.)
Also, and most importantly, read our [**Developer Guidelines**](https://github.com/ether/etherpad-lite/wiki/Developer-Guidelines), really! Also, and most importantly, read our [**Developer Guidelines**](https://github.com/ether/etherpad-lite/blob/master/CONTRIBUTING.md), really!
# Get in touch # Get in touch
Join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) and make some noise on our freenode irc channel [#etherpad-lite-dev](http://webchat.freenode.net?channels=#etherpad-lite-dev)! Join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) and make some noise on our freenode irc channel [#etherpad-lite-dev](http://webchat.freenode.net?channels=#etherpad-lite-dev)!
@ -122,6 +122,7 @@ Join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) and mak
# Donate! # Donate!
* [Flattr] (http://flattr.com/thing/71378/Etherpad-Foundation) * [Flattr] (http://flattr.com/thing/71378/Etherpad-Foundation)
* Paypal - Press the donate button on [etherpad.org](http://etherpad.org) * Paypal - Press the donate button on [etherpad.org](http://etherpad.org)
* [Bitcoin] (https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a)
# License # License
[Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html) [Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html)

View File

@ -35,7 +35,8 @@ async.series([
function(callback) { function(callback) {
settings = require('../src/node/utils/Settings'); settings = require('../src/node/utils/Settings');
db = require('../src/node/db/DB'); db = require('../src/node/db/DB');
dirty = require("../src/node_modules/ueberDB/node_modules/dirty")(padId + ".db"); dirty = require("../node_modules/ep_etherpad-lite/node_modules/ueberDB/node_modules/dirty")(padId + ".db");
callback();
}, },
//intallize the database //intallize the database
function (callback) function (callback)
@ -45,7 +46,7 @@ async.series([
//get the pad //get the pad
function (callback) function (callback)
{ {
padManager = require('../node/db/PadManager'); padManager = require('../src/node/db/PadManager');
padManager.getPad(padId, function(err, _pad) padManager.getPad(padId, function(err, _pad)
{ {
@ -82,7 +83,10 @@ async.series([
db.db.db.wrappedDB.get(dbkey, function(err, dbvalue) db.db.db.wrappedDB.get(dbkey, function(err, dbvalue)
{ {
if(err) { callback(err); return} if(err) { callback(err); return}
dbvalue=JSON.parse(dbvalue);
if(typeof dbvalue != 'object'){
dbvalue=JSON.parse(dbvalue); // if its not json then parse it as json
}
dirty.set(dbkey, dbvalue, callback); dirty.set(dbkey, dbvalue, callback);
}); });

View File

@ -61,7 +61,9 @@ Portal submits content into new blog post
## Usage ## Usage
### API version ### API version
The latest version is `1.2` The latest version is `1.2.7`
The current version can be queried via /api.
### Request Format ### Request Format

56
src/locales/br.json Normal file
View File

@ -0,0 +1,56 @@
{
"index.newPad": "Pad nevez",
"index.createOpenPad": "pe kroui\u00f1\/digeri\u00f1 ur pad gant an anv :",
"pad.toolbar.bold.title": "Tev (Ctrl-B)",
"pad.toolbar.italic.title": "Italek (Ctrl-I)",
"pad.toolbar.underline.title": "Islinenna\u00f1 (Ctrl-U)",
"pad.toolbar.indent.title": "Endanta\u00f1",
"pad.toolbar.unindent.title": "Diendanta\u00f1",
"pad.toolbar.settings.title": "Arventenno\u00f9",
"pad.colorpicker.save": "Enrolla\u00f1",
"pad.colorpicker.cancel": "Nulla\u00f1",
"pad.loading": "O karga\u00f1...",
"pad.settings.myView": "Ma diskwel",
"pad.settings.fontType.normal": "Reizh",
"pad.settings.language": "Yezh :",
"pad.importExport.import_export": "Enporzhia\u00f1\/Ezporzhia\u00f1",
"pad.importExport.import": "Enkarga\u00f1 un destenn pe ur restr",
"pad.importExport.exporthtml": "HTML",
"pad.importExport.exportplain": "Testenn blaen",
"pad.importExport.exportword": "Microsoft Word",
"pad.importExport.exportpdf": "PDF",
"pad.importExport.exportopen": "ODF (Open Document Format)",
"pad.importExport.exportdokuwiki": "DokuWiki",
"pad.modals.connected": "Kevreet.",
"pad.modals.slowcommit": "Digevreet.",
"pad.share.readonly": "Lenn hepken",
"pad.share.link": "Liamm",
"pad.chat": "Flap",
"timeslider.toolbar.authors": "Aozerien :",
"timeslider.toolbar.authorsList": "Aozer ebet",
"timeslider.toolbar.exportlink.title": "Ezporzhia\u00f1",
"timeslider.month.january": "Genver",
"timeslider.month.february": "C'hwevrer",
"timeslider.month.march": "Meurzh",
"timeslider.month.april": "Ebrel",
"timeslider.month.may": "Mae",
"timeslider.month.june": "Mezheven",
"timeslider.month.july": "Gouere",
"timeslider.month.august": "Eost",
"timeslider.month.september": "Gwengolo",
"timeslider.month.october": "Here",
"timeslider.month.november": "Du",
"timeslider.month.december": "Kerzu",
"pad.userlist.guest": "Den pedet",
"pad.userlist.deny": "Nac'h",
"pad.userlist.approve": "Aproui\u00f1",
"pad.impexp.importbutton": "Enporzhia\u00f1 brema\u00f1",
"pad.impexp.importing": "Oc'h enporzhia\u00f1...",
"pad.impexp.importfailed": "C'hwitet eo an enporzhiadenn",
"@metadata": {
"authors": [
"Fulup",
"Y-M D"
]
}
}

View File

@ -19,7 +19,7 @@
"pad.toolbar.clearAuthorship.title": "\u4f5c\u8005\u306e\u8272\u5206\u3051\u3092\u6d88\u53bb", "pad.toolbar.clearAuthorship.title": "\u4f5c\u8005\u306e\u8272\u5206\u3051\u3092\u6d88\u53bb",
"pad.toolbar.import_export.title": "\u4ed6\u306e\u5f62\u5f0f\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\/\u30a8\u30af\u30b9\u30dd\u30fc\u30c8", "pad.toolbar.import_export.title": "\u4ed6\u306e\u5f62\u5f0f\u306e\u30d5\u30a1\u30a4\u30eb\u306e\u30a4\u30f3\u30dd\u30fc\u30c8\/\u30a8\u30af\u30b9\u30dd\u30fc\u30c8",
"pad.toolbar.timeslider.title": "\u30bf\u30a4\u30e0\u30b9\u30e9\u30a4\u30c0\u30fc", "pad.toolbar.timeslider.title": "\u30bf\u30a4\u30e0\u30b9\u30e9\u30a4\u30c0\u30fc",
"pad.toolbar.savedRevision.title": "\u4fdd\u5b58\u6e08\u307f\u306e\u7248", "pad.toolbar.savedRevision.title": "\u7248\u3092\u4fdd\u5b58",
"pad.toolbar.settings.title": "\u8a2d\u5b9a", "pad.toolbar.settings.title": "\u8a2d\u5b9a",
"pad.toolbar.embed.title": "\u3053\u306e\u30d1\u30c3\u30c9\u3092\u57cb\u3081\u8fbc\u3080", "pad.toolbar.embed.title": "\u3053\u306e\u30d1\u30c3\u30c9\u3092\u57cb\u3081\u8fbc\u3080",
"pad.toolbar.showusers.title": "\u3053\u306e\u30d1\u30c3\u30c9\u306e\u30e6\u30fc\u30b6\u30fc\u3092\u8868\u793a", "pad.toolbar.showusers.title": "\u3053\u306e\u30d1\u30c3\u30c9\u306e\u30e6\u30fc\u30b6\u30fc\u3092\u8868\u793a",
@ -87,7 +87,7 @@
"timeslider.exportCurrent": "\u73fe\u5728\u306e\u7248\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3059\u308b\u5f62\u5f0f:", "timeslider.exportCurrent": "\u73fe\u5728\u306e\u7248\u3092\u30a8\u30af\u30b9\u30dd\u30fc\u30c8\u3059\u308b\u5f62\u5f0f:",
"timeslider.version": "\u30d0\u30fc\u30b8\u30e7\u30f3 {{version}}", "timeslider.version": "\u30d0\u30fc\u30b8\u30e7\u30f3 {{version}}",
"timeslider.saved": "| {{year}}\u5e74{{month}}{{day}}\u65e5\u306b\u4fdd\u5b58", "timeslider.saved": "| {{year}}\u5e74{{month}}{{day}}\u65e5\u306b\u4fdd\u5b58",
"timeslider.dateformat": "{{year}}\u5e74{{month}}{{day}}\u65e5 {{hours}}:{{minutes}}:{{seconds}}", "timeslider.dateformat": "{{year}}\u5e74{{month}}\u6708{{day}}\u65e5 {{hours}}:{{minutes}}:{{seconds}}",
"timeslider.month.january": "1\u6708", "timeslider.month.january": "1\u6708",
"timeslider.month.february": "2\u6708", "timeslider.month.february": "2\u6708",
"timeslider.month.march": "3\u6708", "timeslider.month.march": "3\u6708",

View File

@ -19,13 +19,16 @@
"pad.toolbar.clearAuthorship.title": "d\u00e4 Schriiver ier F\u00e4rve fottn\u00e4mme", "pad.toolbar.clearAuthorship.title": "d\u00e4 Schriiver ier F\u00e4rve fottn\u00e4mme",
"pad.toolbar.import_export.title": "Vun ongerscheidlijje Dattei_Fommaate empotteere udder \u00e4xpotteere", "pad.toolbar.import_export.title": "Vun ongerscheidlijje Dattei_Fommaate empotteere udder \u00e4xpotteere",
"pad.toolbar.timeslider.title": "Verjangeheid afschpelle", "pad.toolbar.timeslider.title": "Verjangeheid afschpelle",
"pad.toolbar.savedRevision.title": "Fa\u00dfjehallde Versione", "pad.toolbar.savedRevision.title": "de Versjohn fa\u00dfhallde",
"pad.toolbar.settings.title": "Enscht\u00e4llonge", "pad.toolbar.settings.title": "Enscht\u00e4llonge",
"pad.toolbar.embed.title": "Donn dat Padd enbenge", "pad.toolbar.embed.title": "Donn dat Padd enbenge",
"pad.toolbar.showusers.title": "Verbonge Metschriiver aanzeije", "pad.toolbar.showusers.title": "Verbonge Metschriiver aanzeije",
"pad.colorpicker.save": "Fa\u00dfhallde", "pad.colorpicker.save": "Fa\u00dfhallde",
"pad.colorpicker.cancel": "Oph\u00fc\u00fcre", "pad.colorpicker.cancel": "Oph\u00fc\u00fcre",
"pad.loading": "Aam Laade …", "pad.loading": "Aam Laade …",
"pad.passwordRequired": "Do bruchs e Pa\u00dfwoot f\u00f6r heh dat P\u00e4dd.",
"pad.permissionDenied": "Do h\u00e4s nit dat R\u00e4\u00e4sch, op heh dat P\u00e4dd zohzejriife.",
"pad.wrongPassword": "Ding Pa\u00dfwoot wohr verkeht.",
"pad.settings.padSettings": "Dam P\u00e4dd sin Enscht\u00e4llonge", "pad.settings.padSettings": "Dam P\u00e4dd sin Enscht\u00e4llonge",
"pad.settings.myView": "Anseesch", "pad.settings.myView": "Anseesch",
"pad.settings.stickychat": "Donn der Klaaf emmer aanzeije", "pad.settings.stickychat": "Donn der Klaaf emmer aanzeije",
@ -38,6 +41,7 @@
"pad.settings.language": "Schprooch:", "pad.settings.language": "Schprooch:",
"pad.importExport.import_export": "Empoot\/\u00c4xpoot", "pad.importExport.import_export": "Empoot\/\u00c4xpoot",
"pad.importExport.import": "Donn jeede T\u00e4x udder jeede Zoot Dokem\u00e4nt huhlaade", "pad.importExport.import": "Donn jeede T\u00e4x udder jeede Zoot Dokem\u00e4nt huhlaade",
"pad.importExport.importSuccessful": "Jeschaff!",
"pad.importExport.export": "Don dat P\u00e4dd \u00e4xpoteere al\u00df:", "pad.importExport.export": "Don dat P\u00e4dd \u00e4xpoteere al\u00df:",
"pad.importExport.exporthtml": "HTML", "pad.importExport.exporthtml": "HTML",
"pad.importExport.exportplain": "Eijfach T\u00e4x", "pad.importExport.exportplain": "Eijfach T\u00e4x",
@ -45,9 +49,11 @@
"pad.importExport.exportpdf": "PDF (Poteerbaa Dokem\u00e4nte Fommaat)", "pad.importExport.exportpdf": "PDF (Poteerbaa Dokem\u00e4nte Fommaat)",
"pad.importExport.exportopen": "ODF (Offe Dokem\u00e4nte-Fommaat)", "pad.importExport.exportopen": "ODF (Offe Dokem\u00e4nte-Fommaat)",
"pad.importExport.exportdokuwiki": "DokuWiki", "pad.importExport.exportdokuwiki": "DokuWiki",
"pad.importExport.abiword.innerHTML": "Mer k\u00fcnne blo\u00df eijfaache T\u00e4xte udder HTML_Fommaate empoteere. Opw\u00e4ndejere M\u00fcjjeleschkeite f\u00f6 der Empoot jon och, dof\u00f6r bruch mer en <a href=\"https:\/\/github.com\/ether\/etherpad-lite\/wiki\/How-to-enable-importing-and-exporting-different-file-formats-in-Ubuntu-or-OpenSuse-or-SLES-with-AbiWord\">Enschtallazjuhn met <i lang=\"en\">Abiword<\/i><\/a>.",
"pad.modals.connected": "Verbonge.", "pad.modals.connected": "Verbonge.",
"pad.modals.reconnecting": "Ben wider aam Verbenge&nbsp;&hellip;", "pad.modals.reconnecting": "Ben wider aam Verbenge&nbsp;&hellip;",
"pad.modals.forcereconnect": "Wider verbenge", "pad.modals.forcereconnect": "Wider verbenge",
"pad.modals.userdup": "En enem andere Finster en \u00c4rbeid",
"pad.modals.userdup.explanation": "Heh dat Padd schingk en mieh wi einem Finster vun enem Brauser op heh d\u00e4m R\u00e4\u00e4schner op ze sin.", "pad.modals.userdup.explanation": "Heh dat Padd schingk en mieh wi einem Finster vun enem Brauser op heh d\u00e4m R\u00e4\u00e4schner op ze sin.",
"pad.modals.userdup.advice": "En heh d\u00e4m Finster wider verbenge.", "pad.modals.userdup.advice": "En heh d\u00e4m Finster wider verbenge.",
"pad.modals.unauth": "Nit ber\u00e4\u00e4schtesch", "pad.modals.unauth": "Nit ber\u00e4\u00e4schtesch",
@ -72,10 +78,12 @@
"pad.share.emebdcode": "URL enboue", "pad.share.emebdcode": "URL enboue",
"pad.chat": "Klaaf", "pad.chat": "Klaaf",
"pad.chat.title": "Maach d\u00e4 Klaaf f\u00f6r heh dat P\u00e4dd op", "pad.chat.title": "Maach d\u00e4 Klaaf f\u00f6r heh dat P\u00e4dd op",
"pad.chat.loadmessages": "Mieh Nohresschte laade...",
"timeslider.pageTitle": "{{appTitle}} - Verjangeheid affschpelle", "timeslider.pageTitle": "{{appTitle}} - Verjangeheid affschpelle",
"timeslider.toolbar.returnbutton": "Jangk retuur nohm P\u00e4dd", "timeslider.toolbar.returnbutton": "Jangk retuur nohm P\u00e4dd",
"timeslider.toolbar.authors": "Schriiver:", "timeslider.toolbar.authors": "Schriiver:",
"timeslider.toolbar.authorsList": "Kein Schriivere", "timeslider.toolbar.authorsList": "Kein Schriivere",
"timeslider.toolbar.exportlink.title": "\u00c4xpoot",
"timeslider.exportCurrent": "Donn de meu\u00dfte V\u00e4sjohn \u00e4xpotteere al\u00df:", "timeslider.exportCurrent": "Donn de meu\u00dfte V\u00e4sjohn \u00e4xpotteere al\u00df:",
"timeslider.version": "V\u00e4sjon {{version}}", "timeslider.version": "V\u00e4sjon {{version}}",
"timeslider.saved": "Fa\u00dfjehallde aam {{day}}. {{month}} {{year}}", "timeslider.saved": "Fa\u00dfjehallde aam {{day}}. {{month}} {{year}}",
@ -92,11 +100,19 @@
"timeslider.month.october": "Oktoober", "timeslider.month.october": "Oktoober",
"timeslider.month.november": "Nov\u00e4mber", "timeslider.month.november": "Nov\u00e4mber",
"timeslider.month.december": "Dez\u00e4mber", "timeslider.month.december": "Dez\u00e4mber",
"timeslider.unnamedauthor": "{{num}} naameloose Schriever",
"timeslider.unnamedauthors": "{{num}} naameloose Schriever",
"pad.savedrevs.marked": "Heh di V\u00e4sjohn es j\u00e4z fa\u00dfjehallde.",
"pad.userlist.entername": "Jif Dinge Naame en", "pad.userlist.entername": "Jif Dinge Naame en",
"pad.userlist.unnamed": "naamelo\u00df\u00df", "pad.userlist.unnamed": "naamelo\u00df\u00df",
"pad.userlist.guest": "Ja\u00df\u00df", "pad.userlist.guest": "Ja\u00df\u00df",
"pad.userlist.deny": "Aflehne", "pad.userlist.deny": "Aflehne",
"pad.userlist.approve": "Joodhei\u00dfe",
"pad.editbar.clearcolors": "Sulle mer de F\u00e4rve f\u00f6r de Schriiver uss_em janze T\u00e4x fott maache?",
"pad.impexp.importbutton": "J\u00e4z empoteere",
"pad.impexp.importing": "Ben aam Empotteere&nbsp;&hellip;", "pad.impexp.importing": "Ben aam Empotteere&nbsp;&hellip;",
"pad.impexp.confirmimport": "En Dattei ze empotteere m\u00e4\u00e4t der janze T\u00e4x em P\u00e4dd fott. Wess De dat verfaftesch hann?",
"pad.impexp.convertFailed": "Mer kunnte di Dattei nit empoteere. Nemm en ander Dattei-Fommaat udder donn d\u00e4 T\u00e4x vun Hand kopeere un ennf\u00f6\u00f6je.",
"pad.impexp.uploadFailed": "Et Huhlaade es don\u00e4vve jejange, bes esu jood un probeer et norr_ens", "pad.impexp.uploadFailed": "Et Huhlaade es don\u00e4vve jejange, bes esu jood un probeer et norr_ens",
"pad.impexp.importfailed": "Et Empoteere es don\u00e4vve jejange", "pad.impexp.importfailed": "Et Empoteere es don\u00e4vve jejange",
"pad.impexp.copypaste": "Bes esu jood un donn et koppeere un enf\u00f6\u00f6je", "pad.impexp.copypaste": "Bes esu jood un donn et koppeere un enf\u00f6\u00f6je",

View File

@ -19,7 +19,7 @@
"pad.toolbar.clearAuthorship.title": "Limpar as cores de identifica\u00e7\u00e3o de autoria", "pad.toolbar.clearAuthorship.title": "Limpar as cores de identifica\u00e7\u00e3o de autoria",
"pad.toolbar.import_export.title": "Importar\/Exportar de\/para diferentes formatos de arquivo", "pad.toolbar.import_export.title": "Importar\/Exportar de\/para diferentes formatos de arquivo",
"pad.toolbar.timeslider.title": "Linha do tempo", "pad.toolbar.timeslider.title": "Linha do tempo",
"pad.toolbar.savedRevision.title": "Revis\u00f5es Salvas", "pad.toolbar.savedRevision.title": "Salvar revis\u00e3o",
"pad.toolbar.settings.title": "Configura\u00e7\u00f5es", "pad.toolbar.settings.title": "Configura\u00e7\u00f5es",
"pad.toolbar.embed.title": "Incorporar esta Nota", "pad.toolbar.embed.title": "Incorporar esta Nota",
"pad.toolbar.showusers.title": "Mostrar os usuarios nesta Nota", "pad.toolbar.showusers.title": "Mostrar os usuarios nesta Nota",
@ -100,6 +100,8 @@
"timeslider.month.october": "Outubro", "timeslider.month.october": "Outubro",
"timeslider.month.november": "Novembro", "timeslider.month.november": "Novembro",
"timeslider.month.december": "Dezembro", "timeslider.month.december": "Dezembro",
"timeslider.unnamedauthor": "{{num}} autor desconhecido",
"timeslider.unnamedauthors": "{{num}} autores desconhecidos",
"pad.savedrevs.marked": "Esta revis\u00e3o foi marcada como salva", "pad.savedrevs.marked": "Esta revis\u00e3o foi marcada como salva",
"pad.userlist.entername": "Insira o seu nome", "pad.userlist.entername": "Insira o seu nome",
"pad.userlist.unnamed": "Sem t\u00edtulo", "pad.userlist.unnamed": "Sem t\u00edtulo",

View File

@ -20,7 +20,7 @@
"pad.toolbar.redo.title": "\u91cd\u505a (Ctrl-Y)", "pad.toolbar.redo.title": "\u91cd\u505a (Ctrl-Y)",
"pad.toolbar.clearAuthorship.title": "\u6e05\u9664\u4f5c\u540d\u989c\u8272", "pad.toolbar.clearAuthorship.title": "\u6e05\u9664\u4f5c\u540d\u989c\u8272",
"pad.toolbar.timeslider.title": "\u65f6\u95f4\u8f74", "pad.toolbar.timeslider.title": "\u65f6\u95f4\u8f74",
"pad.toolbar.savedRevision.title": "\u5df2\u4fdd\u5b58\u7684\u4fee\u8ba2", "pad.toolbar.savedRevision.title": "\u4fdd\u5b58\u4fee\u8ba2",
"pad.toolbar.settings.title": "\u8bbe\u7f6e", "pad.toolbar.settings.title": "\u8bbe\u7f6e",
"pad.toolbar.embed.title": "\u5d4c\u5165\u6b64\u8bb0\u4e8b\u672c", "pad.toolbar.embed.title": "\u5d4c\u5165\u6b64\u8bb0\u4e8b\u672c",
"pad.toolbar.showusers.title": "\u663e\u793a\u6b64\u8bb0\u4e8b\u672c\u7684\u7528\u6237", "pad.toolbar.showusers.title": "\u663e\u793a\u6b64\u8bb0\u4e8b\u672c\u7684\u7528\u6237",

View File

@ -1,7 +1,8 @@
{ {
"@metadata": { "@metadata": {
"authors": { "authors": {
"1": "Simon Shek" "0": "Shirayuki",
"2": "Simon Shek"
} }
}, },
"index.newPad": "\u65b0Pad", "index.newPad": "\u65b0Pad",
@ -86,8 +87,8 @@
"timeslider.toolbar.exportlink.title": "\u532f\u51fa", "timeslider.toolbar.exportlink.title": "\u532f\u51fa",
"timeslider.exportCurrent": "\u532f\u51fa\u7576\u524d\u7248\u672c\u70ba\uff1a", "timeslider.exportCurrent": "\u532f\u51fa\u7576\u524d\u7248\u672c\u70ba\uff1a",
"timeslider.version": "\u7248\u672c{{version}}", "timeslider.version": "\u7248\u672c{{version}}",
"timeslider.saved": "{{year}}{{month}}{{day}}\u4fdd\u5b58", "timeslider.saved": "{{year}}\u5e74{{month}}{{day}}\u65e5\u4fdd\u5b58",
"timeslider.dateformat": "{{year}}{{month}}{{day}} {{hours}}:{{minutes}}:{{seconds}}", "timeslider.dateformat": "{{year}}\u5e74{{month}}\u6708{{day}}\u65e5 {{hours}}:{{minutes}}:{{seconds}}",
"timeslider.month.january": "1\u6708", "timeslider.month.january": "1\u6708",
"timeslider.month.february": "2\u6708", "timeslider.month.february": "2\u6708",
"timeslider.month.march": "3\u6708", "timeslider.month.march": "3\u6708",

View File

@ -146,12 +146,11 @@ exports.getPad = function(id, text, callback)
else else
{ {
pad = new Pad(id); pad = new Pad(id);
//initalize the pad //initalize the pad
pad.init(text, function(err) pad.init(text, function(err)
{ {
if(ERR(err, callback)) return; if(ERR(err, callback)) return;
globalPads.set(id, pad); globalPads.set(id, pad);
callback(null, pad); callback(null, pad);
}); });

View File

@ -216,6 +216,9 @@ var version =
} }
}; };
// set the latest available API version here
exports.latestApiVersion = '1.2.7';
/** /**
* Handles a HTTP API call * Handles a HTTP API call
* @param functionName the name of the called function * @param functionName the name of the called function

View File

@ -20,6 +20,7 @@
var ERR = require("async-stacktrace"); var ERR = require("async-stacktrace");
var exporthtml = require("../utils/ExportHtml"); var exporthtml = require("../utils/ExportHtml");
var exporttxt = require("../utils/ExportTxt");
var exportdokuwiki = require("../utils/ExportDokuWiki"); var exportdokuwiki = require("../utils/ExportDokuWiki");
var padManager = require("../db/PadManager"); var padManager = require("../db/PadManager");
var async = require("async"); var async = require("async");
@ -48,22 +49,75 @@ exports.doExport = function(req, res, padId, type)
res.attachment(padId + "." + type); res.attachment(padId + "." + type);
//if this is a plain text export, we can do this directly //if this is a plain text export, we can do this directly
// We have to over engineer this because tabs are stored as attributes and not plain text
if(type == "txt") if(type == "txt")
{ {
padManager.getPad(padId, function(err, pad) var txt;
{ var randNum;
ERR(err); var srcFile, destFile;
if(req.params.rev){
pad.getInternalRevisionAText(req.params.rev, function(junk, text) async.series([
{ //render the txt document
res.send(text.text ? text.text : null); function(callback)
});
}
else
{ {
res.send(pad.text()); exporttxt.getPadTXTDocument(padId, req.params.rev, false, function(err, _txt)
{
if(ERR(err, callback)) return;
txt = _txt;
callback();
});
},
//decide what to do with the txt export
function(callback)
{
//if this is a txt export, we can send this from here directly
res.send(txt);
callback("stop");
},
//send the convert job to abiword
function(callback)
{
//ensure html can be collected by the garbage collector
txt = null;
destFile = tempDirectory + "/eplite_export_" + randNum + "." + type;
abiword.convertFile(srcFile, destFile, type, callback);
},
//send the file
function(callback)
{
res.sendfile(destFile, null, callback);
},
//clean up temporary files
function(callback)
{
async.parallel([
function(callback)
{
fs.unlink(srcFile, callback);
},
function(callback)
{
//100ms delay to accomidate for slow windows fs
if(os.type().indexOf("Windows") > -1)
{
setTimeout(function()
{
fs.unlink(destFile, callback);
}, 100);
}
else
{
fs.unlink(destFile, callback);
}
}
], callback);
} }
}); ], function(err)
{
if(err && err != "stop") ERR(err);
})
} }
else if(type == 'dokuwiki') else if(type == 'dokuwiki')
{ {

View File

@ -1035,7 +1035,7 @@ function handleClientReady(client, message)
} }
// notify all existing users about new user // notify all existing users about new user
client.broadcast.to(padIds.padIds).json.send(messageToTheOtherUsers); client.broadcast.to(padIds.padId).json.send(messageToTheOtherUsers);
//Run trough all sessions of this pad //Run trough all sessions of this pad
async.forEach(socketio.sockets.clients(padIds.padId), function(roomClient, callback) async.forEach(socketio.sockets.clients(padIds.padId), function(roomClient, callback)
@ -1429,7 +1429,7 @@ function composePadChangesets(padId, startNum, endNum, callback)
*/ */
exports.padUsersCount = function (padID, callback) { exports.padUsersCount = function (padID, callback) {
callback(null, { callback(null, {
padUsersCount: socketio.sockets.clients(padId).length padUsersCount: socketio.sockets.clients(padID).length
}); });
} }

View File

@ -57,4 +57,9 @@ exports.expressCreateServer = function (hook_name, args, cb) {
res.end("OK"); res.end("OK");
}); });
}); });
//Provide a possibility to query the latest available API version
args.app.get('/api', function (req, res) {
res.json({"currentVersion" : apiHandler.latestApiVersion});
});
} }

View File

@ -0,0 +1,87 @@
/**
* Helpers for export requests
*/
/*
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var async = require("async");
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
var padManager = require("../db/PadManager");
var ERR = require("async-stacktrace");
var Security = require('ep_etherpad-lite/static/js/security');
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
exports.getPadPlainText = function(pad, revNum){
var atext = ((revNum !== undefined) ? pad.getInternalRevisionAText(revNum) : pad.atext());
var textLines = atext.text.slice(0, -1).split('\n');
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
var apool = pad.pool();
var pieces = [];
for (var i = 0; i < textLines.length; i++){
var line = _analyzeLine(textLines[i], attribLines[i], apool);
if (line.listLevel){
var numSpaces = line.listLevel * 2 - 1;
var bullet = '*';
pieces.push(new Array(numSpaces + 1).join(' '), bullet, ' ', line.text, '\n');
}
else{
pieces.push(line.text, '\n');
}
}
return pieces.join('');
}
exports._analyzeLine = function(text, aline, apool){
var line = {};
// identify list
var lineMarker = 0;
line.listLevel = 0;
if (aline){
var opIter = Changeset.opIterator(aline);
if (opIter.hasNext()){
var listType = Changeset.opAttributeValue(opIter.next(), 'list', apool);
if (listType){
lineMarker = 1;
listType = /([a-z]+)([12345678])/.exec(listType);
if (listType){
line.listTypeName = listType[1];
line.listLevel = Number(listType[2]);
}
}
}
}
if (lineMarker){
line.text = text.substring(1);
line.aline = Changeset.subattribution(aline, 1);
}
else{
line.text = text;
line.aline = aline;
}
return line;
}
exports._encodeWhitespace = function(s){
return s.replace(/[^\x21-\x7E\s\t\n\r]/g, function(c){
return "&#" +c.charCodeAt(0) + ";"
});
}

View File

@ -21,31 +21,9 @@ var padManager = require("../db/PadManager");
var ERR = require("async-stacktrace"); var ERR = require("async-stacktrace");
var Security = require('ep_etherpad-lite/static/js/security'); var Security = require('ep_etherpad-lite/static/js/security');
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks'); var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
function getPadPlainText(pad, revNum) var getPadPlainText = require('./ExportHelper').getPadPlainText
{ var _analyzeLine = require('./ExportHelper')._analyzeLine;
var atext = ((revNum !== undefined) ? pad.getInternalRevisionAText(revNum) : pad.atext()); var _encodeWhitespace = require('./ExportHelper')._encodeWhitespace;
var textLines = atext.text.slice(0, -1).split('\n');
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
var apool = pad.pool();
var pieces = [];
for (var i = 0; i < textLines.length; i++)
{
var line = _analyzeLine(textLines[i], attribLines[i], apool);
if (line.listLevel)
{
var numSpaces = line.listLevel * 2 - 1;
var bullet = '*';
pieces.push(new Array(numSpaces + 1).join(' '), bullet, ' ', line.text, '\n');
}
else
{
pieces.push(line.text, '\n');
}
}
return pieces.join('');
}
function getPadHTML(pad, revNum, callback) function getPadHTML(pad, revNum, callback)
{ {
@ -503,45 +481,6 @@ function getHTMLFromAtext(pad, atext, authorColors)
return pieces.join(''); return pieces.join('');
} }
function _analyzeLine(text, aline, apool)
{
var line = {};
// identify list
var lineMarker = 0;
line.listLevel = 0;
if (aline)
{
var opIter = Changeset.opIterator(aline);
if (opIter.hasNext())
{
var listType = Changeset.opAttributeValue(opIter.next(), 'list', apool);
if (listType)
{
lineMarker = 1;
listType = /([a-z]+)([12345678])/.exec(listType);
if (listType)
{
line.listTypeName = listType[1];
line.listLevel = Number(listType[2]);
}
}
}
}
if (lineMarker)
{
line.text = text.substring(1);
line.aline = Changeset.subattribution(aline, 1);
}
else
{
line.text = text;
line.aline = aline;
}
return line;
}
exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback) exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
{ {
padManager.getPad(padId, function (err, pad) padManager.getPad(padId, function (err, pad)
@ -578,79 +517,6 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
}); });
} }
function _encodeWhitespace(s) {
return s.replace(/[^\x21-\x7E\s\t\n\r]/g, function(c)
{
return "&#" +c.charCodeAt(0) + ";"
});
}
// copied from ACE
function _processSpaces(s)
{
var doesWrap = true;
if (s.indexOf("<") < 0 && !doesWrap)
{
// short-cut
return s.replace(/ /g, '&nbsp;');
}
var parts = [];
s.replace(/<[^>]*>?| |[^ <]+/g, function (m)
{
parts.push(m);
});
if (doesWrap)
{
var endOfLine = true;
var beforeSpace = false;
// last space in a run is normal, others are nbsp,
// end of line is nbsp
for (var i = parts.length - 1; i >= 0; i--)
{
var p = parts[i];
if (p == " ")
{
if (endOfLine || beforeSpace) parts[i] = '&nbsp;';
endOfLine = false;
beforeSpace = true;
}
else if (p.charAt(0) != "<")
{
endOfLine = false;
beforeSpace = false;
}
}
// beginning of line is nbsp
for (var i = 0; i < parts.length; i++)
{
var p = parts[i];
if (p == " ")
{
parts[i] = '&nbsp;';
break;
}
else if (p.charAt(0) != "<")
{
break;
}
}
}
else
{
for (var i = 0; i < parts.length; i++)
{
var p = parts[i];
if (p == " ")
{
parts[i] = '&nbsp;';
}
}
}
return parts.join('');
}
// copied from ACE // copied from ACE
var _REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/; var _REGEX_WORDCHAR = /[\u0030-\u0039\u0041-\u005A\u0061-\u007A\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u00FF\u0100-\u1FFF\u3040-\u9FFF\uF900-\uFDFF\uFE70-\uFEFE\uFF10-\uFF19\uFF21-\uFF3A\uFF41-\uFF5A\uFF66-\uFFDC]/;
@ -676,3 +542,57 @@ function _findURLs(text)
return urls; return urls;
} }
// copied from ACE
function _processSpaces(s){
var doesWrap = true;
if (s.indexOf("<") < 0 && !doesWrap){
// short-cut
return s.replace(/ /g, '&nbsp;');
}
var parts = [];
s.replace(/<[^>]*>?| |[^ <]+/g, function (m){
parts.push(m);
});
if (doesWrap){
var endOfLine = true;
var beforeSpace = false;
// last space in a run is normal, others are nbsp,
// end of line is nbsp
for (var i = parts.length - 1; i >= 0; i--){
var p = parts[i];
if (p == " "){
if (endOfLine || beforeSpace) parts[i] = '&nbsp;';
endOfLine = false;
beforeSpace = true;
}
else if (p.charAt(0) != "<"){
endOfLine = false;
beforeSpace = false;
}
}
// beginning of line is nbsp
for (var i = 0; i < parts.length; i++){
var p = parts[i];
if (p == " "){
parts[i] = '&nbsp;';
break;
}
else if (p.charAt(0) != "<"){
break;
}
}
}
else
{
for (var i = 0; i < parts.length; i++){
var p = parts[i];
if (p == " "){
parts[i] = '&nbsp;';
}
}
}
return parts.join('');
}

293
src/node/utils/ExportTxt.js Normal file
View File

@ -0,0 +1,293 @@
/**
* TXT export
*/
/*
* 2013 John McLear
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS-IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var async = require("async");
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
var padManager = require("../db/PadManager");
var ERR = require("async-stacktrace");
var Security = require('ep_etherpad-lite/static/js/security');
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
var getPadPlainText = require('./ExportHelper').getPadPlainText;
var _analyzeLine = require('./ExportHelper')._analyzeLine;
// This is slightly different than the HTML method as it passes the output to getTXTFromAText
function getPadTXT(pad, revNum, callback)
{
var atext = pad.atext;
var html;
async.waterfall([
// fetch revision atext
function (callback)
{
if (revNum != undefined)
{
pad.getInternalRevisionAText(revNum, function (err, revisionAtext)
{
if(ERR(err, callback)) return;
atext = revisionAtext;
callback();
});
}
else
{
callback(null);
}
},
// convert atext to html
function (callback)
{
html = getTXTFromAtext(pad, atext); // only this line is different to the HTML function
callback(null);
}],
// run final callback
function (err)
{
if(ERR(err, callback)) return;
callback(null, html);
});
}
exports.getPadTXT = getPadTXT;
// This is different than the functionality provided in ExportHtml as it provides formatting
// functionality that is designed specifically for TXT exports
function getTXTFromAtext(pad, atext, authorColors)
{
var apool = pad.apool();
var textLines = atext.text.slice(0, -1).split('\n');
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
var tags = ['h1', 'h2', 'strong', 'em', 'u', 's'];
var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough'];
var anumMap = {};
var css = "";
props.forEach(function (propName, i)
{
var propTrueNum = apool.putAttrib([propName, true], true);
if (propTrueNum >= 0)
{
anumMap[propTrueNum] = i;
}
});
function getLineTXT(text, attribs)
{
var propVals = [false, false, false];
var ENTER = 1;
var STAY = 2;
var LEAVE = 0;
// Use order of tags (b/i/u) as order of nesting, for simplicity
// and decent nesting. For example,
// <b>Just bold<b> <b><i>Bold and italics</i></b> <i>Just italics</i>
// becomes
// <b>Just bold <i>Bold and italics</i></b> <i>Just italics</i>
var taker = Changeset.stringIterator(text);
var assem = Changeset.stringAssembler();
var openTags = [];
var idx = 0;
function processNextChars(numChars)
{
if (numChars <= 0)
{
return;
}
var iter = Changeset.opIterator(Changeset.subattribution(attribs, idx, idx + numChars));
idx += numChars;
while (iter.hasNext())
{
var o = iter.next();
var propChanged = false;
Changeset.eachAttribNumber(o.attribs, function (a)
{
if (a in anumMap)
{
var i = anumMap[a]; // i = 0 => bold, etc.
if (!propVals[i])
{
propVals[i] = ENTER;
propChanged = true;
}
else
{
propVals[i] = STAY;
}
}
});
for (var i = 0; i < propVals.length; i++)
{
if (propVals[i] === true)
{
propVals[i] = LEAVE;
propChanged = true;
}
else if (propVals[i] === STAY)
{
propVals[i] = true; // set it back
}
}
// now each member of propVal is in {false,LEAVE,ENTER,true}
// according to what happens at start of span
if (propChanged)
{
// leaving bold (e.g.) also leaves italics, etc.
var left = false;
for (var i = 0; i < propVals.length; i++)
{
var v = propVals[i];
if (!left)
{
if (v === LEAVE)
{
left = true;
}
}
else
{
if (v === true)
{
propVals[i] = STAY; // tag will be closed and re-opened
}
}
}
var tags2close = [];
for (var i = propVals.length - 1; i >= 0; i--)
{
if (propVals[i] === LEAVE)
{
//emitCloseTag(i);
tags2close.push(i);
propVals[i] = false;
}
else if (propVals[i] === STAY)
{
//emitCloseTag(i);
tags2close.push(i);
}
}
for (var i = 0; i < propVals.length; i++)
{
if (propVals[i] === ENTER || propVals[i] === STAY)
{
propVals[i] = true;
}
}
// propVals is now all {true,false} again
} // end if (propChanged)
var chars = o.chars;
if (o.lines)
{
chars--; // exclude newline at end of line, if present
}
var s = taker.take(chars);
// removes the characters with the code 12. Don't know where they come
// from but they break the abiword parser and are completly useless
// s = s.replace(String.fromCharCode(12), "");
// remove * from s, it's just not needed on a blank line.. This stops
// plugins from being able to display * at the beginning of a line
// s = s.replace("*", ""); // Then remove it
assem.append(s);
} // end iteration over spans in line
var tags2close = [];
for (var i = propVals.length - 1; i >= 0; i--)
{
if (propVals[i])
{
tags2close.push(i);
propVals[i] = false;
}
}
} // end processNextChars
processNextChars(text.length - idx);
return(assem.toString());
} // end getLineHTML
var pieces = [css];
// Need to deal with constraints imposed on HTML lists; can
// only gain one level of nesting at once, can't change type
// mid-list, etc.
// People might use weird indenting, e.g. skip a level,
// so we want to do something reasonable there. We also
// want to deal gracefully with blank lines.
// => keeps track of the parents level of indentation
var lists = []; // e.g. [[1,'bullet'], [3,'bullet'], ...]
for (var i = 0; i < textLines.length; i++)
{
var line = _analyzeLine(textLines[i], attribLines[i], apool);
var lineContent = getLineTXT(line.text, line.aline);
if(line.listTypeName == "bullet"){
lineContent = "* " + lineContent; // add a bullet
}
if(line.listLevel > 0){
for (var j = line.listLevel - 1; j >= 0; j--){
pieces.push('\t');
}
if(line.listTypeName == "number"){
pieces.push(line.listLevel + ". ");
// This is bad because it doesn't truly reflect what the user
// sees because browsers do magic on nested <ol><li>s
}
pieces.push(lineContent, '\n');
}else{
pieces.push(lineContent, '\n');
}
}
return pieces.join('');
}
exports.getTXTFromAtext = getTXTFromAtext;
exports.getPadTXTDocument = function (padId, revNum, noDocType, callback)
{
padManager.getPad(padId, function (err, pad)
{
if(ERR(err, callback)) return;
getPadTXT(pad, revNum, function (err, html)
{
if(ERR(err, callback)) return;
callback(null, html);
});
});
}

View File

@ -16,7 +16,7 @@
"require-kernel" : "1.0.5", "require-kernel" : "1.0.5",
"resolve" : "0.2.x", "resolve" : "0.2.x",
"socket.io" : "0.9.x", "socket.io" : "0.9.x",
"ueberDB" : "0.1.91", "ueberDB" : "0.1.92",
"async" : "0.1.x", "async" : "0.1.x",
"express" : "3.x", "express" : "3.x",
"connect" : "2.4.x", "connect" : "2.4.x",

View File

@ -177,6 +177,10 @@ p {
#overlaysdiv { position: absolute; left: -1000px; top: -1000px; } #overlaysdiv { position: absolute; left: -1000px; top: -1000px; }
/* Stops super long lines without being spaces such as aaaaaaaaaaaaaa*100 breaking the editor
Commented out because it stops IE from being able to render the document, crazy IE bug is crazy. */
/*
.ace-line{ .ace-line{
overflow:hidden; /* Stops super long lines without being spaces such as aaaaaaaaaaaaaa*100 breaking the editor */ overflow:hidden;
} }
*/

View File

@ -1622,9 +1622,17 @@ function Ace2Inner(){
lines = ccData.lines; lines = ccData.lines;
var lineAttribs = ccData.lineAttribs; var lineAttribs = ccData.lineAttribs;
var linesWrapped = ccData.linesWrapped; var linesWrapped = ccData.linesWrapped;
var scrollToTheLeftNeeded = false;
if (linesWrapped > 0) if (linesWrapped > 0)
{ {
if(!browser.ie){
// chrome decides in it's infinite wisdom that its okay to put the browsers visisble window in the middle of the span
// an outcome of this is that the first chars of the string are no longer visible to the user.. Yay chrome..
// Move the browsers visible area to the left hand side of the span
// Firefox isn't quite so bad, but it's still pretty quirky.
var scrollToTheLeftNeeded = true;
}
// console.log("Editor warning: " + linesWrapped + " long line" + (linesWrapped == 1 ? " was" : "s were") + " hard-wrapped into " + ccData.numLinesAfter + " lines."); // console.log("Editor warning: " + linesWrapped + " long line" + (linesWrapped == 1 ? " was" : "s were") + " hard-wrapped into " + ccData.numLinesAfter + " lines.");
} }
@ -1692,6 +1700,10 @@ function Ace2Inner(){
//console.log("removed: "+id); //console.log("removed: "+id);
}); });
if(scrollToTheLeftNeeded){ // needed to stop chrome from breaking the ui when long strings without spaces are pasted
$("#innerdocbody").scrollLeft(0);
}
p.mark("findsel"); p.mark("findsel");
// if the nodes that define the selection weren't encountered during // if the nodes that define the selection weren't encountered during
// content collection, figure out where those nodes are now. // content collection, figure out where those nodes are now.
@ -1897,7 +1909,7 @@ function Ace2Inner(){
var prevLine = rep.lines.prev(thisLine); var prevLine = rep.lines.prev(thisLine);
var prevLineText = prevLine.text; var prevLineText = prevLine.text;
var theIndent = /^ *(?:)/.exec(prevLineText)[0]; var theIndent = /^ *(?:)/.exec(prevLineText)[0];
if (/[\[\(\{]\s*$/.exec(prevLineText)) theIndent += THE_TAB; if (/[\[\(\:\{]\s*$/.exec(prevLineText)) theIndent += THE_TAB;
var cs = Changeset.builder(rep.lines.totalWidth()).keep( var cs = Changeset.builder(rep.lines.totalWidth()).keep(
rep.lines.offsetOfIndex(lineNum), lineNum).insert( rep.lines.offsetOfIndex(lineNum), lineNum).insert(
theIndent, [ theIndent, [
@ -3287,7 +3299,7 @@ function Ace2Inner(){
listType = /([a-z]+)([12345678])/.exec(listType); listType = /([a-z]+)([12345678])/.exec(listType);
var type = listType[1]; var type = listType[1];
var level = Number(listType[2]); var level = Number(listType[2]);
//detect empty list item; exclude indentation //detect empty list item; exclude indentation
if(text === '*' && type !== "indent") if(text === '*' && type !== "indent")
{ {
@ -3317,8 +3329,10 @@ function Ace2Inner(){
function doIndentOutdent(isOut) function doIndentOutdent(isOut)
{ {
if (!(rep.selStart && rep.selEnd) || if (!((rep.selStart && rep.selEnd) ||
((rep.selStart[0] == rep.selEnd[0]) && (rep.selStart[1] == rep.selEnd[1]) && rep.selEnd[1] > 1)) ((rep.selStart[0] == rep.selEnd[0]) && (rep.selStart[1] == rep.selEnd[1]) && rep.selEnd[1] > 1)) &&
(isOut != true)
)
{ {
return false; return false;
} }
@ -3326,7 +3340,6 @@ function Ace2Inner(){
var firstLine, lastLine; var firstLine, lastLine;
firstLine = rep.selStart[0]; firstLine = rep.selStart[0];
lastLine = Math.max(firstLine, rep.selEnd[0] - ((rep.selEnd[1] === 0) ? 1 : 0)); lastLine = Math.max(firstLine, rep.selEnd[0] - ((rep.selEnd[1] === 0) ? 1 : 0));
var mods = []; var mods = [];
for (var n = firstLine; n <= lastLine; n++) for (var n = firstLine; n <= lastLine; n++)
{ {
@ -3731,10 +3744,11 @@ function Ace2Inner(){
}, 200); }, 200);
} }
/* Attempt to apply some sanity to cursor handling in Chrome after a copy / paste event /* 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 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 */ presses and holds the arrow key */
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 newVisibleLineRange = getVisibleLineRange(); // get the current visible range -- This works great. var newVisibleLineRange = getVisibleLineRange(); // get the current visible range -- This works great.
var lineHeight = textLineHeight(); // what Is the height of each line? var lineHeight = textLineHeight(); // what Is the height of each line?
var myselection = document.getSelection(); // get the current caret selection, can't use rep. here because that only gives us the start position not the current var myselection = document.getSelection(); // get the current caret selection, can't use rep. here because that only gives us the start position not the current
@ -3744,6 +3758,7 @@ function Ace2Inner(){
var lineNum = Math.round(caretOffsetTop / lineHeight) ; // Get the current Line Number IE 84 var lineNum = Math.round(caretOffsetTop / lineHeight) ; // Get the current Line Number IE 84
newVisibleLineRange[1] = newVisibleLineRange[1]-1; newVisibleLineRange[1] = newVisibleLineRange[1]-1;
var caretIsVisible = (lineNum > newVisibleLineRange[0] && lineNum < newVisibleLineRange[1]); // Is the cursor in the visible Range IE ie 84 > 14 and 84 < 90? var caretIsVisible = (lineNum > newVisibleLineRange[0] && lineNum < newVisibleLineRange[1]); // Is the cursor in the visible Range IE ie 84 > 14 and 84 < 90?
if(!caretIsVisible){ // is the cursor no longer visible to the user? if(!caretIsVisible){ // is the cursor no longer visible to the user?
// Oh boy the caret is out of the visible area, I need to scroll the browser window to lineNum. // Oh boy the caret is out of the visible area, I need to scroll the browser window to lineNum.
// Get the new Y by getting the line number and multiplying by the height of each line. // Get the new Y by getting the line number and multiplying by the height of each line.
@ -3754,7 +3769,9 @@ function Ace2Inner(){
} }
setScrollY(newY); // set the scroll height of the browser setScrollY(newY); // set the scroll height of the browser
} }
} }
} }
} }
@ -3862,7 +3879,6 @@ function Ace2Inner(){
selection.endPoint = getPointForLineAndChar(se); selection.endPoint = getPointForLineAndChar(se);
selection.focusAtStart = !! rep.selFocusAtStart; selection.focusAtStart = !! rep.selFocusAtStart;
setSelection(selection); setSelection(selection);
} }

View File

@ -1,8 +1,8 @@
(function(document) { (function(document) {
// Set language for l10n // Set language for l10n
var language = document.cookie.match(/language=((\w{2,3})(-w+)?)/); var language = document.cookie.match(/language=((\w{2,3})(-\w+)?)/);
if(language) language = language[1]; if(language) language = language[1];
html10n.bind('indexed', function() { html10n.bind('indexed', function() {
html10n.localize([language, navigator.language, navigator.userLanguage, 'en']) html10n.localize([language, navigator.language, navigator.userLanguage, 'en'])
}) })

View File

@ -156,10 +156,7 @@ var padeditbar = (function()
else if (cmd == 'insertorderedlist') ace.ace_doInsertOrderedList(); else if (cmd == 'insertorderedlist') ace.ace_doInsertOrderedList();
else if (cmd == 'indent') else if (cmd == 'indent')
{ {
if (!ace.ace_doIndentOutdent(false)) ace.ace_doIndentOutdent(false);
{
ace.ace_doInsertUnorderedList();
}
} }
else if (cmd == 'outdent') else if (cmd == 'outdent')
{ {

View File

@ -70,10 +70,12 @@ exports.flatten = function (lst) {
exports.callAll = function (hook_name, args) { exports.callAll = function (hook_name, args) {
if (!args) args = {}; if (!args) args = {};
if (exports.plugins.hooks[hook_name] === undefined) return []; if (exports.plugins){
return _.flatten(_.map(exports.plugins.hooks[hook_name], function (hook) { if (exports.plugins.hooks[hook_name] === undefined) return [];
return hookCallWrapper(hook, hook_name, args); return _.flatten(_.map(exports.plugins.hooks[hook_name], function (hook) {
}), true); return hookCallWrapper(hook, hook_name, args);
}), true);
}
} }
exports.aCallAll = function (hook_name, args, cb) { exports.aCallAll = function (hook_name, args, cb) {

View File

@ -40,8 +40,10 @@
<% e.end_block(); %> <% e.end_block(); %>
<link rel="localizations" type="application/l10n+json" href="../../locales.json" /> <link rel="localizations" type="application/l10n+json" href="../../locales.json" />
<% e.begin_block("timesliderScripts"); %>
<script type="text/javascript" src="../../static/js/html10n.js"></script> <script type="text/javascript" src="../../static/js/html10n.js"></script>
<script type="text/javascript" src="../../static/js/l10n.js"></script> <script type="text/javascript" src="../../static/js/l10n.js"></script>
<% e.end_block(); %>
</head> </head>
<% e.begin_block("timesliderBody"); %> <% e.begin_block("timesliderBody"); %>