mirror of
https://github.com/ether/etherpad-lite.git
synced 2025-02-01 03:12:42 +01:00
Merge pull request #1 from ether/develop
Update to most recent etherpad-lite version
This commit is contained in:
commit
f2836125dc
32 changed files with 574 additions and 171 deletions
|
@ -4,7 +4,7 @@
|
||||||
# About
|
# About
|
||||||
Etherpad is a really-real time collaborative editor maintained by the Etherpad Community.
|
Etherpad is a really-real time collaborative editor maintained by the Etherpad Community.
|
||||||
|
|
||||||
Etherpad is written in JavaScript(99.9%) on both the server and client so it's easy for developers to maintain and add new features. Because of this Etherpad has tons of customizations that you can leverage.
|
Etherpad is written in JavaScript (99.9%) on both the server and client so it's easy for developers to maintain and add new features. Because of this Etherpad has tons of customizations that you can leverage.
|
||||||
|
|
||||||
Etherpad is designed to be easily embeddable and provides a [HTTP API](https://github.com/ether/etherpad-lite/wiki/HTTP-API)
|
Etherpad 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.
|
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.
|
||||||
|
|
|
@ -46,13 +46,14 @@ fi
|
||||||
#check node version
|
#check node version
|
||||||
NODE_VERSION=$(node --version)
|
NODE_VERSION=$(node --version)
|
||||||
NODE_V_MINOR=$(echo $NODE_VERSION | cut -d "." -f 1-2)
|
NODE_V_MINOR=$(echo $NODE_VERSION | cut -d "." -f 1-2)
|
||||||
|
NODE_V_MAIN=$(echo $NODE_VERSION | cut -d "." -f 1)
|
||||||
#iojs version checking added
|
#iojs version checking added
|
||||||
if hash iojs 2>/dev/null; then
|
if hash iojs 2>/dev/null; then
|
||||||
IOJS_VERSION=$(iojs --version)
|
IOJS_VERSION=$(iojs --version)
|
||||||
fi
|
fi
|
||||||
if [ ! $NODE_V_MINOR = "v0.10" ] && [ ! $NODE_V_MINOR = "v0.11" ] && [ ! $NODE_V_MINOR = "v0.12" ]; then
|
if [ ! $NODE_V_MINOR = "v0.10" ] && [ ! $NODE_V_MINOR = "v0.11" ] && [ ! $NODE_V_MINOR = "v0.12" ] && [ ! $NODE_V_MAIN = "v4" ] && [ ! $NODE_V_MAIN = "v5" ]; then
|
||||||
if [ ! $IOJS_VERSION ]; then
|
if [ ! $IOJS_VERSION ]; then
|
||||||
echo "You're running a wrong version of node, or io.js is not installed. You're using $NODE_VERSION, we need v0.10.x, v0.11.x or v0.12.x" >&2
|
echo "You're running a wrong version of node, or io.js is not installed. You're using $NODE_VERSION, we need node v0.10.x or higher" >&2
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
|
@ -6,11 +6,6 @@ cd /D "%~dp0\.."
|
||||||
:: Is node installed?
|
:: Is node installed?
|
||||||
cmd /C node -e "" || ( echo "Please install node.js ( http://nodejs.org )" && exit /B 1 )
|
cmd /C node -e "" || ( echo "Please install node.js ( http://nodejs.org )" && exit /B 1 )
|
||||||
|
|
||||||
echo _
|
|
||||||
echo Checking node version...
|
|
||||||
set check_version="if(['10','11','12'].indexOf(process.version.split('.')[1]) === -1 && process.version.split('.')[0] !== '1') { console.log('You are running a wrong version of Node. Etherpad requires v0.10+'); process.exit(1) }"
|
|
||||||
cmd /C node -e %check_version% || exit /B 1
|
|
||||||
|
|
||||||
echo _
|
echo _
|
||||||
echo Ensure that all dependencies are up to date... If this is the first time you have run Etherpad please be patient.
|
echo Ensure that all dependencies are up to date... If this is the first time you have run Etherpad please be patient.
|
||||||
cmd /C npm install src/ --loglevel warn || exit /B 1
|
cmd /C npm install src/ --loglevel warn || exit /B 1
|
||||||
|
|
|
@ -79,6 +79,9 @@ async.series([
|
||||||
newPad.pool.numToAttrib = oldPad.pool.numToAttrib;
|
newPad.pool.numToAttrib = oldPad.pool.numToAttrib;
|
||||||
for(var curRevNum = 0; curRevNum <= newRevHead; curRevNum++) {
|
for(var curRevNum = 0; curRevNum <= newRevHead; curRevNum++) {
|
||||||
db.db.get("pad:" + padId + ":revs:" + curRevNum, function(err, rev) {
|
db.db.get("pad:" + padId + ":revs:" + curRevNum, function(err, rev) {
|
||||||
|
if (rev.meta) {
|
||||||
|
throw "The specified revision number could not be found.";
|
||||||
|
}
|
||||||
var newRevNum = ++newPad.head;
|
var newRevNum = ++newPad.head;
|
||||||
var newRevId = "pad:" + newPad.id + ":revs:" + newRevNum;
|
var newRevId = "pad:" + newPad.id + ":revs:" + newRevNum;
|
||||||
db.db.set(newRevId, rev);
|
db.db.set(newRevId, rev);
|
||||||
|
|
|
@ -339,3 +339,14 @@ Things in context:
|
||||||
|
|
||||||
This hook is provided to allow author highlight style to be modified.
|
This hook is provided to allow author highlight style to be modified.
|
||||||
Registered hooks should return 1 if the plugin handles highlighting. If no plugin returns 1, the core will use the default background-based highlighting.
|
Registered hooks should return 1 if the plugin handles highlighting. If no plugin returns 1, the core will use the default background-based highlighting.
|
||||||
|
|
||||||
|
## aceSelectionChanged
|
||||||
|
Called from: src/static/js/ace2_inner.js
|
||||||
|
|
||||||
|
Things in context:
|
||||||
|
|
||||||
|
1. rep - information about where the user's cursor is
|
||||||
|
2. documentAttributeManager - information about attributes in the document
|
||||||
|
|
||||||
|
This hook allows a plugin to react to a cursor or selection change,
|
||||||
|
perhaps to update a UI element based on the style at the cursor location.
|
||||||
|
|
|
@ -357,7 +357,7 @@ Things in context:
|
||||||
|
|
||||||
1. Pad object
|
1. Pad object
|
||||||
|
|
||||||
This hook will allow a plug-in developer to include more properties and attributes to support during HTML Export. An Array should be returned.
|
This hook will allow a plug-in developer to include more properties and attributes to support during HTML Export. If tags are stored as `['color', 'red']` on the attribute pool, use `exportHtmlAdditionalTagsWithData` instead. An Array should be returned.
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
```
|
```
|
||||||
|
@ -368,6 +368,24 @@ exports.exportHtmlAdditionalTags = function(hook, pad, cb){
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## exportHtmlAdditionalTagsWithData
|
||||||
|
Called from src/node/utils/ExportHtml.js
|
||||||
|
|
||||||
|
Things in context:
|
||||||
|
|
||||||
|
1. Pad object
|
||||||
|
|
||||||
|
Identical to `exportHtmlAdditionalTags`, but for tags that are stored with an specific value (not simply `true`) on the attribute pool. For example `['color', 'red']`, instead of `['bold', true]`. This hook will allow a plug-in developer to include more properties and attributes to support during HTML Export. An Array of arrays should be returned. The exported HTML will contain tags like `<span data-color="red">` for the content where attributes are `['color', 'red']`.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
```
|
||||||
|
// Add the props to be supported in export
|
||||||
|
exports.exportHtmlAdditionalTagsWithData = function(hook, pad, cb){
|
||||||
|
var padId = pad.id;
|
||||||
|
cb([["color", "red"], ["color", "blue"]]);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## userLeave
|
## userLeave
|
||||||
Called from src/node/handler/PadMessageHandler.js
|
Called from src/node/handler/PadMessageHandler.js
|
||||||
|
|
||||||
|
@ -384,3 +402,20 @@ exports.userLeave = function(hook, session, callback) {
|
||||||
console.log('%s left pad %s', session.author, session.padId);
|
console.log('%s left pad %s', session.author, session.padId);
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### clientReady
|
||||||
|
Called from src/node/handler/PadMessageHandler.js
|
||||||
|
|
||||||
|
This in context:
|
||||||
|
|
||||||
|
1. message
|
||||||
|
|
||||||
|
This hook gets called when handling a CLIENT_READY which is the first message from the client to the server.
|
||||||
|
|
||||||
|
Example:
|
||||||
|
|
||||||
|
```
|
||||||
|
exports.clientReady = function(hook, message) {
|
||||||
|
console.log('Client has entered the pad' + message.padId);
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
|
@ -86,10 +86,14 @@
|
||||||
may cause problems during deployment. Set to 0 to disable caching */
|
may cause problems during deployment. Set to 0 to disable caching */
|
||||||
"maxAge" : 21600, // 60 * 60 * 6 = 6 hours
|
"maxAge" : 21600, // 60 * 60 * 6 = 6 hours
|
||||||
|
|
||||||
/* This is the path to the Abiword executable. Setting it to null, disables abiword.
|
/* This is the absolute path to the Abiword executable. Setting it to null, disables abiword.
|
||||||
Abiword is needed to advanced import/export features of pads*/
|
Abiword is needed to advanced import/export features of pads*/
|
||||||
"abiword" : null,
|
"abiword" : null,
|
||||||
|
|
||||||
|
/* This is the absolute path to the soffice executable. Setting it to null, disables LibreOffice exporting.
|
||||||
|
LibreOffice can be used in lieu of Abiword to export pads */
|
||||||
|
"soffice" : null,
|
||||||
|
|
||||||
/* This is the path to the Tidy executable. Setting it to null, disables Tidy.
|
/* This is the path to the Tidy executable. Setting it to null, disables Tidy.
|
||||||
Tidy is used to improve the quality of exported pads*/
|
Tidy is used to improve the quality of exported pads*/
|
||||||
"tidyHtml" : null,
|
"tidyHtml" : null,
|
||||||
|
@ -131,6 +135,11 @@
|
||||||
// Allow Load Testing tools to hit the Etherpad Instance. Warning this will disable security on the instance.
|
// Allow Load Testing tools to hit the Etherpad Instance. Warning this will disable security on the instance.
|
||||||
"loadTest": false,
|
"loadTest": false,
|
||||||
|
|
||||||
|
// Disable indentation on new line when previous line ends with some special chars (':', '[', '(', '{')
|
||||||
|
/*
|
||||||
|
"indentationOnNewLine": false,
|
||||||
|
*/
|
||||||
|
|
||||||
/* The toolbar buttons configuration.
|
/* The toolbar buttons configuration.
|
||||||
"toolbar": {
|
"toolbar": {
|
||||||
"left": [
|
"left": [
|
||||||
|
|
|
@ -6,7 +6,8 @@
|
||||||
"Alami",
|
"Alami",
|
||||||
"Meno25",
|
"Meno25",
|
||||||
"Test Create account",
|
"Test Create account",
|
||||||
"محمد أحمد عبد الفتاح"
|
"محمد أحمد عبد الفتاح",
|
||||||
|
"Haytham morsy"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"index.newPad": "باد جديد",
|
"index.newPad": "باد جديد",
|
||||||
|
@ -97,6 +98,9 @@
|
||||||
"timeslider.exportCurrent": "تصدير النسخة الحالية ك:",
|
"timeslider.exportCurrent": "تصدير النسخة الحالية ك:",
|
||||||
"timeslider.version": "إصدار {{version}}",
|
"timeslider.version": "إصدار {{version}}",
|
||||||
"timeslider.saved": "محفوظ {{month}} {{day}}, {{year}}",
|
"timeslider.saved": "محفوظ {{month}} {{day}}, {{year}}",
|
||||||
|
"timeslider.playPause": "تشغيل / إيقاف مؤقت محتويات الباد",
|
||||||
|
"timeslider.backRevision": "عد إلى مراجعة في هذه الباد",
|
||||||
|
"timeslider.forwardRevision": "انطلق إلى مراجعة في هذه الباد",
|
||||||
"timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
"timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
||||||
"timeslider.month.january": "يناير",
|
"timeslider.month.january": "يناير",
|
||||||
"timeslider.month.february": "فبراير",
|
"timeslider.month.february": "فبراير",
|
||||||
|
|
|
@ -132,7 +132,7 @@
|
||||||
"pad.impexp.confirmimport": "Al importar un archivo se borrará el contenido actual del pad. ¿Estás seguro de que quieres continuar?",
|
"pad.impexp.confirmimport": "Al importar un archivo se borrará el contenido actual del pad. ¿Estás seguro de que quieres continuar?",
|
||||||
"pad.impexp.convertFailed": "No pudimos importar este archivo. Inténtalo con un formato diferente o copia y pega manualmente.",
|
"pad.impexp.convertFailed": "No pudimos importar este archivo. Inténtalo con un formato diferente o copia y pega manualmente.",
|
||||||
"pad.impexp.padHasData": "No hemos podido importar este archivo porque este pad ya ha tenido cambios. Importa a un nuevo pad.",
|
"pad.impexp.padHasData": "No hemos podido importar este archivo porque este pad ya ha tenido cambios. Importa a un nuevo pad.",
|
||||||
"pad.impexp.uploadFailed": "El envío falló. Intentalo de nuevo.",
|
"pad.impexp.uploadFailed": "El envío falló. Inténtalo de nuevo.",
|
||||||
"pad.impexp.importfailed": "Fallo al importar",
|
"pad.impexp.importfailed": "Fallo al importar",
|
||||||
"pad.impexp.copypaste": "Intenta copiar y pegar",
|
"pad.impexp.copypaste": "Intenta copiar y pegar",
|
||||||
"pad.impexp.exportdisabled": "La exportación al formato {{type}} está desactivada. Contacta a tu administrador de sistemas."
|
"pad.impexp.exportdisabled": "La exportación al formato {{type}} está desactivada. Contacta a tu administrador de sistemas."
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
"@metadata": {
|
"@metadata": {
|
||||||
"authors": [
|
"authors": [
|
||||||
"Denö",
|
"Denö",
|
||||||
"Mashoi7"
|
"Mashoi7",
|
||||||
|
"Ilja.mos"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"pad.toolbar.underline.title": "Alleviivua (Ctrl+U)",
|
"pad.toolbar.underline.title": "Alleviivua (Ctrl+U)",
|
||||||
|
@ -36,7 +37,7 @@
|
||||||
"timeslider.month.january": "pakkaskuudu",
|
"timeslider.month.january": "pakkaskuudu",
|
||||||
"timeslider.month.february": "tuhukuudu",
|
"timeslider.month.february": "tuhukuudu",
|
||||||
"timeslider.month.march": "kevätkuudu",
|
"timeslider.month.march": "kevätkuudu",
|
||||||
"timeslider.month.april": "kevätkuudu",
|
"timeslider.month.april": "sulakuudu",
|
||||||
"timeslider.month.may": "oraskuudu",
|
"timeslider.month.may": "oraskuudu",
|
||||||
"timeslider.month.june": "kezäkuudu",
|
"timeslider.month.june": "kezäkuudu",
|
||||||
"timeslider.month.july": "heinykuudu",
|
"timeslider.month.july": "heinykuudu",
|
||||||
|
|
|
@ -2,7 +2,8 @@
|
||||||
"@metadata": {
|
"@metadata": {
|
||||||
"authors": [
|
"authors": [
|
||||||
"Aalam",
|
"Aalam",
|
||||||
"Babanwalia"
|
"Babanwalia",
|
||||||
|
"ਪ੍ਰਚਾਰਕ"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"index.newPad": "ਨਵਾਂ ਪੈਡ",
|
"index.newPad": "ਨਵਾਂ ਪੈਡ",
|
||||||
|
@ -10,29 +11,31 @@
|
||||||
"pad.toolbar.bold.title": "ਗੂੜ੍ਹਾ (Ctrl-B)",
|
"pad.toolbar.bold.title": "ਗੂੜ੍ਹਾ (Ctrl-B)",
|
||||||
"pad.toolbar.italic.title": "ਤਿਰਛਾ (Ctrl-I)",
|
"pad.toolbar.italic.title": "ਤਿਰਛਾ (Ctrl-I)",
|
||||||
"pad.toolbar.underline.title": "ਹੇਠਾਂ-ਰੇਖਾ (Ctrl-U)",
|
"pad.toolbar.underline.title": "ਹੇਠਾਂ-ਰੇਖਾ (Ctrl-U)",
|
||||||
"pad.toolbar.strikethrough.title": "ਵਿੰਨ੍ਹੋ ਵਿਨੋ",
|
"pad.toolbar.strikethrough.title": "ਵਿੰਨ੍ਹੋ (Ctrl+5)",
|
||||||
"pad.toolbar.ol.title": "ਲੜੀਵਾਰ ਲਿਸਟ",
|
"pad.toolbar.ol.title": "ਲੜੀਵਾਰ ਸੂਚੀ",
|
||||||
"pad.toolbar.ul.title": "ਬਿਨ-ਲੜੀਬੱਧ ਸੂਚੀ",
|
"pad.toolbar.ul.title": "ਬਿਨ-ਲੜੀਬੱਧ ਸੂਚੀ",
|
||||||
"pad.toolbar.indent.title": "ਹਾਸ਼ੀਏ ਤੋਂ ਪਰ੍ਹੇ (ਟੈਬ)",
|
"pad.toolbar.indent.title": "ਹਾਸ਼ੀਏ ਤੋਂ ਪਰ੍ਹੇ (ਟੈਬ)",
|
||||||
"pad.toolbar.unindent.title": "ਹਾਸ਼ੀਏ ਵੱਲ (ਸ਼ਿਫ਼ਟ+ਟੈਬ)",
|
"pad.toolbar.unindent.title": "ਹਾਸ਼ੀਏ ਵੱਲ (ਸ਼ਿਫ਼ਟ+ਟੈਬ)",
|
||||||
"pad.toolbar.undo.title": "ਵਾਪਸ (Ctrl-Z)",
|
"pad.toolbar.undo.title": "ਵਾਪਸ (Ctrl-Z)",
|
||||||
"pad.toolbar.redo.title": "ਪਰਤਾਓ (Ctrl-Y)",
|
"pad.toolbar.redo.title": "ਪਰਤਾਓ (Ctrl-Y)",
|
||||||
"pad.toolbar.clearAuthorship.title": "ਪਰਮਾਣਕਿਤਾ ਰੰਗ ਸਾਫ਼ ਕਰੋ",
|
"pad.toolbar.clearAuthorship.title": "ਪਰਮਾਣਕਿਤਾ ਰੰਗ ਸਾਫ਼ ਕਰੋ (Ctrl+Shift+C)",
|
||||||
"pad.toolbar.import_export.title": "ਵੱਖ-ਵੱਖ ਫਾਇਲ ਫਾਰਮੈਟ ਤੋਂ/ਵਿੱਚ ਇੰਪੋਰਟ/ਐਕਸਪੋਰਟ ਕਰੋ",
|
"pad.toolbar.import_export.title": "ਵੱਖ-ਵੱਖ ਫਾਇਲ ਫਾਰਮੈਟ ਤੋਂ/ਵਿੱਚ ਇੰਪੋਰਟ/ਐਕਸਪੋਰਟ ਕਰੋ",
|
||||||
"pad.toolbar.timeslider.title": "ਸਮਾਂ-ਲਕੀਰ",
|
"pad.toolbar.timeslider.title": "ਸਮਾਂ-ਲਕੀਰ",
|
||||||
"pad.toolbar.savedRevision.title": "ਰੀਵਿਜ਼ਨ ਸੰਭਾਲੋ",
|
"pad.toolbar.savedRevision.title": "ਰੀਵਿਜ਼ਨ ਸੰਭਾਲੋ",
|
||||||
"pad.toolbar.settings.title": "ਸੈਟਿੰਗ",
|
"pad.toolbar.settings.title": "ਸੈਟਿੰਗ",
|
||||||
"pad.toolbar.embed.title": "ਇਹ ਪੈਡ ਸਾਂਝਾ ਤੇ ਇੰਬੈੱਡ ਕਰੋ",
|
"pad.toolbar.embed.title": "ਇਹ ਪੈਡ ਸਾਂਝਾ ਤੇ ਇੰਬੈੱਡ ਕਰੋ",
|
||||||
"pad.toolbar.showusers.title": "ਇਹ ਪੈਡ ਉੱਤੇ ਯੂਜ਼ਰ ਵੇਖਾਓ",
|
"pad.toolbar.showusers.title": "ਇਹ ਪੈਡ ਉੱਤੇ ਯੂਜ਼ਰ ਵੇਖਾਓ",
|
||||||
"pad.colorpicker.save": "ਸਾਂਭੋ",
|
"pad.colorpicker.save": "ਸੰਭਾਲੋ",
|
||||||
"pad.colorpicker.cancel": "ਰੱਦ ਕਰੋ",
|
"pad.colorpicker.cancel": "ਰੱਦ ਕਰੋ",
|
||||||
"pad.loading": "…ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ",
|
"pad.loading": "…ਲੋਡ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ",
|
||||||
|
"pad.noCookie": "ਕੂਕੀਜ਼ ਨਹੀਂ ਲੱਭੀਅਾਂ। ਕਿਰਪਾ ਕਰਕੇ ਬ੍ਰਾੳੂਜ਼ਰ ਵਿੱਚ ਕੂਕੀਜ਼ ਲਾਗੂ ਕਰੋ।",
|
||||||
"pad.passwordRequired": "ਇਹ ਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਤੁਹਾਨੂੰ ਪਾਸਵਰਡ ਚਾਹੀਦਾ ਹੈ",
|
"pad.passwordRequired": "ਇਹ ਪੈਡ ਦੀ ਵਰਤੋਂ ਕਰਨ ਲਈ ਤੁਹਾਨੂੰ ਪਾਸਵਰਡ ਚਾਹੀਦਾ ਹੈ",
|
||||||
"pad.permissionDenied": "ਇਹ ਪੈਡ ਵਰਤਨ ਲਈ ਤੁਹਾਨੂੰ ਅਧਿਕਾਰ ਨਹੀਂ ਹਨ",
|
"pad.permissionDenied": "ਇਹ ਪੈਡ ਵਰਤਨ ਲਈ ਤੁਹਾਨੂੰ ਅਧਿਕਾਰ ਨਹੀਂ ਹਨ",
|
||||||
"pad.wrongPassword": "ਤੁਹਾਡਾ ਪਾਸਵਰਡ ਗਲਤੀ ਸੀ",
|
"pad.wrongPassword": "ਤੁਹਾਡਾ ਪਾਸਵਰਡ ਗਲਤੀ ਸੀ",
|
||||||
"pad.settings.padSettings": "ਪੈਡ ਸੈਟਿੰਗ",
|
"pad.settings.padSettings": "ਪੈਡ ਸੈਟਿੰਗ",
|
||||||
"pad.settings.myView": "ਮੇਰੀ ਝਲਕ",
|
"pad.settings.myView": "ਮੇਰੀ ਝਲਕ",
|
||||||
"pad.settings.stickychat": "ਹਮੇਸ਼ਾ ਸਕਰੀਨ ਉੱਤੇ ਗੱਲ ਕਰੋ",
|
"pad.settings.stickychat": "ਹਮੇਸ਼ਾ ਸਕਰੀਨ ਉੱਤੇ ਗੱਲ ਕਰੋ",
|
||||||
|
"pad.settings.chatandusers": "ਗੱਲ-ਬਾਤ ਅਤੇ ਵਰਤੋਂਕਾਰ ਦਿਖਾਵੋ",
|
||||||
"pad.settings.colorcheck": "ਲੇਖਕੀ ਰੰਗ",
|
"pad.settings.colorcheck": "ਲੇਖਕੀ ਰੰਗ",
|
||||||
"pad.settings.linenocheck": "ਲਾਈਨ ਨੰਬਰ",
|
"pad.settings.linenocheck": "ਲਾਈਨ ਨੰਬਰ",
|
||||||
"pad.settings.rtlcheck": "ਸਮੱਗਰੀ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਪੜ੍ਹਨੀ ਹੈ?",
|
"pad.settings.rtlcheck": "ਸਮੱਗਰੀ ਸੱਜੇ ਤੋਂ ਖੱਬੇ ਪੜ੍ਹਨੀ ਹੈ?",
|
||||||
|
@ -45,10 +48,11 @@
|
||||||
"pad.importExport.import": "ਕੋਈ ਵੀ ਟੈਕਸਟ ਫਾਇਲ ਜਾਂ ਦਸਤਾਵੇਜ਼ ਅੱਪਲੋਡ ਕਰੋ",
|
"pad.importExport.import": "ਕੋਈ ਵੀ ਟੈਕਸਟ ਫਾਇਲ ਜਾਂ ਦਸਤਾਵੇਜ਼ ਅੱਪਲੋਡ ਕਰੋ",
|
||||||
"pad.importExport.importSuccessful": "ਸਫ਼ਲ!",
|
"pad.importExport.importSuccessful": "ਸਫ਼ਲ!",
|
||||||
"pad.importExport.export": "ਮੌਜੂਦਾ ਪੈਡ ਨੂੰ ਐਕਸਪੋਰਟ ਕਰੋ:",
|
"pad.importExport.export": "ਮੌਜੂਦਾ ਪੈਡ ਨੂੰ ਐਕਸਪੋਰਟ ਕਰੋ:",
|
||||||
|
"pad.importExport.exportetherpad": "ੲੈਥਰਪੈਡ",
|
||||||
"pad.importExport.exporthtml": "HTML",
|
"pad.importExport.exporthtml": "HTML",
|
||||||
"pad.importExport.exportplain": "ਸਧਾਰਨ ਟੈਕਸਟ",
|
"pad.importExport.exportplain": "ਸਧਾਰਨ ਟੈਕਸਟ",
|
||||||
"pad.importExport.exportword": "ਮਾਈਕਰੋਸਾਫਟ ਵਰਡ",
|
"pad.importExport.exportword": "ਮਾਈਕਰੋਸਾਫਟ ਵਰਡ",
|
||||||
"pad.importExport.exportpdf": "ਪੀਡੀਐਫ",
|
"pad.importExport.exportpdf": "PDF",
|
||||||
"pad.importExport.exportopen": "ODF (ਓਪਨ ਡੌਕੂਮੈਂਟ ਫਾਰਮੈਟ)",
|
"pad.importExport.exportopen": "ODF (ਓਪਨ ਡੌਕੂਮੈਂਟ ਫਾਰਮੈਟ)",
|
||||||
"pad.importExport.abiword.innerHTML": "ਤੁਸੀਂ ਸਿਰਫ਼ ਸਾਦੀਆਂ ਲਿਖਤੀ ਜਾਂ ਐੱਚ.ਟੀ.ਐੱਮ.ਐੱਲ. ਰੂਪ-ਰੇਖਾਵਾਂ ਤੋਂ ਦਰਾਮਦ ਕਰ ਸਕਦੇ ਹੋ। ਹੋਰ ਉੱਨਤ ਦਰਾਮਦੀ ਗੁਣਾਂ ਵਾਸਤੇ ਮਿਹਰਬਾਨੀ ਕਰਕੇ <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\">ਐਬੀਵਰਡ ਥਾਪੋ</a>।",
|
"pad.importExport.abiword.innerHTML": "ਤੁਸੀਂ ਸਿਰਫ਼ ਸਾਦੀਆਂ ਲਿਖਤੀ ਜਾਂ ਐੱਚ.ਟੀ.ਐੱਮ.ਐੱਲ. ਰੂਪ-ਰੇਖਾਵਾਂ ਤੋਂ ਦਰਾਮਦ ਕਰ ਸਕਦੇ ਹੋ। ਹੋਰ ਉੱਨਤ ਦਰਾਮਦੀ ਗੁਣਾਂ ਵਾਸਤੇ ਮਿਹਰਬਾਨੀ ਕਰਕੇ <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\">ਐਬੀਵਰਡ ਥਾਪੋ</a>।",
|
||||||
"pad.modals.connected": "ਕੁਨੈਕਟ ਹੈ।",
|
"pad.modals.connected": "ਕੁਨੈਕਟ ਹੈ।",
|
||||||
|
@ -88,8 +92,11 @@
|
||||||
"timeslider.toolbar.authorsList": "ਕੋਈ ਲੇਖਕ ਨਹੀਂ",
|
"timeslider.toolbar.authorsList": "ਕੋਈ ਲੇਖਕ ਨਹੀਂ",
|
||||||
"timeslider.toolbar.exportlink.title": "ਐਕਸਪੋਰਟ",
|
"timeslider.toolbar.exportlink.title": "ਐਕਸਪੋਰਟ",
|
||||||
"timeslider.exportCurrent": "ਮੌਜੂਦਾ ਵਰਜਨ ਇੰਝ ਐਕਸਪੋਰਟ ਕਰੋ:",
|
"timeslider.exportCurrent": "ਮੌਜੂਦਾ ਵਰਜਨ ਇੰਝ ਐਕਸਪੋਰਟ ਕਰੋ:",
|
||||||
"timeslider.version": "ਵਰਜਨ {{version}}",
|
"timeslider.version": "ਵਰਜ਼ਨ {{version}}",
|
||||||
"timeslider.saved": "{{day}} {{month}} {{year}} ਨੂੰ ਸੰਭਾਲਿਆ",
|
"timeslider.saved": "{{day}} {{month}} {{year}} ਨੂੰ ਸੰਭਾਲਿਆ",
|
||||||
|
"timeslider.playPause": "ਪੈਡ ਸਮੱਗਰੀ ਚਲਾਓ / ਵਿਰਾਮ ਕਰੋ",
|
||||||
|
"timeslider.backRevision": "ਇਸ ਪੈਡ ਵਿੱਚ ਪਿਛਲੇ ਰੀਵਿਜ਼ਨ ਤੇ ਜਾਓ",
|
||||||
|
"timeslider.forwardRevision": "ਇਸ ਪੈਡ ਵਿੱਚ ਅਗਲੇ ਰੀਵਿਜ਼ਨ ਤੇ ਜਾਓ",
|
||||||
"timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
"timeslider.dateformat": "{{day}}/{{month}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
||||||
"timeslider.month.january": "ਜਨਵਰੀ",
|
"timeslider.month.january": "ਜਨਵਰੀ",
|
||||||
"timeslider.month.february": "ਫ਼ਰਵਰੀ",
|
"timeslider.month.february": "ਫ਼ਰਵਰੀ",
|
||||||
|
@ -118,5 +125,5 @@
|
||||||
"pad.impexp.uploadFailed": "ਅੱਪਲੋਡ ਲਈ ਫੇਲ੍ਹ ਹੈ, ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ ਜੀ।",
|
"pad.impexp.uploadFailed": "ਅੱਪਲੋਡ ਲਈ ਫੇਲ੍ਹ ਹੈ, ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ ਜੀ।",
|
||||||
"pad.impexp.importfailed": "ਇੰਪੋਰਟ ਫੇਲ੍ਹ ਹੈ",
|
"pad.impexp.importfailed": "ਇੰਪੋਰਟ ਫੇਲ੍ਹ ਹੈ",
|
||||||
"pad.impexp.copypaste": "ਕਾਪੀ ਕਰੋ ਚੇਪੋ ਜੀ",
|
"pad.impexp.copypaste": "ਕਾਪੀ ਕਰੋ ਚੇਪੋ ਜੀ",
|
||||||
"pad.impexp.exportdisabled": "{{type}} ਰੂਪ-ਰੇਖਾ ਵਜੋਂ ਬਰਾਮਦ ਕਰਨਾ ਬੰਦ ਹੈ। ਵੇਰਵੇ ਵਾਸਤੇ ਮਿਹਰਬਾਨੀ ਕਰਕੇ ਆਪਣੇ ਸਿਸਟਮ ਦੇ ਪ੍ਰਬੰਧਕ ਨਾਲ਼ ਰਾਬਤਾ ਬਣਾਉ।"
|
"pad.impexp.exportdisabled": "{{type}} ਫਾਰਮੈਟ ਵਜੋਂ ਬਰਾਮਦ ਕਰਨਾ ਬੰਦ ਹੈ। ਵੇਰਵੇ ਵਾਸਤੇ ਆਪਣੇ ਸਿਸਟਮ ਦੇ ਪਰਬੰਧਕ ਨਾਲ ਸੰਪਰਕ ਕਰੋ।"
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,8 @@
|
||||||
"Hedwig",
|
"Hedwig",
|
||||||
"ImGelu",
|
"ImGelu",
|
||||||
"Minisarm",
|
"Minisarm",
|
||||||
"Strainu"
|
"Strainu",
|
||||||
|
"Wintereu"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"index.newPad": "Pad nou",
|
"index.newPad": "Pad nou",
|
||||||
|
@ -21,6 +22,7 @@
|
||||||
"pad.toolbar.import_export.title": "Importă/Exportă din/în diferite formate",
|
"pad.toolbar.import_export.title": "Importă/Exportă din/în diferite formate",
|
||||||
"pad.toolbar.savedRevision.title": "Salvează revizia",
|
"pad.toolbar.savedRevision.title": "Salvează revizia",
|
||||||
"pad.toolbar.settings.title": "Setări",
|
"pad.toolbar.settings.title": "Setări",
|
||||||
|
"pad.toolbar.showusers.title": "Arată utilizatorii de pe acest pad",
|
||||||
"pad.colorpicker.save": "Salvează",
|
"pad.colorpicker.save": "Salvează",
|
||||||
"pad.colorpicker.cancel": "Anulează",
|
"pad.colorpicker.cancel": "Anulează",
|
||||||
"pad.loading": "Se încarcă...",
|
"pad.loading": "Se încarcă...",
|
||||||
|
@ -46,10 +48,10 @@
|
||||||
"pad.importExport.exportpdf": "PDF",
|
"pad.importExport.exportpdf": "PDF",
|
||||||
"pad.importExport.exportopen": "ODF (Open Document Format)",
|
"pad.importExport.exportopen": "ODF (Open Document Format)",
|
||||||
"pad.modals.connected": "Conectat.",
|
"pad.modals.connected": "Conectat.",
|
||||||
"pad.modals.reconnecting": "Se reconectează la pad-ul tău..",
|
"pad.modals.reconnecting": "Se reconectează la pad-ul dumneavoastră..",
|
||||||
"pad.modals.forcereconnect": "Forțează reconectarea",
|
"pad.modals.forcereconnect": "Forțează reconectarea",
|
||||||
"pad.modals.userdup": "Deschis în altă fereastră",
|
"pad.modals.userdup": "Deschis în altă fereastră",
|
||||||
"pad.modals.userdup.advice": "Reconectează pentru a folosi această fereastră în schimb",
|
"pad.modals.userdup.advice": "Reconectați-vă dacă doriți să utilizați această fereastră.",
|
||||||
"pad.modals.unauth": "Nu ești autorizat",
|
"pad.modals.unauth": "Nu ești autorizat",
|
||||||
"pad.modals.initsocketfail": "Serverul nu este disponibil.",
|
"pad.modals.initsocketfail": "Serverul nu este disponibil.",
|
||||||
"pad.modals.initsocketfail.explanation": "Nu s-a putut conecta la serverul de sincronizare.",
|
"pad.modals.initsocketfail.explanation": "Nu s-a putut conecta la serverul de sincronizare.",
|
||||||
|
@ -61,12 +63,12 @@
|
||||||
"pad.share": "Distribuie acest pad",
|
"pad.share": "Distribuie acest pad",
|
||||||
"pad.share.readonly": "Doar în citire",
|
"pad.share.readonly": "Doar în citire",
|
||||||
"pad.share.link": "Legătură",
|
"pad.share.link": "Legătură",
|
||||||
"pad.share.emebdcode": "Încorporează URL-ul",
|
"pad.share.emebdcode": "Adresa URL încorporată",
|
||||||
"pad.chat": "Chat",
|
"pad.chat": "Chat",
|
||||||
"pad.chat.title": "Deschide chat-ul pentru acest pad.",
|
"pad.chat.title": "Deschide chat-ul pentru acest pad.",
|
||||||
"pad.chat.loadmessages": "Încarcă mai multe mesaje",
|
"pad.chat.loadmessages": "Încarcă mai multe mesaje",
|
||||||
"timeslider.toolbar.returnbutton": "Înapoi la pad",
|
"timeslider.toolbar.returnbutton": "Înapoi la pad",
|
||||||
"timeslider.toolbar.authors": "Aurori:",
|
"timeslider.toolbar.authors": "Autori:",
|
||||||
"timeslider.toolbar.authorsList": "Niciun autor",
|
"timeslider.toolbar.authorsList": "Niciun autor",
|
||||||
"timeslider.toolbar.exportlink.title": "Exportă",
|
"timeslider.toolbar.exportlink.title": "Exportă",
|
||||||
"timeslider.exportCurrent": "Exportă versiunea curentă ca:",
|
"timeslider.exportCurrent": "Exportă versiunea curentă ca:",
|
||||||
|
@ -85,7 +87,7 @@
|
||||||
"timeslider.month.october": "octombrie",
|
"timeslider.month.october": "octombrie",
|
||||||
"timeslider.month.november": "noiembrie",
|
"timeslider.month.november": "noiembrie",
|
||||||
"timeslider.month.december": "decembrie",
|
"timeslider.month.december": "decembrie",
|
||||||
"pad.userlist.entername": "Introdu numele tău",
|
"pad.userlist.entername": "Introduceți numele dumneavoastră",
|
||||||
"pad.userlist.unnamed": "fără nume",
|
"pad.userlist.unnamed": "fără nume",
|
||||||
"pad.userlist.guest": "Oaspete",
|
"pad.userlist.guest": "Oaspete",
|
||||||
"pad.userlist.deny": "Respinge",
|
"pad.userlist.deny": "Respinge",
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
"Kosovastar"
|
"Kosovastar"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"index.newPad": "Bllok i Ri",
|
"index.newPad": "Bllok i ri",
|
||||||
"index.createOpenPad": "ose krijoni/hapni një Bllok me emrin:",
|
"index.createOpenPad": "ose krijoni/hapni një Bllok me emrin:",
|
||||||
"pad.toolbar.bold.title": "Të trasha (Ctrl-B)",
|
"pad.toolbar.bold.title": "Të trasha (Ctrl-B)",
|
||||||
"pad.toolbar.italic.title": "Të pjerrëta (Ctrl-I)",
|
"pad.toolbar.italic.title": "Të pjerrëta (Ctrl-I)",
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
"pad.toolbar.strikethrough.title": "Hequrvije (Ctrl+5)",
|
"pad.toolbar.strikethrough.title": "Hequrvije (Ctrl+5)",
|
||||||
"pad.toolbar.ol.title": "Listë e renditur (Ctrl+Shift+N)",
|
"pad.toolbar.ol.title": "Listë e renditur (Ctrl+Shift+N)",
|
||||||
"pad.toolbar.ul.title": "Listë e parenditur (Ctrl+Shift+L)",
|
"pad.toolbar.ul.title": "Listë e parenditur (Ctrl+Shift+L)",
|
||||||
"pad.toolbar.indent.title": "Brendazi (TAB)",
|
"pad.toolbar.indent.title": "E dhëmbëzuar (TAB)",
|
||||||
"pad.toolbar.unindent.title": "Jashtazi (Shift+TAB)",
|
"pad.toolbar.unindent.title": "Jashtazi (Shift+TAB)",
|
||||||
"pad.toolbar.undo.title": "Zhbëje (Ctrl-Z)",
|
"pad.toolbar.undo.title": "Zhbëje (Ctrl-Z)",
|
||||||
"pad.toolbar.redo.title": "Ribëje (Ctrl-Y)",
|
"pad.toolbar.redo.title": "Ribëje (Ctrl-Y)",
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
"pad.toolbar.import_export.title": "Importoni/Eksportoni nga/në formate të tjera kartelash",
|
"pad.toolbar.import_export.title": "Importoni/Eksportoni nga/në formate të tjera kartelash",
|
||||||
"pad.toolbar.timeslider.title": "Rrjedha kohore",
|
"pad.toolbar.timeslider.title": "Rrjedha kohore",
|
||||||
"pad.toolbar.savedRevision.title": "Ruaje Rishikimin",
|
"pad.toolbar.savedRevision.title": "Ruaje Rishikimin",
|
||||||
"pad.toolbar.settings.title": "Rregullime",
|
"pad.toolbar.settings.title": "Parametrat",
|
||||||
"pad.toolbar.embed.title": "Ndajeni me të tjerët dhe Trupëzojeni këtë bllok",
|
"pad.toolbar.embed.title": "Ndajeni me të tjerët dhe Trupëzojeni këtë bllok",
|
||||||
"pad.toolbar.showusers.title": "Shfaq përdoruesit në këtë bllok",
|
"pad.toolbar.showusers.title": "Shfaq përdoruesit në këtë bllok",
|
||||||
"pad.colorpicker.save": "Ruaje",
|
"pad.colorpicker.save": "Ruaje",
|
||||||
|
@ -45,6 +45,7 @@
|
||||||
"pad.importExport.import": "Ngarkoni cilëndo kartelë teksti ose dokument",
|
"pad.importExport.import": "Ngarkoni cilëndo kartelë teksti ose dokument",
|
||||||
"pad.importExport.importSuccessful": "Me sukses!",
|
"pad.importExport.importSuccessful": "Me sukses!",
|
||||||
"pad.importExport.export": "Eksportojeni bllokun e tanishëm si:",
|
"pad.importExport.export": "Eksportojeni bllokun e tanishëm si:",
|
||||||
|
"pad.importExport.exportetherpad": "Etherpad",
|
||||||
"pad.importExport.exporthtml": "HTML",
|
"pad.importExport.exporthtml": "HTML",
|
||||||
"pad.importExport.exportplain": "Tekst të thjeshtë",
|
"pad.importExport.exportplain": "Tekst të thjeshtë",
|
||||||
"pad.importExport.exportword": "Microsoft Word",
|
"pad.importExport.exportword": "Microsoft Word",
|
||||||
|
@ -58,7 +59,7 @@
|
||||||
"pad.modals.userdup.explanation": "Ky bllok duket se gjendet i hapur në më shumë se një dritare shfletuesi në këtë kompjuter.",
|
"pad.modals.userdup.explanation": "Ky bllok duket se gjendet i hapur në më shumë se një dritare shfletuesi në këtë kompjuter.",
|
||||||
"pad.modals.userdup.advice": "Rilidhuni që të përdoret kjo dritare.",
|
"pad.modals.userdup.advice": "Rilidhuni që të përdoret kjo dritare.",
|
||||||
"pad.modals.unauth": "I paautorizuar",
|
"pad.modals.unauth": "I paautorizuar",
|
||||||
"pad.modals.unauth.explanation": "Ndërkohë që shihnit këtë dritare, lejet tuaja kanë ndryshuar. Provoni të rilidheni.",
|
"pad.modals.unauth.explanation": "Ndërkohë që sheh këtë dritare, lejet e tua kanë ndryshuar. Provo të rilidhesh.",
|
||||||
"pad.modals.looping.explanation": "Ka probleme komunikimi me shërbyesin e njëkohësimit.",
|
"pad.modals.looping.explanation": "Ka probleme komunikimi me shërbyesin e njëkohësimit.",
|
||||||
"pad.modals.looping.cause": "Ndoshta jeni lidhur përmes një firewall-i ose ndërmjetësi të papërputhshëm.",
|
"pad.modals.looping.cause": "Ndoshta jeni lidhur përmes një firewall-i ose ndërmjetësi të papërputhshëm.",
|
||||||
"pad.modals.initsocketfail": "Nuk kapet dot shërbyesi.",
|
"pad.modals.initsocketfail": "Nuk kapet dot shërbyesi.",
|
||||||
|
@ -90,6 +91,7 @@
|
||||||
"timeslider.exportCurrent": "Eksportojeni versionin e tanishëm si:",
|
"timeslider.exportCurrent": "Eksportojeni versionin e tanishëm si:",
|
||||||
"timeslider.version": "Versioni {{version}}",
|
"timeslider.version": "Versioni {{version}}",
|
||||||
"timeslider.saved": "Ruajtur më {{month}} {{day}}, {{year}}",
|
"timeslider.saved": "Ruajtur më {{month}} {{day}}, {{year}}",
|
||||||
|
"timeslider.playPause": "Luaj përmbajtjet e Pad / Pauzo",
|
||||||
"timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
"timeslider.dateformat": "{{month}}/{{day}}/{{year}} {{hours}}:{{minutes}}:{{seconds}}",
|
||||||
"timeslider.month.january": "Janar",
|
"timeslider.month.january": "Janar",
|
||||||
"timeslider.month.february": "Shkurt",
|
"timeslider.month.february": "Shkurt",
|
||||||
|
|
|
@ -82,7 +82,7 @@
|
||||||
"pad.modals.badChangeset.cause": "这可能是因为服务器配置的错误或者其他未预料到的行为。如果您认为这是错误,请联系服务管理员。要继续编辑,请尝试重新连接。",
|
"pad.modals.badChangeset.cause": "这可能是因为服务器配置的错误或者其他未预料到的行为。如果您认为这是错误,请联系服务管理员。要继续编辑,请尝试重新连接。",
|
||||||
"pad.modals.corruptPad.explanation": "您试图连接的记事本已损坏。",
|
"pad.modals.corruptPad.explanation": "您试图连接的记事本已损坏。",
|
||||||
"pad.modals.corruptPad.cause": "这可能是因为服务器配置的错误或者其他未预料到的行为。请联系服务管理员。",
|
"pad.modals.corruptPad.cause": "这可能是因为服务器配置的错误或者其他未预料到的行为。请联系服务管理员。",
|
||||||
"pad.modals.deleted": "已刪除。",
|
"pad.modals.deleted": "已删除。",
|
||||||
"pad.modals.deleted.explanation": "此记事本已被移除。",
|
"pad.modals.deleted.explanation": "此记事本已被移除。",
|
||||||
"pad.modals.disconnected": "您已断开连接。",
|
"pad.modals.disconnected": "您已断开连接。",
|
||||||
"pad.modals.disconnected.explanation": "到服务器的连接已丢失",
|
"pad.modals.disconnected.explanation": "到服务器的连接已丢失",
|
||||||
|
|
|
@ -307,6 +307,38 @@ exports.setText = function(padID, text, callback)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
appendText(padID, text) appends text to a pad
|
||||||
|
|
||||||
|
Example returns:
|
||||||
|
|
||||||
|
{code: 0, message:"ok", data: null}
|
||||||
|
{code: 1, message:"padID does not exist", data: null}
|
||||||
|
{code: 1, message:"text too long", data: null}
|
||||||
|
*/
|
||||||
|
exports.appendText = function(padID, text, callback)
|
||||||
|
{
|
||||||
|
//text is required
|
||||||
|
if(typeof text != "string")
|
||||||
|
{
|
||||||
|
callback(new customError("text is no string","apierror"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//get the pad
|
||||||
|
getPadSafe(padID, true, function(err, pad)
|
||||||
|
{
|
||||||
|
if(ERR(err, callback)) return;
|
||||||
|
|
||||||
|
pad.appendText(text);
|
||||||
|
|
||||||
|
//update the clients on the pad
|
||||||
|
padMessageHandler.updatePadClients(pad, callback);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
getHTML(padID, [rev]) returns the html of a pad
|
getHTML(padID, [rev]) returns the html of a pad
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ exports.createAuthor = function(name, callback)
|
||||||
var author = "a." + randomString(16);
|
var author = "a." + randomString(16);
|
||||||
|
|
||||||
//create the globalAuthors db entry
|
//create the globalAuthors db entry
|
||||||
var authorObj = {"colorId" : Math.floor(Math.random()*32), "name": name, "timestamp": new Date().getTime()};
|
var authorObj = {"colorId" : Math.floor(Math.random()*(exports.getColorPalette().length)), "name": name, "timestamp": new Date().getTime()};
|
||||||
|
|
||||||
//set the global author db entry
|
//set the global author db entry
|
||||||
db.set("globalAuthor:" + author, authorObj);
|
db.set("globalAuthor:" + author, authorObj);
|
||||||
|
|
|
@ -303,6 +303,19 @@ Pad.prototype.setText = function setText(newText) {
|
||||||
this.appendRevision(changeset);
|
this.appendRevision(changeset);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Pad.prototype.appendText = function appendText(newText) {
|
||||||
|
//clean the new text
|
||||||
|
newText = exports.cleanText(newText);
|
||||||
|
|
||||||
|
var oldText = this.text();
|
||||||
|
|
||||||
|
//create the changeset
|
||||||
|
var changeset = Changeset.makeSplice(oldText, oldText.length, 0, newText);
|
||||||
|
|
||||||
|
//append the changeset
|
||||||
|
this.appendRevision(changeset);
|
||||||
|
};
|
||||||
|
|
||||||
Pad.prototype.appendChatMessage = function appendChatMessage(text, userId, time) {
|
Pad.prototype.appendChatMessage = function appendChatMessage(text, userId, time) {
|
||||||
this.chatHead++;
|
this.chatHead++;
|
||||||
//save the chat entry in the database
|
//save the chat entry in the database
|
||||||
|
|
|
@ -444,10 +444,61 @@ var version =
|
||||||
, "getChatHead" : ["padID"]
|
, "getChatHead" : ["padID"]
|
||||||
, "restoreRevision" : ["padID", "rev"]
|
, "restoreRevision" : ["padID", "rev"]
|
||||||
}
|
}
|
||||||
|
, "1.2.13":
|
||||||
|
{ "createGroup" : []
|
||||||
|
, "createGroupIfNotExistsFor" : ["groupMapper"]
|
||||||
|
, "deleteGroup" : ["groupID"]
|
||||||
|
, "listPads" : ["groupID"]
|
||||||
|
, "listAllPads" : []
|
||||||
|
, "createDiffHTML" : ["padID", "startRev", "endRev"]
|
||||||
|
, "createPad" : ["padID", "text"]
|
||||||
|
, "createGroupPad" : ["groupID", "padName", "text"]
|
||||||
|
, "createAuthor" : ["name"]
|
||||||
|
, "createAuthorIfNotExistsFor": ["authorMapper" , "name"]
|
||||||
|
, "listPadsOfAuthor" : ["authorID"]
|
||||||
|
, "createSession" : ["groupID", "authorID", "validUntil"]
|
||||||
|
, "deleteSession" : ["sessionID"]
|
||||||
|
, "getSessionInfo" : ["sessionID"]
|
||||||
|
, "listSessionsOfGroup" : ["groupID"]
|
||||||
|
, "listSessionsOfAuthor" : ["authorID"]
|
||||||
|
, "getText" : ["padID", "rev"]
|
||||||
|
, "setText" : ["padID", "text"]
|
||||||
|
, "getHTML" : ["padID", "rev"]
|
||||||
|
, "setHTML" : ["padID", "html"]
|
||||||
|
, "getAttributePool" : ["padID"]
|
||||||
|
, "getRevisionsCount" : ["padID"]
|
||||||
|
, "getSavedRevisionsCount" : ["padID"]
|
||||||
|
, "listSavedRevisions" : ["padID"]
|
||||||
|
, "saveRevision" : ["padID", "rev"]
|
||||||
|
, "getRevisionChangeset" : ["padID", "rev"]
|
||||||
|
, "getLastEdited" : ["padID"]
|
||||||
|
, "deletePad" : ["padID"]
|
||||||
|
, "copyPad" : ["sourceID", "destinationID", "force"]
|
||||||
|
, "movePad" : ["sourceID", "destinationID", "force"]
|
||||||
|
, "getReadOnlyID" : ["padID"]
|
||||||
|
, "getPadID" : ["roID"]
|
||||||
|
, "setPublicStatus" : ["padID", "publicStatus"]
|
||||||
|
, "getPublicStatus" : ["padID"]
|
||||||
|
, "setPassword" : ["padID", "password"]
|
||||||
|
, "isPasswordProtected" : ["padID"]
|
||||||
|
, "listAuthorsOfPad" : ["padID"]
|
||||||
|
, "padUsersCount" : ["padID"]
|
||||||
|
, "getAuthorName" : ["authorID"]
|
||||||
|
, "padUsers" : ["padID"]
|
||||||
|
, "sendClientsMessage" : ["padID", "msg"]
|
||||||
|
, "listAllGroups" : []
|
||||||
|
, "checkToken" : []
|
||||||
|
, "appendChatMessage" : ["padID", "text", "authorID", "time"]
|
||||||
|
, "getChatHistory" : ["padID"]
|
||||||
|
, "getChatHistory" : ["padID", "start", "end"]
|
||||||
|
, "getChatHead" : ["padID"]
|
||||||
|
, "restoreRevision" : ["padID", "rev"]
|
||||||
|
, "appendText" : ["padID", "text"]
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// set the latest available API version here
|
// set the latest available API version here
|
||||||
exports.latestApiVersion = '1.2.12';
|
exports.latestApiVersion = '1.2.13';
|
||||||
|
|
||||||
// exports the versions so it can be used by the new Swagger endpoint
|
// exports the versions so it can be used by the new Swagger endpoint
|
||||||
exports.version = version;
|
exports.version = version;
|
||||||
|
|
|
@ -30,9 +30,15 @@ var os = require('os');
|
||||||
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
|
var hooks = require("ep_etherpad-lite/static/js/pluginfw/hooks");
|
||||||
var TidyHtml = require('../utils/TidyHtml');
|
var TidyHtml = require('../utils/TidyHtml');
|
||||||
|
|
||||||
|
var convertor = null;
|
||||||
|
|
||||||
//load abiword only if its enabled
|
//load abiword only if its enabled
|
||||||
if(settings.abiword != null)
|
if(settings.abiword != null)
|
||||||
var abiword = require("../utils/Abiword");
|
convertor = require("../utils/Abiword");
|
||||||
|
|
||||||
|
// Use LibreOffice if an executable has been defined in the settings
|
||||||
|
if(settings.soffice != null)
|
||||||
|
convertor = require("../utils/LibreOffice");
|
||||||
|
|
||||||
var tempDirectory = "/tmp";
|
var tempDirectory = "/tmp";
|
||||||
|
|
||||||
|
@ -70,71 +76,11 @@ exports.doExport = function(req, res, padId, type)
|
||||||
}
|
}
|
||||||
else if(type == "txt")
|
else if(type == "txt")
|
||||||
{
|
{
|
||||||
var txt;
|
exporttxt.getPadTXTDocument(padId, req.params.rev, false, function(err, txt)
|
||||||
var randNum;
|
|
||||||
var srcFile, destFile;
|
|
||||||
|
|
||||||
async.series([
|
|
||||||
//render the txt document
|
|
||||||
function(callback)
|
|
||||||
{
|
|
||||||
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 + "/etherpad_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);
|
if(ERR(err)) return;
|
||||||
})
|
res.send(txt);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -183,11 +129,11 @@ exports.doExport = function(req, res, padId, type)
|
||||||
TidyHtml.tidy(srcFile, callback);
|
TidyHtml.tidy(srcFile, callback);
|
||||||
},
|
},
|
||||||
|
|
||||||
//send the convert job to abiword
|
//send the convert job to the convertor (abiword, libreoffice, ..)
|
||||||
function(callback)
|
function(callback)
|
||||||
{
|
{
|
||||||
destFile = tempDirectory + "/etherpad_export_" + randNum + "." + type;
|
destFile = tempDirectory + "/etherpad_export_" + randNum + "." + type;
|
||||||
abiword.convertFile(srcFile, destFile, type, callback);
|
convertor.convertFile(srcFile, destFile, type, callback);
|
||||||
},
|
},
|
||||||
//send the file
|
//send the file
|
||||||
function(callback)
|
function(callback)
|
||||||
|
|
|
@ -1020,6 +1020,8 @@ function handleClientReady(client, message)
|
||||||
var currentTime;
|
var currentTime;
|
||||||
var padIds;
|
var padIds;
|
||||||
|
|
||||||
|
hooks.callAll("clientReady", message);
|
||||||
|
|
||||||
async.series([
|
async.series([
|
||||||
//Get ro/rw id:s
|
//Get ro/rw id:s
|
||||||
function (callback)
|
function (callback)
|
||||||
|
@ -1229,6 +1231,7 @@ function handleClientReady(client, message)
|
||||||
"plugins": plugins.plugins,
|
"plugins": plugins.plugins,
|
||||||
"parts": plugins.parts,
|
"parts": plugins.parts,
|
||||||
},
|
},
|
||||||
|
"indentationOnNewLine": settings.indentationOnNewLine,
|
||||||
"initialChangesets": [] // FIXME: REMOVE THIS SHIT
|
"initialChangesets": [] // FIXME: REMOVE THIS SHIT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1365,6 +1368,12 @@ function handleChangesetRequest(client, message)
|
||||||
messageLogger.warn("Dropped message, changeset request has no granularity!");
|
messageLogger.warn("Dropped message, changeset request has no granularity!");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/isInteger#Polyfill
|
||||||
|
if(Math.floor(message.data.granularity) !== message.data.granularity)
|
||||||
|
{
|
||||||
|
messageLogger.warn("Dropped message, changeset request granularity is not an integer!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
if(message.data.start == null)
|
if(message.data.start == null)
|
||||||
{
|
{
|
||||||
messageLogger.warn("Dropped message, changeset request has no start!");
|
messageLogger.warn("Dropped message, changeset request has no start!");
|
||||||
|
|
|
@ -16,6 +16,7 @@ exports.expressCreateServer = function (hook_name, args, cb) {
|
||||||
if(sanitizedPadId != padId)
|
if(sanitizedPadId != padId)
|
||||||
{
|
{
|
||||||
var real_url = sanitizedPadId;
|
var real_url = sanitizedPadId;
|
||||||
|
real_url = encodeURIComponent(real_url);
|
||||||
var query = url.parse(req.url).query;
|
var query = url.parse(req.url).query;
|
||||||
if ( query ) real_url += '?' + query;
|
if ( query ) real_url += '?' + query;
|
||||||
res.header('Location', real_url);
|
res.header('Location', real_url);
|
||||||
|
|
|
@ -19,6 +19,7 @@ var async = require("async");
|
||||||
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
var Changeset = require("ep_etherpad-lite/static/js/Changeset");
|
||||||
var padManager = require("../db/PadManager");
|
var padManager = require("../db/PadManager");
|
||||||
var ERR = require("async-stacktrace");
|
var ERR = require("async-stacktrace");
|
||||||
|
var _ = require('underscore');
|
||||||
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');
|
||||||
var _analyzeLine = require('./ExportHelper')._analyzeLine;
|
var _analyzeLine = require('./ExportHelper')._analyzeLine;
|
||||||
|
@ -77,12 +78,21 @@ function getHTMLFromAtext(pad, atext, authorColors)
|
||||||
var tags = ['h1', 'h2', 'strong', 'em', 'u', 's'];
|
var tags = ['h1', 'h2', 'strong', 'em', 'u', 's'];
|
||||||
var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough'];
|
var props = ['heading1', 'heading2', 'bold', 'italic', 'underline', 'strikethrough'];
|
||||||
|
|
||||||
|
// prepare tags stored as ['tag', true] to be exported
|
||||||
hooks.aCallAll("exportHtmlAdditionalTags", pad, function(err, newProps){
|
hooks.aCallAll("exportHtmlAdditionalTags", pad, function(err, newProps){
|
||||||
newProps.forEach(function (propName, i){
|
newProps.forEach(function (propName, i){
|
||||||
tags.push(propName);
|
tags.push(propName);
|
||||||
props.push(propName);
|
props.push(propName);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
// prepare tags stored as ['tag', 'value'] to be exported. This will generate HTML
|
||||||
|
// with tags like <span data-tag="value">
|
||||||
|
hooks.aCallAll("exportHtmlAdditionalTagsWithData", pad, function(err, newProps){
|
||||||
|
newProps.forEach(function (propName, i){
|
||||||
|
tags.push('span data-' + propName[0] + '="' + propName[1] + '"');
|
||||||
|
props.push(propName);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
// holds a map of used styling attributes (*1, *2, etc) in the apool
|
// holds a map of used styling attributes (*1, *2, etc) in the apool
|
||||||
// and maps them to an index in props
|
// and maps them to an index in props
|
||||||
|
@ -130,7 +140,13 @@ function getHTMLFromAtext(pad, atext, authorColors)
|
||||||
// this pad, and if yes puts its attrib id->props value into anumMap
|
// this pad, and if yes puts its attrib id->props value into anumMap
|
||||||
props.forEach(function (propName, i)
|
props.forEach(function (propName, i)
|
||||||
{
|
{
|
||||||
var propTrueNum = apool.putAttrib([propName, true], true);
|
var attrib = [propName, true];
|
||||||
|
if (_.isArray(propName)) {
|
||||||
|
// propName can be in the form of ['color', 'red'],
|
||||||
|
// see hook exportHtmlAdditionalTagsWithData
|
||||||
|
attrib = propName;
|
||||||
|
}
|
||||||
|
var propTrueNum = apool.putAttrib(attrib, true);
|
||||||
if (propTrueNum >= 0)
|
if (propTrueNum >= 0)
|
||||||
{
|
{
|
||||||
anumMap[propTrueNum] = i;
|
anumMap[propTrueNum] = i;
|
||||||
|
@ -154,6 +170,12 @@ function getHTMLFromAtext(pad, atext, authorColors)
|
||||||
|
|
||||||
var property = props[i];
|
var property = props[i];
|
||||||
|
|
||||||
|
// we are not insterested on properties in the form of ['color', 'red'],
|
||||||
|
// see hook exportHtmlAdditionalTagsWithData
|
||||||
|
if (_.isArray(property)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(property.substr(0,6) === "author"){
|
if(property.substr(0,6) === "author"){
|
||||||
return stripDotFromAuthorID(property);
|
return stripDotFromAuthorID(property);
|
||||||
}
|
}
|
||||||
|
@ -165,6 +187,13 @@ function getHTMLFromAtext(pad, atext, authorColors)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// tags added by exportHtmlAdditionalTagsWithData will be exported as <span> with
|
||||||
|
// data attributes
|
||||||
|
function isSpanWithData(i){
|
||||||
|
var property = props[i];
|
||||||
|
return _.isArray(property);
|
||||||
|
}
|
||||||
|
|
||||||
function emitOpenTag(i)
|
function emitOpenTag(i)
|
||||||
{
|
{
|
||||||
openTags.unshift(i);
|
openTags.unshift(i);
|
||||||
|
@ -186,8 +215,9 @@ function getHTMLFromAtext(pad, atext, authorColors)
|
||||||
{
|
{
|
||||||
openTags.shift();
|
openTags.shift();
|
||||||
var spanClass = getSpanClassFor(i);
|
var spanClass = getSpanClassFor(i);
|
||||||
|
var spanWithData = isSpanWithData(i);
|
||||||
|
|
||||||
if(spanClass){
|
if(spanClass || spanWithData){
|
||||||
assem.append('</span>');
|
assem.append('</span>');
|
||||||
} else {
|
} else {
|
||||||
assem.append('</');
|
assem.append('</');
|
||||||
|
@ -464,6 +494,9 @@ exports.getPadHTMLDocument = function (padId, revNum, noDocType, callback)
|
||||||
(noDocType ? '' : '<!doctype html>\n') +
|
(noDocType ? '' : '<!doctype html>\n') +
|
||||||
'<html lang="en">\n' + (noDocType ? '' : '<head>\n' +
|
'<html lang="en">\n' + (noDocType ? '' : '<head>\n' +
|
||||||
'<title>' + Security.escapeHTML(padId) + '</title>\n' +
|
'<title>' + Security.escapeHTML(padId) + '</title>\n' +
|
||||||
|
'<meta name="generator" content="Etherpad">\n' +
|
||||||
|
'<meta name="author" content="Etherpad">\n' +
|
||||||
|
'<meta name="changedby" content="Etherpad">\n' +
|
||||||
'<meta charset="utf-8">\n' +
|
'<meta charset="utf-8">\n' +
|
||||||
'<style> * { font-family: arial, sans-serif;\n' +
|
'<style> * { font-family: arial, sans-serif;\n' +
|
||||||
'font-size: 13px;\n' +
|
'font-size: 13px;\n' +
|
||||||
|
|
93
src/node/utils/LibreOffice.js
Normal file
93
src/node/utils/LibreOffice.js
Normal file
|
@ -0,0 +1,93 @@
|
||||||
|
/**
|
||||||
|
* Controls the communication with LibreOffice
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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 fs = require("fs");
|
||||||
|
var os = require("os");
|
||||||
|
var path = require("path");
|
||||||
|
var settings = require("./Settings");
|
||||||
|
var spawn = require("child_process").spawn;
|
||||||
|
|
||||||
|
// Conversion tasks will be queued up, so we don't overload the system
|
||||||
|
var queue = async.queue(doConvertTask, 1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a file from one type to another
|
||||||
|
*
|
||||||
|
* @param {String} srcFile The path on disk to convert
|
||||||
|
* @param {String} destFile The path on disk where the converted file should be stored
|
||||||
|
* @param {String} type The type to convert into
|
||||||
|
* @param {Function} callback Standard callback function
|
||||||
|
*/
|
||||||
|
exports.convertFile = function(srcFile, destFile, type, callback) {
|
||||||
|
queue.push({"srcFile": srcFile, "destFile": destFile, "type": type, "callback": callback});
|
||||||
|
};
|
||||||
|
|
||||||
|
function doConvertTask(task, callback) {
|
||||||
|
var tmpDir = os.tmpdir();
|
||||||
|
|
||||||
|
async.series([
|
||||||
|
// Generate a PDF file with LibreOffice
|
||||||
|
function(callback) {
|
||||||
|
var soffice = spawn(settings.soffice, [
|
||||||
|
'--headless',
|
||||||
|
'--invisible',
|
||||||
|
'--nologo',
|
||||||
|
'--nolockcheck',
|
||||||
|
'--convert-to', task.type,
|
||||||
|
task.srcFile,
|
||||||
|
'--outdir', tmpDir
|
||||||
|
]);
|
||||||
|
|
||||||
|
var stdoutBuffer = '';
|
||||||
|
|
||||||
|
// Delegate the processing of stdout to another function
|
||||||
|
soffice.stdout.on('data', function(data) {
|
||||||
|
stdoutBuffer += data.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Append error messages to the buffer
|
||||||
|
soffice.stderr.on('data', function(data) {
|
||||||
|
stdoutBuffer += data.toString();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Throw an exception if libreoffice failed
|
||||||
|
soffice.on('exit', function(code) {
|
||||||
|
if (code != 0) {
|
||||||
|
return callback("LibreOffice died with exit code " + code + " and message: " + stdoutBuffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
callback();
|
||||||
|
})
|
||||||
|
},
|
||||||
|
|
||||||
|
// Move the PDF file to the correct place
|
||||||
|
function(callback) {
|
||||||
|
var filename = path.basename(task.srcFile);
|
||||||
|
var pdfFilename = filename.substr(0, filename.lastIndexOf('.')) + '.' + task.type;
|
||||||
|
var pdfPath = path.join(tmpDir, pdfFilename);
|
||||||
|
fs.rename(pdfPath, task.destFile, callback);
|
||||||
|
}
|
||||||
|
], function(err) {
|
||||||
|
// Invoke the callback for the local queue
|
||||||
|
callback();
|
||||||
|
|
||||||
|
// Invoke the callback for the task
|
||||||
|
task.callback(err);
|
||||||
|
});
|
||||||
|
}
|
|
@ -152,6 +152,11 @@ exports.minify = true;
|
||||||
*/
|
*/
|
||||||
exports.abiword = null;
|
exports.abiword = null;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path of the libreoffice executable
|
||||||
|
*/
|
||||||
|
exports.soffice = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The path of the tidy executable
|
* The path of the tidy executable
|
||||||
*/
|
*/
|
||||||
|
@ -177,6 +182,11 @@ exports.disableIPlogging = false;
|
||||||
*/
|
*/
|
||||||
exports.loadTest = false;
|
exports.loadTest = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enable indentation on new lines
|
||||||
|
*/
|
||||||
|
exports.indentationOnNewLine = true;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* log4js appender configuration
|
* log4js appender configuration
|
||||||
*/
|
*/
|
||||||
|
@ -218,8 +228,14 @@ exports.getGitCommit = function() {
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var rootPath = path.resolve(npm.dir, '..');
|
var rootPath = path.resolve(npm.dir, '..');
|
||||||
var ref = fs.readFileSync(rootPath + "/.git/HEAD", "utf-8");
|
if (fs.lstatSync(rootPath + '/.git').isFile()) {
|
||||||
var refPath = rootPath + "/.git/" + ref.substring(5, ref.indexOf("\n"));
|
rootPath = fs.readFileSync(rootPath + '/.git', "utf8");
|
||||||
|
rootPath = rootPath.split(' ').pop().trim();
|
||||||
|
} else {
|
||||||
|
rootPath += '/.git';
|
||||||
|
}
|
||||||
|
var ref = fs.readFileSync(rootPath + "/HEAD", "utf-8");
|
||||||
|
var refPath = rootPath + "/" + ref.substring(5, ref.indexOf("\n"));
|
||||||
version = fs.readFileSync(refPath, "utf-8");
|
version = fs.readFileSync(refPath, "utf-8");
|
||||||
version = version.substring(0, 7);
|
version = version.substring(0, 7);
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,7 +265,7 @@ plugins.ensure(function () {\n\
|
||||||
iframeHTML: iframeHTML
|
iframeHTML: iframeHTML
|
||||||
});
|
});
|
||||||
|
|
||||||
iframeHTML.push('</head><body id="innerdocbody" role="application" class="syntax" spellcheck="false"> </body></html>');
|
iframeHTML.push('</head><body id="innerdocbody" class="innerdocbody" role="application" class="syntax" spellcheck="false"> </body></html>');
|
||||||
|
|
||||||
// Expose myself to global for my child frame.
|
// Expose myself to global for my child frame.
|
||||||
var thisFunctionsName = "ChildAccessibleAce2Editor";
|
var thisFunctionsName = "ChildAccessibleAce2Editor";
|
||||||
|
@ -315,7 +315,7 @@ window.onload = function () {\n\
|
||||||
|
|
||||||
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly
|
// bizarrely, in FF2, a file with no "external" dependencies won't finish loading properly
|
||||||
// (throbs busy while typing)
|
// (throbs busy while typing)
|
||||||
outerHTML.push('<style type="text/css" title="dynamicsyntax"></style>', '<link rel="stylesheet" type="text/css" href="data:text/css,"/>', scriptTag(outerScript), '</head><body id="outerdocbody"><div id="sidediv"><!-- --></div><div id="linemetricsdiv">x</div></body></html>');
|
outerHTML.push('<style type="text/css" title="dynamicsyntax"></style>', '<link rel="stylesheet" type="text/css" href="data:text/css,"/>', scriptTag(outerScript), '</head><body id="outerdocbody" class="outerdocbody"><div id="sidediv" class="sidediv"><!-- --></div><div id="linemetricsdiv">x</div></body></html>');
|
||||||
|
|
||||||
var outerFrame = document.createElement("IFRAME");
|
var outerFrame = document.createElement("IFRAME");
|
||||||
outerFrame.name = "ace_outer";
|
outerFrame.name = "ace_outer";
|
||||||
|
|
|
@ -1894,7 +1894,11 @@ 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;
|
var shouldIndent = parent.parent.clientVars.indentationOnNewLine;
|
||||||
|
if (shouldIndent && /[\[\(\:\{]\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, [
|
||||||
|
@ -2897,6 +2901,12 @@ function Ace2Inner(){
|
||||||
rep.selFocusAtStart = newSelFocusAtStart;
|
rep.selFocusAtStart = newSelFocusAtStart;
|
||||||
currentCallStack.repChanged = true;
|
currentCallStack.repChanged = true;
|
||||||
|
|
||||||
|
hooks.callAll('aceSelectionChanged', {
|
||||||
|
rep: rep,
|
||||||
|
callstack: currentCallStack,
|
||||||
|
documentAttributeManager: documentAttributeManager,
|
||||||
|
});
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
//console.log("selStart: %o, selEnd: %o, focusAtStart: %s", rep.selStart, rep.selEnd,
|
//console.log("selStart: %o, selEnd: %o, focusAtStart: %s", rep.selStart, rep.selEnd,
|
||||||
//String(!!rep.selFocusAtStart));
|
//String(!!rep.selFocusAtStart));
|
||||||
|
@ -3632,12 +3642,6 @@ function Ace2Inner(){
|
||||||
var altKey = evt.altKey;
|
var altKey = evt.altKey;
|
||||||
var shiftKey = evt.shiftKey;
|
var shiftKey = evt.shiftKey;
|
||||||
|
|
||||||
// prevent ESC key
|
|
||||||
if (keyCode == 27)
|
|
||||||
{
|
|
||||||
evt.preventDefault();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// Is caret potentially hidden by the chat button?
|
// Is caret potentially hidden by the chat button?
|
||||||
var myselection = document.getSelection(); // get the current caret selection
|
var myselection = document.getSelection(); // get the current caret selection
|
||||||
var caretOffsetTop = myselection.focusNode.parentNode.offsetTop | myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214
|
var caretOffsetTop = myselection.focusNode.parentNode.offsetTop | myselection.focusNode.offsetTop; // get the carets selection offset in px IE 214
|
||||||
|
@ -3706,7 +3710,12 @@ function Ace2Inner(){
|
||||||
documentAttributeManager: documentAttributeManager,
|
documentAttributeManager: documentAttributeManager,
|
||||||
evt:evt
|
evt:evt
|
||||||
});
|
});
|
||||||
specialHandled = (specialHandledInHook&&specialHandledInHook.length>0)?specialHandledInHook[0]:specialHandled;
|
|
||||||
|
// if any hook returned true, set specialHandled with true
|
||||||
|
if (specialHandledInHook) {
|
||||||
|
specialHandled = _.contains(specialHandledInHook, true);
|
||||||
|
}
|
||||||
|
|
||||||
if ((!specialHandled) && altKey && isTypeForSpecialKey && keyCode == 120){
|
if ((!specialHandled) && altKey && isTypeForSpecialKey && keyCode == 120){
|
||||||
// Alt F9 focuses on the File Menu and/or editbar.
|
// Alt F9 focuses on the File Menu and/or editbar.
|
||||||
// Note that while most editors use Alt F10 this is not desirable
|
// Note that while most editors use Alt F10 this is not desirable
|
||||||
|
@ -3830,6 +3839,15 @@ function Ace2Inner(){
|
||||||
}, 0);
|
}, 0);
|
||||||
specialHandled = true;
|
specialHandled = true;
|
||||||
}
|
}
|
||||||
|
if ((!specialHandled) && isTypeForSpecialKey && keyCode == 27)
|
||||||
|
{
|
||||||
|
// prevent esc key;
|
||||||
|
// in mozilla versions 14-19 avoid reconnecting pad.
|
||||||
|
|
||||||
|
fastIncorp(4);
|
||||||
|
evt.preventDefault();
|
||||||
|
specialHandled = true;
|
||||||
|
}
|
||||||
if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "s" && (evt.metaKey || evt.ctrlKey) && !evt.altKey) /* Do a saved revision on ctrl S */
|
if ((!specialHandled) && isTypeForCmdKey && String.fromCharCode(which).toLowerCase() == "s" && (evt.metaKey || evt.ctrlKey) && !evt.altKey) /* Do a saved revision on ctrl S */
|
||||||
{
|
{
|
||||||
evt.preventDefault();
|
evt.preventDefault();
|
||||||
|
@ -4978,6 +4996,13 @@ function Ace2Inner(){
|
||||||
if(e.target.a || e.target.localName === "a"){
|
if(e.target.a || e.target.localName === "a"){
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call paste hook
|
||||||
|
hooks.callAll('acePaste', {
|
||||||
|
editorInfo: editorInfo,
|
||||||
|
rep: rep,
|
||||||
|
documentAttributeManager: documentAttributeManager
|
||||||
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
// CompositionEvent is not implemented below IE version 8
|
// CompositionEvent is not implemented below IE version 8
|
||||||
|
@ -5347,8 +5372,9 @@ function Ace2Inner(){
|
||||||
function initLineNumbers()
|
function initLineNumbers()
|
||||||
{
|
{
|
||||||
lineNumbersShown = 1;
|
lineNumbersShown = 1;
|
||||||
sideDiv.innerHTML = '<table border="0" cellpadding="0" cellspacing="0" align="right"><tr><td id="sidedivinner"><div>1</div></td></tr></table>';
|
sideDiv.innerHTML = '<table border="0" cellpadding="0" cellspacing="0" align="right"><tr><td id="sidedivinner" class="sidedivinner"><div>1</div></td></tr></table>';
|
||||||
sideDivInner = outerWin.document.getElementById("sidedivinner");
|
sideDivInner = outerWin.document.getElementById("sidedivinner");
|
||||||
|
$(sideDiv).addClass("sidediv");
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateLineNumbers()
|
function updateLineNumbers()
|
||||||
|
|
|
@ -11,7 +11,7 @@ $(document).ready(function () {
|
||||||
|
|
||||||
//connect
|
//connect
|
||||||
var room = url + "pluginfw/installer";
|
var room = url + "pluginfw/installer";
|
||||||
socket = io.connect(room, {resource : resource});
|
socket = io.connect(room, {path: baseURL + "socket.io", resource : resource});
|
||||||
|
|
||||||
function search(searchTerm, limit) {
|
function search(searchTerm, limit) {
|
||||||
if(search.searchTerm != searchTerm) {
|
if(search.searchTerm != searchTerm) {
|
||||||
|
|
|
@ -10,7 +10,7 @@ $(document).ready(function () {
|
||||||
|
|
||||||
//connect
|
//connect
|
||||||
var room = url + "settings";
|
var room = url + "settings";
|
||||||
socket = io.connect(room, {resource : resource});
|
socket = io.connect(room, {path: baseURL + "socket.io", resource : resource});
|
||||||
|
|
||||||
socket.on('settings', function (settings) {
|
socket.on('settings', function (settings) {
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ function makeContentCollector(collectStyles, abrowser, apool, domInterface, clas
|
||||||
function textify(str)
|
function textify(str)
|
||||||
{
|
{
|
||||||
return sanitizeUnicode(
|
return sanitizeUnicode(
|
||||||
str.replace(/\n/g, '').replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' '));
|
str.replace(/(\n | \n)/g, ' ').replace(/[\n\r ]/g, ' ').replace(/\xa0/g, ' ').replace(/\t/g, ' '));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getAssoc(node, name)
|
function getAssoc(node, name)
|
||||||
|
|
|
@ -100,7 +100,7 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="editorcontainerbox">
|
<div id="editorcontainerbox">
|
||||||
<div id="editorcontainer"></div>
|
<div id="editorcontainer" class="editorcontainer"></div>
|
||||||
<div id="editorloadingbox">
|
<div id="editorloadingbox">
|
||||||
<div id="passwordRequired">
|
<div id="passwordRequired">
|
||||||
<p data-l10n-id="pad.passwordRequired">You need a password to access this pad</p>
|
<p data-l10n-id="pad.passwordRequired">You need a password to access this pad</p>
|
||||||
|
|
|
@ -79,6 +79,8 @@ describe('Permission', function(){
|
||||||
-> movePad(newPadID, originalPadId) -- Should provide consistant pad data
|
-> movePad(newPadID, originalPadId) -- Should provide consistant pad data
|
||||||
-> getText(originalPadId) -- Should be "hello world"
|
-> getText(originalPadId) -- Should be "hello world"
|
||||||
-> getLastEdited(padID) -- Should not be 0
|
-> getLastEdited(padID) -- Should not be 0
|
||||||
|
-> appendText(padID, "hello")
|
||||||
|
-> getText(padID) -- Should be "hello worldhello"
|
||||||
-> setHTML(padID) -- Should fail on invalid HTML
|
-> setHTML(padID) -- Should fail on invalid HTML
|
||||||
-> setHTML(padID) *3 -- Should fail on invalid HTML
|
-> setHTML(padID) *3 -- Should fail on invalid HTML
|
||||||
-> getHTML(padID) -- Should return HTML close to posted HTML
|
-> getHTML(padID) -- Should return HTML close to posted HTML
|
||||||
|
@ -483,6 +485,30 @@ describe('getLastEdited', function(){
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('appendText', function(){
|
||||||
|
it('Append text to a pad Id', function(done) {
|
||||||
|
api.get(endPoint('appendText', '1.2.13')+"&padID="+testPadId+"&text=hello")
|
||||||
|
.expect(function(res){
|
||||||
|
if(res.body.code !== 0) throw new Error("Pad Append Text failed");
|
||||||
|
})
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getText', function(){
|
||||||
|
it('Gets text on a pad Id', function(done) {
|
||||||
|
api.get(endPoint('getText')+"&padID="+testPadId)
|
||||||
|
.expect(function(res){
|
||||||
|
if(res.body.code !== 0) throw new Error("Pad Get Text failed");
|
||||||
|
if(res.body.data.text !== text+"\nhello") throw new Error("Pad Text not set properly");
|
||||||
|
})
|
||||||
|
.expect('Content-Type', /json/)
|
||||||
|
.expect(200, done);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
describe('setHTML', function(){
|
describe('setHTML', function(){
|
||||||
it('Sets the HTML of a Pad attempting to pass ugly HTML', function(done) {
|
it('Sets the HTML of a Pad attempting to pass ugly HTML', function(done) {
|
||||||
var html = "<div><b>Hello HTML</title></head></div>";
|
var html = "<div><b>Hello HTML</title></head></div>";
|
||||||
|
@ -542,8 +568,9 @@ describe('createPad', function(){
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var endPoint = function(point){
|
var endPoint = function(point, version){
|
||||||
return '/api/'+apiVersion+'/'+point+'?apikey='+apiKey;
|
version = version || apiVersion;
|
||||||
|
return '/api/'+version+'/'+point+'?apikey='+apiKey;
|
||||||
}
|
}
|
||||||
|
|
||||||
function makeid()
|
function makeid()
|
||||||
|
|
|
@ -68,6 +68,80 @@ describe("indentation button", function(){
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("indents text with spaces on enter if previous line ends with ':', '[', '(', or '{'", function(done){
|
||||||
|
var inner$ = helper.padInner$;
|
||||||
|
var chrome$ = helper.padChrome$;
|
||||||
|
|
||||||
|
//type a bit, make a line break and type again
|
||||||
|
var $firstTextElement = inner$("div").first();
|
||||||
|
$firstTextElement.sendkeys("line with ':'{enter}");
|
||||||
|
$firstTextElement.sendkeys("line with '['{enter}");
|
||||||
|
$firstTextElement.sendkeys("line with '('{enter}");
|
||||||
|
$firstTextElement.sendkeys("line with '{{}'{enter}");
|
||||||
|
|
||||||
|
helper.waitFor(function(){
|
||||||
|
// wait for Etherpad to split four lines into separated divs
|
||||||
|
var $fourthLine = inner$("div").first().next().next().next();
|
||||||
|
return $fourthLine.text().indexOf("line with '{'") === 0;
|
||||||
|
}).done(function(){
|
||||||
|
// we validate bottom to top for easier implementation
|
||||||
|
|
||||||
|
// curly braces
|
||||||
|
var $lineWithCurlyBraces = inner$("div").first().next().next().next();
|
||||||
|
$lineWithCurlyBraces.sendkeys('{{}');
|
||||||
|
pressEnter(); // cannot use sendkeys('{enter}') here, browser does not read the command properly
|
||||||
|
var $lineAfterCurlyBraces = inner$("div").first().next().next().next().next();
|
||||||
|
expect($lineAfterCurlyBraces.text()).to.match(/\s{4}/); // tab === 4 spaces
|
||||||
|
|
||||||
|
// parenthesis
|
||||||
|
var $lineWithParenthesis = inner$("div").first().next().next();
|
||||||
|
$lineWithParenthesis.sendkeys('(');
|
||||||
|
pressEnter();
|
||||||
|
var $lineAfterParenthesis = inner$("div").first().next().next().next();
|
||||||
|
expect($lineAfterParenthesis.text()).to.match(/\s{4}/);
|
||||||
|
|
||||||
|
// bracket
|
||||||
|
var $lineWithBracket = inner$("div").first().next();
|
||||||
|
$lineWithBracket.sendkeys('[');
|
||||||
|
pressEnter();
|
||||||
|
var $lineAfterBracket = inner$("div").first().next().next();
|
||||||
|
expect($lineAfterBracket.text()).to.match(/\s{4}/);
|
||||||
|
|
||||||
|
// colon
|
||||||
|
var $lineWithColon = inner$("div").first();
|
||||||
|
$lineWithColon.sendkeys(':');
|
||||||
|
pressEnter();
|
||||||
|
var $lineAfterColon = inner$("div").first().next();
|
||||||
|
expect($lineAfterColon.text()).to.match(/\s{4}/);
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("appends indentation to the indent of previous line if previous line ends with ':', '[', '(', or '{'", function(done){
|
||||||
|
var inner$ = helper.padInner$;
|
||||||
|
var chrome$ = helper.padChrome$;
|
||||||
|
|
||||||
|
//type a bit, make a line break and type again
|
||||||
|
var $firstTextElement = inner$("div").first();
|
||||||
|
$firstTextElement.sendkeys(" line with some indentation and ':'{enter}");
|
||||||
|
$firstTextElement.sendkeys("line 2{enter}");
|
||||||
|
|
||||||
|
helper.waitFor(function(){
|
||||||
|
// wait for Etherpad to split two lines into separated divs
|
||||||
|
var $secondLine = inner$("div").first().next();
|
||||||
|
return $secondLine.text().indexOf("line 2") === 0;
|
||||||
|
}).done(function(){
|
||||||
|
var $lineWithColon = inner$("div").first();
|
||||||
|
$lineWithColon.sendkeys(':');
|
||||||
|
pressEnter();
|
||||||
|
var $lineAfterColon = inner$("div").first().next();
|
||||||
|
expect($lineAfterColon.text()).to.match(/\s{6}/); // previous line indentation + regular tab (4 spaces)
|
||||||
|
|
||||||
|
done();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
it("makes text indented and outdented", function() {
|
it("makes text indented and outdented", function() {
|
||||||
|
@ -203,3 +277,15 @@ describe("indentation button", function(){
|
||||||
});*/
|
});*/
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function pressEnter(){
|
||||||
|
var inner$ = helper.padInner$;
|
||||||
|
if(inner$(window)[0].bowser.firefox || inner$(window)[0].bowser.modernIE){ // if it's a mozilla or IE
|
||||||
|
var evtType = "keypress";
|
||||||
|
}else{
|
||||||
|
var evtType = "keydown";
|
||||||
|
}
|
||||||
|
var e = inner$.Event(evtType);
|
||||||
|
e.keyCode = 13; // enter :|
|
||||||
|
inner$("#innerdocbody").trigger(e);
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue