resolve merge conflict
This commit is contained in:
commit
4a98ec3c23
25 changed files with 658 additions and 186 deletions
|
@ -3,7 +3,15 @@
|
|||
* NEW: Plugins can now provide their own frontend tests
|
||||
* NEW: Improved server-side logging
|
||||
* NEW: Admin dashboard mobile device support and new hooks for Admin dashboard
|
||||
* NEW: Get current API version from API
|
||||
* Fix: Text Export indentation now supports multiple indentations
|
||||
* Fix: Bugfix getChatHistory API method
|
||||
* Fix: Stop Chrome losing caret after paste is texted
|
||||
* Fix: Make colons on end of line create 4 spaces on indent
|
||||
* Fix: 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: Indentation and bullets on text export
|
||||
* Fix: Resolve various warnings on dependencies during install
|
||||
|
|
|
@ -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)
|
||||
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.
|
||||
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.)
|
||||
|
||||
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
|
||||
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!
|
||||
* [Flattr] (http://flattr.com/thing/71378/Etherpad-Foundation)
|
||||
* Paypal - Press the donate button on [etherpad.org](http://etherpad.org)
|
||||
* [Bitcoin] (https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a)
|
||||
|
||||
# License
|
||||
[Apache License v2](http://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
|
|
|
@ -35,7 +35,8 @@ async.series([
|
|||
function(callback) {
|
||||
settings = require('../src/node/utils/Settings');
|
||||
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
|
||||
function (callback)
|
||||
|
@ -45,7 +46,7 @@ async.series([
|
|||
//get the pad
|
||||
function (callback)
|
||||
{
|
||||
padManager = require('../node/db/PadManager');
|
||||
padManager = require('../src/node/db/PadManager');
|
||||
|
||||
padManager.getPad(padId, function(err, _pad)
|
||||
{
|
||||
|
@ -82,7 +83,10 @@ async.series([
|
|||
db.db.db.wrappedDB.get(dbkey, function(err, dbvalue)
|
||||
{
|
||||
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);
|
||||
});
|
||||
|
|
|
@ -61,7 +61,9 @@ Portal submits content into new blog post
|
|||
## Usage
|
||||
|
||||
### 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
|
||||
|
||||
|
|
56
src/locales/br.json
Normal file
56
src/locales/br.json
Normal 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"
|
||||
]
|
||||
}
|
||||
}
|
|
@ -19,7 +19,7 @@
|
|||
"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.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.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",
|
||||
|
@ -87,7 +87,7 @@
|
|||
"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.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.february": "2\u6708",
|
||||
"timeslider.month.march": "3\u6708",
|
||||
|
|
|
@ -19,13 +19,16 @@
|
|||
"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.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.embed.title": "Donn dat Padd enbenge",
|
||||
"pad.toolbar.showusers.title": "Verbonge Metschriiver aanzeije",
|
||||
"pad.colorpicker.save": "Fa\u00dfhallde",
|
||||
"pad.colorpicker.cancel": "Oph\u00fc\u00fcre",
|
||||
"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.myView": "Anseesch",
|
||||
"pad.settings.stickychat": "Donn der Klaaf emmer aanzeije",
|
||||
|
@ -38,6 +41,7 @@
|
|||
"pad.settings.language": "Schprooch:",
|
||||
"pad.importExport.import_export": "Empoot\/\u00c4xpoot",
|
||||
"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.exporthtml": "HTML",
|
||||
"pad.importExport.exportplain": "Eijfach T\u00e4x",
|
||||
|
@ -45,9 +49,11 @@
|
|||
"pad.importExport.exportpdf": "PDF (Poteerbaa Dokem\u00e4nte Fommaat)",
|
||||
"pad.importExport.exportopen": "ODF (Offe Dokem\u00e4nte-Fommaat)",
|
||||
"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.reconnecting": "Ben wider aam 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.advice": "En heh d\u00e4m Finster wider verbenge.",
|
||||
"pad.modals.unauth": "Nit ber\u00e4\u00e4schtesch",
|
||||
|
@ -72,10 +78,12 @@
|
|||
"pad.share.emebdcode": "URL enboue",
|
||||
"pad.chat": "Klaaf",
|
||||
"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.toolbar.returnbutton": "Jangk retuur nohm P\u00e4dd",
|
||||
"timeslider.toolbar.authors": "Schriiver:",
|
||||
"timeslider.toolbar.authorsList": "Kein Schriivere",
|
||||
"timeslider.toolbar.exportlink.title": "\u00c4xpoot",
|
||||
"timeslider.exportCurrent": "Donn de meu\u00dfte V\u00e4sjohn \u00e4xpotteere al\u00df:",
|
||||
"timeslider.version": "V\u00e4sjon {{version}}",
|
||||
"timeslider.saved": "Fa\u00dfjehallde aam {{day}}. {{month}} {{year}}",
|
||||
|
@ -92,11 +100,19 @@
|
|||
"timeslider.month.october": "Oktoober",
|
||||
"timeslider.month.november": "Nov\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.unnamed": "naamelo\u00df\u00df",
|
||||
"pad.userlist.guest": "Ja\u00df\u00df",
|
||||
"pad.userlist.deny": "Aflehne",
|
||||
"pad.userlist.approve": "Joodhei\u00dfe",
|
||||
"pad.editbar.clearcolors": "Sulle mer de F\u00e4rve f\u00f6r de Schriiver uss_em janze T\u00e4x fott maache?",
|
||||
"pad.impexp.importbutton": "J\u00e4z empoteere",
|
||||
"pad.impexp.importing": "Ben aam Empotteere …",
|
||||
"pad.impexp.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.importfailed": "Et Empoteere es don\u00e4vve jejange",
|
||||
"pad.impexp.copypaste": "Bes esu jood un donn et koppeere un enf\u00f6\u00f6je",
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
"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.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.embed.title": "Incorporar esta Nota",
|
||||
"pad.toolbar.showusers.title": "Mostrar os usuarios nesta Nota",
|
||||
|
@ -100,6 +100,8 @@
|
|||
"timeslider.month.october": "Outubro",
|
||||
"timeslider.month.november": "Novembro",
|
||||
"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.userlist.entername": "Insira o seu nome",
|
||||
"pad.userlist.unnamed": "Sem t\u00edtulo",
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
"pad.toolbar.redo.title": "\u91cd\u505a (Ctrl-Y)",
|
||||
"pad.toolbar.clearAuthorship.title": "\u6e05\u9664\u4f5c\u540d\u989c\u8272",
|
||||
"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.embed.title": "\u5d4c\u5165\u6b64\u8bb0\u4e8b\u672c",
|
||||
"pad.toolbar.showusers.title": "\u663e\u793a\u6b64\u8bb0\u4e8b\u672c\u7684\u7528\u6237",
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{
|
||||
"@metadata": {
|
||||
"authors": {
|
||||
"1": "Simon Shek"
|
||||
"0": "Shirayuki",
|
||||
"2": "Simon Shek"
|
||||
}
|
||||
},
|
||||
"index.newPad": "\u65b0Pad",
|
||||
|
@ -86,8 +87,8 @@
|
|||
"timeslider.toolbar.exportlink.title": "\u532f\u51fa",
|
||||
"timeslider.exportCurrent": "\u532f\u51fa\u7576\u524d\u7248\u672c\u70ba\uff1a",
|
||||
"timeslider.version": "\u7248\u672c{{version}}",
|
||||
"timeslider.saved": "{{year}}{{month}}{{day}}\u4fdd\u5b58",
|
||||
"timeslider.dateformat": "{{year}}{{month}}{{day}} {{hours}}:{{minutes}}:{{seconds}}",
|
||||
"timeslider.saved": "{{year}}\u5e74{{month}}{{day}}\u65e5\u4fdd\u5b58",
|
||||
"timeslider.dateformat": "{{year}}\u5e74{{month}}\u6708{{day}}\u65e5 {{hours}}:{{minutes}}:{{seconds}}",
|
||||
"timeslider.month.january": "1\u6708",
|
||||
"timeslider.month.february": "2\u6708",
|
||||
"timeslider.month.march": "3\u6708",
|
||||
|
|
|
@ -151,7 +151,6 @@ exports.getPad = function(id, text, callback)
|
|||
pad.init(text, function(err)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
globalPads.set(id, pad);
|
||||
callback(null, pad);
|
||||
});
|
||||
|
|
|
@ -216,6 +216,9 @@ var version =
|
|||
}
|
||||
};
|
||||
|
||||
// set the latest available API version here
|
||||
exports.latestApiVersion = '1.2.7';
|
||||
|
||||
/**
|
||||
* Handles a HTTP API call
|
||||
* @param functionName the name of the called function
|
||||
|
|
|
@ -20,6 +20,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 async = require("async");
|
||||
|
@ -48,22 +49,75 @@ exports.doExport = function(req, res, padId, type)
|
|||
res.attachment(padId + "." + 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")
|
||||
{
|
||||
padManager.getPad(padId, function(err, pad)
|
||||
var txt;
|
||||
var randNum;
|
||||
var srcFile, destFile;
|
||||
|
||||
async.series([
|
||||
//render the txt document
|
||||
function(callback)
|
||||
{
|
||||
ERR(err);
|
||||
if(req.params.rev){
|
||||
pad.getInternalRevisionAText(req.params.rev, function(junk, text)
|
||||
exporttxt.getPadTXTDocument(padId, req.params.rev, false, function(err, _txt)
|
||||
{
|
||||
res.send(text.text ? text.text : null);
|
||||
if(ERR(err, callback)) return;
|
||||
txt = _txt;
|
||||
callback();
|
||||
});
|
||||
},
|
||||
//decide what to do with the txt export
|
||||
function(callback)
|
||||
{
|
||||
//if this is a txt export, we can send this from here directly
|
||||
res.send(txt);
|
||||
callback("stop");
|
||||
},
|
||||
//send the convert job to abiword
|
||||
function(callback)
|
||||
{
|
||||
//ensure html can be collected by the garbage collector
|
||||
txt = null;
|
||||
|
||||
destFile = tempDirectory + "/eplite_export_" + randNum + "." + type;
|
||||
abiword.convertFile(srcFile, destFile, type, callback);
|
||||
},
|
||||
//send the file
|
||||
function(callback)
|
||||
{
|
||||
res.sendfile(destFile, null, callback);
|
||||
},
|
||||
//clean up temporary files
|
||||
function(callback)
|
||||
{
|
||||
async.parallel([
|
||||
function(callback)
|
||||
{
|
||||
fs.unlink(srcFile, callback);
|
||||
},
|
||||
function(callback)
|
||||
{
|
||||
//100ms delay to accomidate for slow windows fs
|
||||
if(os.type().indexOf("Windows") > -1)
|
||||
{
|
||||
setTimeout(function()
|
||||
{
|
||||
fs.unlink(destFile, callback);
|
||||
}, 100);
|
||||
}
|
||||
else
|
||||
{
|
||||
res.send(pad.text());
|
||||
fs.unlink(destFile, callback);
|
||||
}
|
||||
});
|
||||
}
|
||||
], callback);
|
||||
}
|
||||
], function(err)
|
||||
{
|
||||
if(err && err != "stop") ERR(err);
|
||||
})
|
||||
}
|
||||
else if(type == 'dokuwiki')
|
||||
{
|
||||
|
|
|
@ -1035,7 +1035,7 @@ function handleClientReady(client, message)
|
|||
}
|
||||
|
||||
// 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
|
||||
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) {
|
||||
callback(null, {
|
||||
padUsersCount: socketio.sockets.clients(padId).length
|
||||
padUsersCount: socketio.sockets.clients(padID).length
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -57,4 +57,9 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
|||
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});
|
||||
});
|
||||
}
|
||||
|
|
87
src/node/utils/ExportHelper.js
Normal file
87
src/node/utils/ExportHelper.js
Normal file
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* Helpers for export requests
|
||||
*/
|
||||
|
||||
/*
|
||||
* 2011 Peter 'Pita' Martischka (Primary Technology Ltd)
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var async = require("async");
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var padManager = require("../db/PadManager");
|
||||
var ERR = require("async-stacktrace");
|
||||
var Security = require('ep_etherpad-lite/static/js/security');
|
||||
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||
|
||||
exports.getPadPlainText = function(pad, revNum){
|
||||
var atext = ((revNum !== undefined) ? pad.getInternalRevisionAText(revNum) : pad.atext());
|
||||
var textLines = atext.text.slice(0, -1).split('\n');
|
||||
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
|
||||
var apool = pad.pool();
|
||||
|
||||
var pieces = [];
|
||||
for (var i = 0; i < textLines.length; i++){
|
||||
var line = _analyzeLine(textLines[i], attribLines[i], apool);
|
||||
if (line.listLevel){
|
||||
var numSpaces = line.listLevel * 2 - 1;
|
||||
var bullet = '*';
|
||||
pieces.push(new Array(numSpaces + 1).join(' '), bullet, ' ', line.text, '\n');
|
||||
}
|
||||
else{
|
||||
pieces.push(line.text, '\n');
|
||||
}
|
||||
}
|
||||
|
||||
return pieces.join('');
|
||||
}
|
||||
|
||||
|
||||
exports._analyzeLine = function(text, aline, apool){
|
||||
var line = {};
|
||||
|
||||
// identify list
|
||||
var lineMarker = 0;
|
||||
line.listLevel = 0;
|
||||
if (aline){
|
||||
var opIter = Changeset.opIterator(aline);
|
||||
if (opIter.hasNext()){
|
||||
var listType = Changeset.opAttributeValue(opIter.next(), 'list', apool);
|
||||
if (listType){
|
||||
lineMarker = 1;
|
||||
listType = /([a-z]+)([12345678])/.exec(listType);
|
||||
if (listType){
|
||||
line.listTypeName = listType[1];
|
||||
line.listLevel = Number(listType[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (lineMarker){
|
||||
line.text = text.substring(1);
|
||||
line.aline = Changeset.subattribution(aline, 1);
|
||||
}
|
||||
else{
|
||||
line.text = text;
|
||||
line.aline = aline;
|
||||
}
|
||||
return line;
|
||||
}
|
||||
|
||||
|
||||
exports._encodeWhitespace = function(s){
|
||||
return s.replace(/[^\x21-\x7E\s\t\n\r]/g, function(c){
|
||||
return "&#" +c.charCodeAt(0) + ";"
|
||||
});
|
||||
}
|
|
@ -21,31 +21,9 @@ var padManager = require("../db/PadManager");
|
|||
var ERR = require("async-stacktrace");
|
||||
var Security = require('ep_etherpad-lite/static/js/security');
|
||||
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||
function getPadPlainText(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('');
|
||||
}
|
||||
var getPadPlainText = require('./ExportHelper').getPadPlainText
|
||||
var _analyzeLine = require('./ExportHelper')._analyzeLine;
|
||||
var _encodeWhitespace = require('./ExportHelper')._encodeWhitespace;
|
||||
|
||||
function getPadHTML(pad, revNum, callback)
|
||||
{
|
||||
|
@ -503,45 +481,6 @@ function getHTMLFromAtext(pad, atext, authorColors)
|
|||
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)
|
||||
{
|
||||
padManager.getPad(padId, function (err, pad)
|
||||
|
@ -578,79 +517,6 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
|
|||
});
|
||||
}
|
||||
|
||||
function _encodeWhitespace(s) {
|
||||
return s.replace(/[^\x21-\x7E\s\t\n\r]/g, function(c)
|
||||
{
|
||||
return "&#" +c.charCodeAt(0) + ";"
|
||||
});
|
||||
}
|
||||
|
||||
// copied from ACE
|
||||
|
||||
|
||||
function _processSpaces(s)
|
||||
{
|
||||
var doesWrap = true;
|
||||
if (s.indexOf("<") < 0 && !doesWrap)
|
||||
{
|
||||
// short-cut
|
||||
return s.replace(/ /g, ' ');
|
||||
}
|
||||
var parts = [];
|
||||
s.replace(/<[^>]*>?| |[^ <]+/g, function (m)
|
||||
{
|
||||
parts.push(m);
|
||||
});
|
||||
if (doesWrap)
|
||||
{
|
||||
var endOfLine = true;
|
||||
var beforeSpace = false;
|
||||
// last space in a run is normal, others are nbsp,
|
||||
// end of line is nbsp
|
||||
for (var i = parts.length - 1; i >= 0; i--)
|
||||
{
|
||||
var p = parts[i];
|
||||
if (p == " ")
|
||||
{
|
||||
if (endOfLine || beforeSpace) parts[i] = ' ';
|
||||
endOfLine = false;
|
||||
beforeSpace = true;
|
||||
}
|
||||
else if (p.charAt(0) != "<")
|
||||
{
|
||||
endOfLine = false;
|
||||
beforeSpace = false;
|
||||
}
|
||||
}
|
||||
// beginning of line is nbsp
|
||||
for (var i = 0; i < parts.length; i++)
|
||||
{
|
||||
var p = parts[i];
|
||||
if (p == " ")
|
||||
{
|
||||
parts[i] = ' ';
|
||||
break;
|
||||
}
|
||||
else if (p.charAt(0) != "<")
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < parts.length; i++)
|
||||
{
|
||||
var p = parts[i];
|
||||
if (p == " ")
|
||||
{
|
||||
parts[i] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
return parts.join('');
|
||||
}
|
||||
|
||||
|
||||
// copied from ACE
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// copied from ACE
|
||||
function _processSpaces(s){
|
||||
var doesWrap = true;
|
||||
if (s.indexOf("<") < 0 && !doesWrap){
|
||||
// short-cut
|
||||
return s.replace(/ /g, ' ');
|
||||
}
|
||||
var parts = [];
|
||||
s.replace(/<[^>]*>?| |[^ <]+/g, function (m){
|
||||
parts.push(m);
|
||||
});
|
||||
if (doesWrap){
|
||||
var endOfLine = true;
|
||||
var beforeSpace = false;
|
||||
// last space in a run is normal, others are nbsp,
|
||||
// end of line is nbsp
|
||||
for (var i = parts.length - 1; i >= 0; i--){
|
||||
var p = parts[i];
|
||||
if (p == " "){
|
||||
if (endOfLine || beforeSpace) parts[i] = ' ';
|
||||
endOfLine = false;
|
||||
beforeSpace = true;
|
||||
}
|
||||
else if (p.charAt(0) != "<"){
|
||||
endOfLine = false;
|
||||
beforeSpace = false;
|
||||
}
|
||||
}
|
||||
// beginning of line is nbsp
|
||||
for (var i = 0; i < parts.length; i++){
|
||||
var p = parts[i];
|
||||
if (p == " "){
|
||||
parts[i] = ' ';
|
||||
break;
|
||||
}
|
||||
else if (p.charAt(0) != "<"){
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (var i = 0; i < parts.length; i++){
|
||||
var p = parts[i];
|
||||
if (p == " "){
|
||||
parts[i] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
return parts.join('');
|
||||
}
|
||||
|
||||
|
|
293
src/node/utils/ExportTxt.js
Normal file
293
src/node/utils/ExportTxt.js
Normal file
|
@ -0,0 +1,293 @@
|
|||
/**
|
||||
* TXT export
|
||||
*/
|
||||
|
||||
/*
|
||||
* 2013 John McLear
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
var async = require("async");
|
||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||
var padManager = require("../db/PadManager");
|
||||
var ERR = require("async-stacktrace");
|
||||
var Security = require('ep_etherpad-lite/static/js/security');
|
||||
var hooks = require('ep_etherpad-lite/static/js/pluginfw/hooks');
|
||||
var getPadPlainText = require('./ExportHelper').getPadPlainText;
|
||||
var _analyzeLine = require('./ExportHelper')._analyzeLine;
|
||||
|
||||
// This is slightly different than the HTML method as it passes the output to getTXTFromAText
|
||||
function getPadTXT(pad, revNum, callback)
|
||||
{
|
||||
var atext = pad.atext;
|
||||
var html;
|
||||
async.waterfall([
|
||||
// fetch revision atext
|
||||
|
||||
|
||||
function (callback)
|
||||
{
|
||||
if (revNum != undefined)
|
||||
{
|
||||
pad.getInternalRevisionAText(revNum, function (err, revisionAtext)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
atext = revisionAtext;
|
||||
callback();
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
callback(null);
|
||||
}
|
||||
},
|
||||
|
||||
// convert atext to html
|
||||
|
||||
|
||||
function (callback)
|
||||
{
|
||||
html = getTXTFromAtext(pad, atext); // only this line is different to the HTML function
|
||||
callback(null);
|
||||
}],
|
||||
// run final callback
|
||||
|
||||
|
||||
function (err)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, html);
|
||||
});
|
||||
}
|
||||
|
||||
exports.getPadTXT = getPadTXT;
|
||||
|
||||
|
||||
// This is different than the functionality provided in ExportHtml as it provides formatting
|
||||
// functionality that is designed specifically for TXT exports
|
||||
function getTXTFromAtext(pad, atext, authorColors)
|
||||
{
|
||||
var apool = pad.apool();
|
||||
var textLines = atext.text.slice(0, -1).split('\n');
|
||||
var attribLines = Changeset.splitAttributionLines(atext.attribs, atext.text);
|
||||
|
||||
var tags = ['h1', 'h2', 'strong', 'em', 'u', 's'];
|
||||
var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough'];
|
||||
var anumMap = {};
|
||||
var css = "";
|
||||
|
||||
props.forEach(function (propName, i)
|
||||
{
|
||||
var propTrueNum = apool.putAttrib([propName, true], true);
|
||||
if (propTrueNum >= 0)
|
||||
{
|
||||
anumMap[propTrueNum] = i;
|
||||
}
|
||||
});
|
||||
|
||||
function getLineTXT(text, attribs)
|
||||
{
|
||||
var propVals = [false, false, false];
|
||||
var ENTER = 1;
|
||||
var STAY = 2;
|
||||
var LEAVE = 0;
|
||||
|
||||
// Use order of tags (b/i/u) as order of nesting, for simplicity
|
||||
// and decent nesting. For example,
|
||||
// <b>Just bold<b> <b><i>Bold and italics</i></b> <i>Just italics</i>
|
||||
// becomes
|
||||
// <b>Just bold <i>Bold and italics</i></b> <i>Just italics</i>
|
||||
var taker = Changeset.stringIterator(text);
|
||||
var assem = Changeset.stringAssembler();
|
||||
var openTags = [];
|
||||
|
||||
var idx = 0;
|
||||
|
||||
function processNextChars(numChars)
|
||||
{
|
||||
if (numChars <= 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var iter = Changeset.opIterator(Changeset.subattribution(attribs, idx, idx + numChars));
|
||||
idx += numChars;
|
||||
|
||||
while (iter.hasNext())
|
||||
{
|
||||
var o = iter.next();
|
||||
var propChanged = false;
|
||||
Changeset.eachAttribNumber(o.attribs, function (a)
|
||||
{
|
||||
if (a in anumMap)
|
||||
{
|
||||
var i = anumMap[a]; // i = 0 => bold, etc.
|
||||
if (!propVals[i])
|
||||
{
|
||||
propVals[i] = ENTER;
|
||||
propChanged = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
propVals[i] = STAY;
|
||||
}
|
||||
}
|
||||
});
|
||||
for (var i = 0; i < propVals.length; i++)
|
||||
{
|
||||
if (propVals[i] === true)
|
||||
{
|
||||
propVals[i] = LEAVE;
|
||||
propChanged = true;
|
||||
}
|
||||
else if (propVals[i] === STAY)
|
||||
{
|
||||
propVals[i] = true; // set it back
|
||||
}
|
||||
}
|
||||
// now each member of propVal is in {false,LEAVE,ENTER,true}
|
||||
// according to what happens at start of span
|
||||
if (propChanged)
|
||||
{
|
||||
// leaving bold (e.g.) also leaves italics, etc.
|
||||
var left = false;
|
||||
for (var i = 0; i < propVals.length; i++)
|
||||
{
|
||||
var v = propVals[i];
|
||||
if (!left)
|
||||
{
|
||||
if (v === LEAVE)
|
||||
{
|
||||
left = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (v === true)
|
||||
{
|
||||
propVals[i] = STAY; // tag will be closed and re-opened
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var tags2close = [];
|
||||
|
||||
for (var i = propVals.length - 1; i >= 0; i--)
|
||||
{
|
||||
if (propVals[i] === LEAVE)
|
||||
{
|
||||
//emitCloseTag(i);
|
||||
tags2close.push(i);
|
||||
propVals[i] = false;
|
||||
}
|
||||
else if (propVals[i] === STAY)
|
||||
{
|
||||
//emitCloseTag(i);
|
||||
tags2close.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i = 0; i < propVals.length; i++)
|
||||
{
|
||||
if (propVals[i] === ENTER || propVals[i] === STAY)
|
||||
{
|
||||
propVals[i] = true;
|
||||
}
|
||||
}
|
||||
// propVals is now all {true,false} again
|
||||
} // end if (propChanged)
|
||||
|
||||
var chars = o.chars;
|
||||
if (o.lines)
|
||||
{
|
||||
chars--; // exclude newline at end of line, if present
|
||||
}
|
||||
|
||||
var s = taker.take(chars);
|
||||
|
||||
// removes the characters with the code 12. Don't know where they come
|
||||
// from but they break the abiword parser and are completly useless
|
||||
// s = s.replace(String.fromCharCode(12), "");
|
||||
|
||||
// remove * from s, it's just not needed on a blank line.. This stops
|
||||
// plugins from being able to display * at the beginning of a line
|
||||
// s = s.replace("*", ""); // Then remove it
|
||||
|
||||
assem.append(s);
|
||||
} // end iteration over spans in line
|
||||
|
||||
var tags2close = [];
|
||||
for (var i = propVals.length - 1; i >= 0; i--)
|
||||
{
|
||||
if (propVals[i])
|
||||
{
|
||||
tags2close.push(i);
|
||||
propVals[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
} // end processNextChars
|
||||
processNextChars(text.length - idx);
|
||||
return(assem.toString());
|
||||
} // end getLineHTML
|
||||
var pieces = [css];
|
||||
|
||||
// Need to deal with constraints imposed on HTML lists; can
|
||||
// only gain one level of nesting at once, can't change type
|
||||
// mid-list, etc.
|
||||
// People might use weird indenting, e.g. skip a level,
|
||||
// so we want to do something reasonable there. We also
|
||||
// want to deal gracefully with blank lines.
|
||||
// => keeps track of the parents level of indentation
|
||||
var lists = []; // e.g. [[1,'bullet'], [3,'bullet'], ...]
|
||||
for (var i = 0; i < textLines.length; i++)
|
||||
{
|
||||
var line = _analyzeLine(textLines[i], attribLines[i], apool);
|
||||
var lineContent = getLineTXT(line.text, line.aline);
|
||||
if(line.listTypeName == "bullet"){
|
||||
lineContent = "* " + lineContent; // add a bullet
|
||||
}
|
||||
if(line.listLevel > 0){
|
||||
for (var j = line.listLevel - 1; j >= 0; j--){
|
||||
pieces.push('\t');
|
||||
}
|
||||
if(line.listTypeName == "number"){
|
||||
pieces.push(line.listLevel + ". ");
|
||||
// This is bad because it doesn't truly reflect what the user
|
||||
// sees because browsers do magic on nested <ol><li>s
|
||||
}
|
||||
pieces.push(lineContent, '\n');
|
||||
}else{
|
||||
pieces.push(lineContent, '\n');
|
||||
}
|
||||
}
|
||||
|
||||
return pieces.join('');
|
||||
}
|
||||
exports.getTXTFromAtext = getTXTFromAtext;
|
||||
|
||||
exports.getPadTXTDocument = function (padId, revNum, noDocType, callback)
|
||||
{
|
||||
padManager.getPad(padId, function (err, pad)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
|
||||
getPadTXT(pad, revNum, function (err, html)
|
||||
{
|
||||
if(ERR(err, callback)) return;
|
||||
callback(null, html);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
@ -16,7 +16,7 @@
|
|||
"require-kernel" : "1.0.5",
|
||||
"resolve" : "0.2.x",
|
||||
"socket.io" : "0.9.x",
|
||||
"ueberDB" : "0.1.91",
|
||||
"ueberDB" : "0.1.92",
|
||||
"async" : "0.1.x",
|
||||
"express" : "3.x",
|
||||
"connect" : "2.4.x",
|
||||
|
|
|
@ -177,6 +177,10 @@ p {
|
|||
|
||||
#overlaysdiv { position: absolute; left: -1000px; top: -1000px; }
|
||||
|
||||
/* Stops super long lines without being spaces such as aaaaaaaaaaaaaa*100 breaking the editor
|
||||
Commented out because it stops IE from being able to render the document, crazy IE bug is crazy. */
|
||||
/*
|
||||
.ace-line{
|
||||
overflow:hidden; /* Stops super long lines without being spaces such as aaaaaaaaaaaaaa*100 breaking the editor */
|
||||
overflow:hidden;
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -1622,9 +1622,17 @@ function Ace2Inner(){
|
|||
lines = ccData.lines;
|
||||
var lineAttribs = ccData.lineAttribs;
|
||||
var linesWrapped = ccData.linesWrapped;
|
||||
var scrollToTheLeftNeeded = false;
|
||||
|
||||
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.");
|
||||
}
|
||||
|
||||
|
@ -1692,6 +1700,10 @@ function Ace2Inner(){
|
|||
//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");
|
||||
// if the nodes that define the selection weren't encountered during
|
||||
// content collection, figure out where those nodes are now.
|
||||
|
@ -1897,7 +1909,7 @@ function Ace2Inner(){
|
|||
var prevLine = rep.lines.prev(thisLine);
|
||||
var prevLineText = prevLine.text;
|
||||
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(
|
||||
rep.lines.offsetOfIndex(lineNum), lineNum).insert(
|
||||
theIndent, [
|
||||
|
@ -3317,8 +3329,10 @@ function Ace2Inner(){
|
|||
|
||||
function doIndentOutdent(isOut)
|
||||
{
|
||||
if (!(rep.selStart && rep.selEnd) ||
|
||||
((rep.selStart[0] == rep.selEnd[0]) && (rep.selStart[1] == rep.selEnd[1]) && rep.selEnd[1] > 1))
|
||||
if (!((rep.selStart && rep.selEnd) ||
|
||||
((rep.selStart[0] == rep.selEnd[0]) && (rep.selStart[1] == rep.selEnd[1]) && rep.selEnd[1] > 1)) &&
|
||||
(isOut != true)
|
||||
)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -3326,7 +3340,6 @@ function Ace2Inner(){
|
|||
var firstLine, lastLine;
|
||||
firstLine = rep.selStart[0];
|
||||
lastLine = Math.max(firstLine, rep.selEnd[0] - ((rep.selEnd[1] === 0) ? 1 : 0));
|
||||
|
||||
var mods = [];
|
||||
for (var n = firstLine; n <= lastLine; n++)
|
||||
{
|
||||
|
@ -3735,6 +3748,7 @@ function Ace2Inner(){
|
|||
We have to do this the way we do because rep. doesn't hold the value for keyheld events IE if the user
|
||||
presses and holds the arrow key */
|
||||
if((evt.which == 37 || evt.which == 38 || evt.which == 39 || evt.which == 40) && $.browser.chrome){
|
||||
|
||||
var newVisibleLineRange = getVisibleLineRange(); // get the current visible range -- This works great.
|
||||
var lineHeight = textLineHeight(); // what Is the height of each line?
|
||||
var myselection = document.getSelection(); // get the current caret selection, can't use rep. here because that only gives us the start position not the current
|
||||
|
@ -3744,6 +3758,7 @@ function Ace2Inner(){
|
|||
var lineNum = Math.round(caretOffsetTop / lineHeight) ; // Get the current Line Number IE 84
|
||||
newVisibleLineRange[1] = newVisibleLineRange[1]-1;
|
||||
var caretIsVisible = (lineNum > newVisibleLineRange[0] && lineNum < newVisibleLineRange[1]); // Is the cursor in the visible Range IE ie 84 > 14 and 84 < 90?
|
||||
|
||||
if(!caretIsVisible){ // is the cursor no longer visible to the user?
|
||||
// Oh boy the caret is out of the visible area, I need to scroll the browser window to lineNum.
|
||||
// Get the new Y by getting the line number and multiplying by the height of each line.
|
||||
|
@ -3754,7 +3769,9 @@ function Ace2Inner(){
|
|||
}
|
||||
setScrollY(newY); // set the scroll height of the browser
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3862,7 +3879,6 @@ function Ace2Inner(){
|
|||
selection.endPoint = getPointForLineAndChar(se);
|
||||
|
||||
selection.focusAtStart = !! rep.selFocusAtStart;
|
||||
|
||||
setSelection(selection);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
(function(document) {
|
||||
// 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];
|
||||
|
||||
html10n.bind('indexed', function() {
|
||||
|
|
|
@ -156,10 +156,7 @@ var padeditbar = (function()
|
|||
else if (cmd == 'insertorderedlist') ace.ace_doInsertOrderedList();
|
||||
else if (cmd == 'indent')
|
||||
{
|
||||
if (!ace.ace_doIndentOutdent(false))
|
||||
{
|
||||
ace.ace_doInsertUnorderedList();
|
||||
}
|
||||
ace.ace_doIndentOutdent(false);
|
||||
}
|
||||
else if (cmd == 'outdent')
|
||||
{
|
||||
|
|
|
@ -70,11 +70,13 @@ exports.flatten = function (lst) {
|
|||
|
||||
exports.callAll = function (hook_name, args) {
|
||||
if (!args) args = {};
|
||||
if (exports.plugins){
|
||||
if (exports.plugins.hooks[hook_name] === undefined) return [];
|
||||
return _.flatten(_.map(exports.plugins.hooks[hook_name], function (hook) {
|
||||
return hookCallWrapper(hook, hook_name, args);
|
||||
}), true);
|
||||
}
|
||||
}
|
||||
|
||||
exports.aCallAll = function (hook_name, args, cb) {
|
||||
if (!args) args = {};
|
||||
|
|
|
@ -40,8 +40,10 @@
|
|||
<% e.end_block(); %>
|
||||
|
||||
<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/l10n.js"></script>
|
||||
<% e.end_block(); %>
|
||||
</head>
|
||||
|
||||
<% e.begin_block("timesliderBody"); %>
|
||||
|
|
Loading…
Reference in a new issue