Commit c6d13a96 authored by Marcel Klehr's avatar Marcel Klehr

Merge branch 'release/1.4.0'

parents 44f8b437 a7671a69
......@@ -15,3 +15,4 @@ npm-debug.log
.ep_initialized
*.crt
*.key
bin/etherpad-1.deb
......@@ -3,7 +3,7 @@ node_js:
- "0.10"
install:
- "bin/installDeps.sh"
- "export GIT_HASH=$(cat .git/HEAD | head -c 7)"
- "export GIT_HASH=$(git rev-parse --verify --short HEAD)"
before_script:
- "tests/frontend/travis/sauce_tunnel.sh"
script:
......
# 1.4
* NEW: Disable toolbar items through settings.json
* NEW: Internal stats/metrics engine
* NEW: Copy/Move Pad API functions
* NEW: getAttributeOnSelection method
* NEW: CSS function when an attribute is active on caret location
* NEW: Various new eejs blocks
* NEW: Ace afterEditHook
* NEW: Import hook to introduce alternative export methods
* NEW: preProcessDomLine allows Domline attributes to be processed before native attributes
* Fix: Allow for lighter author colors
* Fix: Improved randomness of session tokens
* Fix: Don't panic if an author2session/group2session no longer exists
* Fix: Gracefully fallback to related languages if chosen language is unavailable
* Fix: Various changeset/stability bugs
* Fix: Re-enable import buttons after failed import
* Fix: Allow browser tabs to be cycled when in editor
* Fix: Better Protocol detection
* Fix: padList API Fix
* Fix: Caret walking issue
* Fix: Better settings.json parsing
* Fix: Improved import/export handling
* Other: Various whitespace/code clean-up
* Other: .deb packaging creator
* Other: More API Documentation
* Other: Lots more translations
* Other: Support Node 0.11
# 1.3
* NEW: We now follow the semantic versioning scheme!
* NEW: Option to disable IP logging
......
......@@ -29,7 +29,7 @@ Etherpad works with node v0.8 and v0.10, only. (We don't support v0.6)
### Prebuilt windows package
This package works out of the box on any windows machine, but it's not very useful for developing purposes...
1. [Download the latest windows package](http://etherpad.org/downloads/etherpad-lite-win-1.2.91-7492fb18a4.zip)
1. [Download the latest windows package](http://etherpad.org/#download)
2. Extract the folder
Now, run `start.bat` and open <http://localhost:9001> in your browser. You like it? [Next steps](#next-steps).
......
#!/usr/bin/env bash
# IMPORTANT
# Protect agaisnt mispelling a var and rm -rf /
set -u
set -e
SRC=/tmp/etherpad-deb-src
DIST=/tmp/etherpad-deb-dist
SYSROOT=${SRC}/sysroot
DEBIAN=${SRC}/DEBIAN
rm -rf ${DIST}
mkdir -p ${DIST}/
rm -rf ${SRC}
rsync -a bin/deb-src/ ${SRC}/
mkdir -p ${SYSROOT}/opt/
rsync --exclude '.git' -a . ${SYSROOT}/opt/etherpad/ --delete
mkdir -p ${SYSROOT}/usr/share/doc
cp README.md ${SYSROOT}/usr/share/doc/etherpad
find ${SRC}/ -type d -exec chmod 0755 {} \;
find ${SRC}/ -type f -exec chmod go-w {} \;
chown -R root:root ${SRC}/
let SIZE=`du -s ${SYSROOT} | sed s'/\s\+.*//'`+8
pushd ${SYSROOT}/
tar czf ${DIST}/data.tar.gz [a-z]*
popd
sed s"/SIZE/${SIZE}/" -i ${DEBIAN}/control
pushd ${DEBIAN}
tar czf ${DIST}/control.tar.gz *
popd
pushd ${DIST}/
echo 2.0 > ./debian-binary
find ${DIST}/ -type d -exec chmod 0755 {} \;
find ${DIST}/ -type f -exec chmod go-w {} \;
chown -R root:root ${DIST}/
ar r ${DIST}/etherpad-1.deb debian-binary control.tar.gz data.tar.gz
popd
rsync -a ${DIST}/etherpad-1.deb ./
Package: etherpad
Version: 1.3
Section: base
Priority: optional
Architecture: i386
Installed-Size: SIZE
Depends:
Maintainer: John McLear <john@mclear.co.uk>
Description: Etherpad is a collaborative editor.
#!/bin/bash
# Start the services!
service etherpad start
echo "Give Etherpad about 3 minutes to install dependencies then visit http://localhost:9001 in your web browser"
echo "To stop etherpad type 'service etherpad stop', To restart type 'service etherpad restart'".
rm -f /tmp/etherpad.log /tmp/etherpad.err
#!/bin/bash
# Installs node if it isn't already installed
#
# Don't steamroll over a previously installed node version
# TODO provide a local version of node?
VER="0.10.4"
ARCH="x86"
if [ `arch | grep 64` ]
then
ARCH="x64"
fi
# TODO test version
if [ ! -f /usr/local/bin/node ]
then
pushd /tmp
wget -c "http://nodejs.org/dist/v${VER}/node-v${VER}-linux-${ARCH}.tar.gz"
rm -rf /tmp/node-v${VER}-linux-${ARCH}
tar xf node-v${VER}-linux-${ARCH}.tar.gz -C /tmp/
cp -a /tmp/node-v${VER}-linux-${ARCH}/* /usr/local/
fi
# Create Etherpad user
adduser --system etherpad
#!/bin/bash
# Stop the appserver:
service etherpad stop || true
description "etherpad"
start on started networking
stop on runlevel [!2345]
env EPHOME=/opt/etherpad
env EPLOGS=/var/log/etherpad
env EPUSER=etherpad
respawn
pre-start script
cd $EPHOME
mkdir $EPLOGS ||true
chown $EPUSER $EPLOGS ||true
chmod 0755 $EPLOGS ||true
chown -R $EPUSER $EPHOME/var ||true
$EPHOME/bin/installDeps.sh >> $EPLOGS/error.log || { stop; exit 1; }
end script
script
cd $EPHOME/
exec su -s /bin/sh -c 'exec "$0" "$@"' $EPUSER -- node node_modules/ep_etherpad-lite/node/server.js \
>> $EPLOGS/access.log \
2>> $EPLOGS/error.log
echo "Etherpad is running on http://localhost:9001 - To change settings edit /opt/etherpad/settings.json"
end script
......@@ -16,7 +16,7 @@ if [ $(uname) = "SunOS" ]; then
}
fi
#Is wget installed?
#Is curl installed?
hash curl > /dev/null 2>&1 || {
echo "Please install curl" >&2
exit 1
......@@ -44,8 +44,8 @@ fi
#check node version
NODE_VERSION=$(node --version)
NODE_V_MINOR=$(echo $NODE_VERSION | cut -d "." -f 1-2)
if [ ! $NODE_V_MINOR = "v0.8" ] && [ ! $NODE_V_MINOR = "v0.10" ]; then
echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.8.x or v0.10.x" >&2
if [ ! $NODE_V_MINOR = "v0.8" ] && [ ! $NODE_V_MINOR = "v0.10" ] && [ ! $NODE_V_MINOR = "v0.11" ]; then
echo "You're running a wrong version of node, you're using $NODE_VERSION, we need v0.8.x, v0.10.x or v0.11.x" >&2
exit 1
fi
......
......@@ -17,19 +17,19 @@ Installed Xvfb and PhantomJS
I installed Xvfb following (roughly) this guide: http://blog.martin-lyness.com/archives/installing-xvfb-on-ubuntu-9-10-karmic-koala
#sudo apt-get install xvfb
#sudo apt-get install xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic
#sudo apt-get install xvfb
#sudo apt-get install xfonts-100dpi xfonts-75dpi xfonts-scalable xfonts-cyrillic
Launched two instances of Xvfb directly from the terminal:
#Xvfb :0 -ac
#Xvfb :1 -ac
#Xvfb :0 -ac
#Xvfb :1 -ac
I installed PhantomJS following this guide: http://code.google.com/p/phantomjs/wiki/Installation
#sudo add-apt-repository ppa:jerome-etienne/neoip
#sudo apt-get update
#sudo apt-get install phantomjs
#sudo add-apt-repository ppa:jerome-etienne/neoip
#sudo apt-get update
#sudo apt-get install phantomjs
I created a small JavaScript file for PhatomJS to use to control the browser instances:
......
......@@ -3,7 +3,7 @@
# connect 500 instances to display :0
for i in {1..500}
do
echo $i
echo $i
echo "Displaying Some shit"
DISPLAY=:0 screen -d -m /home/phantomjs/bin/phantomjs loader.js http://10.0.0.55:9001/p/pad2 && sleep 2
done
......
......@@ -33,4 +33,7 @@ bin/installDeps.sh $* || exit 1
#Move to the node folder and start
echo "start..."
node node_modules/ep_etherpad-lite/node/server.js $*
SCRIPTPATH=`pwd -P`
node $SCRIPTPATH/node_modules/ep_etherpad-lite/node/server.js $*
......@@ -5,4 +5,6 @@
@include hooks_server-side
@include editorInfo
@include changeset_library
@include pluginfw
\ No newline at end of file
@include pluginfw
@include toolbar
@include editbar
\ No newline at end of file
# Editbar
srf/static/js/pad_editbar.js
## isEnabled()
## disable()
## toggleDropDown(dropdown, callback)
Shows the dropdown `div.popup` whose `id` equals `dropdown`.
## registerCommand(cmd, callback)
Register a handler for a specific command. Commands are fired if the corresponding button is clicked or the corresponding select is changed.
## registerAceCommand(cmd, callback)
Creates an ace callstack and calls the callback with an ace instance: `callback(cmd, ace)`.
Example:
```
toolbar.registerAceCommand("insertorderedlist", function (cmd, ace) {
ace.ace_doInsertOrderedList();
});
```
## registerDropdownCommand(cmd, dropdown)
Ties a `div.popup` where `id` equals `dropdown` to a `command` fired by clicking a button.
## triggerCommand(cmd[, item])
Triggers a command (optionally with some internal representation of the toolbar item that triggered it).
\ No newline at end of file
......@@ -39,6 +39,13 @@ Returns the `rep` object.
## editorInfo.ace_performDocumentApplyAttributesToCharRange(?)
## editorInfo.ace_setAttributeOnSelection(?)
## editorInfo.ace_toggleAttributeOnSelection(?)
## editorInfo.ace_getAttributeOnSelection(attribute)
Returns a boolean if an attribute exists on a selected range.
The attribute should be the string name of the attribute applied to the selection IE subscript
Example usage: Apply the activeButton Class to a button if an attribute is on a highlighted/selected caret position or range.
Example: `call.editorInfo.ace_getAttributeOnSelection("subscript");` // call here is the callstack from aceEditEvent.
See the ep_subscript plugin for an example of this function in action.
Notes: Does not work on first or last character of a line. Suffers from a race condition if called with aceEditEvent.
## editorInfo.ace_performSelectionChange(?)
## editorInfo.ace_doIndentOutdent(?)
## editorInfo.ace_doUndoRedo(?)
......
......@@ -10,6 +10,22 @@ nothing
This hook proxies the functionality of jQuery's `$(document).ready` event.
## aceDomLinePreProcessLineAttributes
Called from: src/static/js/domline.js
Things in context:
1. domline - The current DOM line being processed
2. cls - The class of the current block element (useful for styling)
This hook is called for elements in the DOM that have the "lineMarkerAttribute" set. You can add elements into this category with the aceRegisterBlockElements hook above. This hook is run BEFORE the numbered and ordered lists logic is applied.
The return value of this hook should have the following structure:
`{ preHtml: String, postHtml: String, processedMarker: Boolean }`
The preHtml and postHtml values will be added to the HTML display of the element, and if processedMarker is true, the engine won't try to process it any more.
## aceDomLineProcessLineAttributes
Called from: src/static/js/domline.js
......@@ -18,7 +34,7 @@ Things in context:
1. domline - The current DOM line being processed
2. cls - The class of the current block element (useful for styling)
This hook is called for elements in the DOM that have the "lineMarkerAttribute" set. You can add elements into this category with the aceRegisterBlockElements hook above.
This hook is called for elements in the DOM that have the "lineMarkerAttribute" set. You can add elements into this category with the aceRegisterBlockElements hook above. This hook is run AFTER the ordered and numbered lists logic is applied.
The return value of this hook should have the following structure:
......
......@@ -63,7 +63,46 @@ Things in context:
This hook gets called upon the rendering of an ejs template block. For any specific kind of block, you can change how that block gets rendered by modifying the content object passed in.
Have a look at `src/templates/pad.html` and `src/templates/timeslider.html` to see which blocks are available.
Available blocks in `pad.html` are:
* `htmlHead` - after `<html>` and immediately before the title tag
* `styles` - the style `<link>`s
* `body` - the contents of the body tag
* `editbarMenuLeft` - the left tool bar (consider using the toolbar controller instead of manually adding html here)
* `editbarMenuRight` - right tool bar
* `afterEditbar` - allows you to add stuff immediately after the toolbar
* `userlist` - the contents of the userlist dropdown
* `loading` - the intial loading message
* `mySettings` - the left column of the settings dropdown ("My view"); intended for adding checkboxes only
* `mySettings.dropdowns` - add your dropdown settings here
* `globalSettings` - the right column of the settings dropdown ("Global view")
* `importColumn` - import form
* `exportColumn` - export form
* `modals` - Contains all connectivity messages
* `embedPopup` - the embed dropdown
* `scripts` - Add your script tags here, if you really have to (consider use client-side hooks instead)
`timeslider.html` blocks:
* `timesliderStyles`
* `timesliderScripts`
* `timesliderBody`
* `timesliderTop`
* `timesliderEditbarRight`
* `modals`
`index.html` blocks:
* `indexWrapper` - contains the form for creating new pads
## padInitToolbar
Called from: src/node/hooks/express/specialpages.js
Things in context:
1. toolbar - the toolbar controller that will render the toolbar eventually
Here you can add custom toolbar items that will be available in the toolbar config in `settings.json`. For more about the toolbar controller see the API section.
## padCreate
Called from: src/node/db/Pad.js
......
......@@ -61,7 +61,7 @@ Portal submits content into new blog post
## Usage
### API version
The latest version is `1.2.7`
The latest version is `1.2.9`
The current version can be queried via /api.
......@@ -294,6 +294,65 @@ returns the text of a pad formatted as HTML
* `{code: 0, message:"ok", data: {html:"Welcome Text<br>More Text"}}`
* `{code: 1, message:"padID does not exist", data: null}`
#### setHTML(padID, html)
* API >= 1
sets the text of a pad based on HTML, HTML must be well formed. Malformed HTML will send a warning to the API log.
*Example returns:*
* `{code: 0, message:"ok", data: null}`
* `{code: 1, message:"padID does not exist", data: null}`
#### getAttributePool(padID)
* API >= 1.2.8
returns the attribute pool of a pad
*Example returns:*
* `{ "code":0,
"message":"ok",
"data": {
"pool":{
"numToAttrib":{
"0":["author","a.X4m8bBWJBZJnWGSh"],
"1":["author","a.TotfBPzov54ihMdH"],
"2":["author","a.StiblqrzgeNTbK05"],
"3":["bold","true"]
},
"attribToNum":{
"author,a.X4m8bBWJBZJnWGSh":0,
"author,a.TotfBPzov54ihMdH":1,
"author,a.StiblqrzgeNTbK05":2,
"bold,true":3
},
"nextNum":4
}
}
}`
* `{"code":1,"message":"padID does not exist","data":null}`
#### getRevisionChangeset(padID, [rev])
* API >= 1.2.8
get the changeset at a given revision, or last revision if 'rev' is not defined.
*Example returns:*
* `{ "code" : 0,
"message" : "ok",
"data" : "Z:1>6b|5+6b$Welcome to Etherpad!\n\nThis pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!\n\nGet involved with Etherpad at http://etherpad.org\n"
}`
* `{"code":1,"message":"padID does not exist","data":null}`
* `{"code":1,"message":"rev is higher than the head revision of the pad","data":null}`
#### createDiffHTML(padID, startRev, endRev)
* API >= 1.2.7
returns an object of diffs from 2 points in a pad
*Example returns:*
* `{"code":0,"message":"ok","data":{"html":"<style>\n.authora_HKIv23mEbachFYfH {background-color: #a979d9}\n.authora_n4gEeMLsv1GivNeh {background-color: #a9b5d9}\n.removed {text-decoration: line-through; -ms-filter:'progid:DXImageTransform.Microsoft.Alpha(Opacity=80)'; filter: alpha(opacity=80); opacity: 0.8; }\n</style>Welcome to Etherpad!<br><br>This pad text is synchronized as you type, so that everyone viewing this page sees the same text. This allows you to collaborate seamlessly on documents!<br><br>Get involved with Etherpad at <a href=\"http&#x3a;&#x2F;&#x2F;etherpad&#x2e;org\">http:&#x2F;&#x2F;etherpad.org</a><br><span class=\"authora_HKIv23mEbachFYfH\">aw</span><br><br>","authors":["a.HKIv23mEbachFYfH",""]}}`
* `{"code":4,"message":"no or wrong API Key","data":null}`
### Chat
#### getChatHistory(padID, [start, end])
* API >= 1.2.7
......@@ -365,6 +424,24 @@ returns the list of users that are currently editing this pad
deletes a pad
*Example returns:*
* `{code: 0, message:"ok", data: null}`
* `{code: 1, message:"padID does not exist", data: null}`
#### copyPad(sourceID, destinationID[, force=false])
* API >= 1.2.8
copies a pad with full history and chat. If force is true and the destination pad exists, it will be overwritten.
*Example returns:*
* `{code: 0, message:"ok", data: null}`
* `{code: 1, message:"padID does not exist", data: null}`
#### movePad(sourceID, destinationID[, force=false])
* API >= 1.2.8
moves a pad. If force is true and the destination pad exists, it will be overwritten.
*Example returns:*
* `{code: 0, message:"ok", data: null}`
* `{code: 1, message:"padID does not exist", data: null}`
......
# Toolbar controller
src/node/utils/toolbar.js
## button(opts)
* {Object} `opts`
* `command` - this command fill be fired on the editbar on click
* `localizationId` - will be set as `data-l10-id`
* `class` - here you can add additional classes to the button
Returns: {Button}
Example:
```
var orderedlist = toolbar.button({
command: "insertorderedlist",
localizationId: "pad.toolbar.ol.title",
class: "buttonicon buttonicon-insertorderedlist"
})
```
You can also create buttons with text:
```
var myButton = toolbar.button({
command: "myButton",
localizationId: "myPlugin.toolbar.myButton",
class: "buttontext"
})
```
## selectButton(opts)
* {Object} `opts`
* `id` - id of the menu item
* `selectId` - id of the select element
* `command` - this command fill be fired on the editbar on change
Returns: {SelectButton}
## SelectButton.addOption(value, text, attributes)
* {String} value - The value of this option
* {String} text - the label text used for this option
* {Object} attributes - any additional html attributes go here (e.g. `data-l10n-id`)
## registerButton(name, item)
* {String} name - used to reference the item in the toolbar config in settings.json
* {Button|SelectButton} item - the button to add
\ No newline at end of file
html {
border-top: solid green 5pt;
}
body.apidoc {
width: 60%;
min-width: 10cm;
......@@ -5,8 +9,7 @@ body.apidoc {
}
#header {
background-color: #5a5;
padding: 10px;
padding: 1pc 0;
color: #111;
}
......
......@@ -79,14 +79,14 @@ Here are descriptions of the operations, where capital letters are variables:
kept MUST be a newline, and the final newline of the document is allowed.
"*I" : Apply attribute I from the pool to the following +, =, |+, or |= command.
In other words, any number of * ops can come before a +, =, or | but not
between a | and the corresponding + or =.
between a | and the corresponding + or =.
If +, text is inserted having this attribute. If =, text is kept but with
the attribute applied as an attribute addition or removal.
Consecutive attributes must be sorted lexically by (key,value) with key
and value taken as strings. It's illegal to have duplicate keys
for (key,value) pairs that apply to the same text. It's illegal to
have an empty value for a key in the case of an insertion (+), the
pair should just be omitted.
the attribute applied as an attribute addition or removal.
Consecutive attributes must be sorted lexically by (key,value) with key
and value taken as strings. It's illegal to have duplicate keys
for (key,value) pairs that apply to the same text. It's illegal to
have an empty value for a key in the case of an insertion (+), the
pair should just be omitted.
Characters from the source text that aren't accounted for are assumed to be kept
with the same attributes.
......
@include documentation
@include stats
@include localization
@include custom_static
@include api/api
......
# Statistics
Etherpad keeps track of the goings-on inside the edit machinery. If you'd like to have a look at this, just point your browser to `/stats`.
We currently measure:
- totalUsers (counter)
- connects (meter)
- disconnects (meter)
- pendingEdits (counter)
- edits (timer)
- failedChangesets (meter)
- httpRequests (timer)
- http500 (meter)
- memoryUsage (gauge)
Under the hood, we are happy to rely on [measured](https://github.com/felixge/node-measured) for all our metrics needs.
To modify or simply access our stats in your plugin, simply `require('ep_etherpad-lite/stats')` which is a `measured.Collection`.
\ No newline at end of file
......@@ -103,6 +103,25 @@
// restrict socket.io transport methods
"socketTransportProtocols" : ["xhr-polling", "jsonp-polling", "htmlfile"],
/* The toolbar buttons configuration.
"toolbar": {
"left": [
["bold", "italic", "underline", "strikethrough"],
["orderedlist", "unorderedlist", "indent", "outdent"],
["undo", "redo"],
["clearauthorship"]
],
"right": [
["importexport", "timeslider", "savedrevision"],
["settings", "embed"],