Typos and minor fixes in bin, doc, and root

pull/3223/head
HairyFotr 2017-09-14 13:33:27 +02:00
parent 457fdaa360
commit c7548450c0
No known key found for this signature in database
GPG Key ID: E6EC696442BA5B10
27 changed files with 175 additions and 174 deletions

1
.gitignore vendored
View File

@ -18,3 +18,4 @@ npm-debug.log
*.key *.key
bin/etherpad-1.deb bin/etherpad-1.deb
credentials.json credentials.json
out/

View File

@ -6,7 +6,7 @@
* Please be polite, we all are humans and problems can occur. * Please be polite, we all are humans and problems can occur.
* Please add as much information as possible, for example * Please add as much information as possible, for example
* client os(s) and version(s) * client os(s) and version(s)
* browser(s) and version(s), is the problem reproduceable on different clients * browser(s) and version(s), is the problem reproducible on different clients
* special environments like firewalls or antivirus * special environments like firewalls or antivirus
* host os and version * host os and version
* npm and nodejs version * npm and nodejs version
@ -49,7 +49,7 @@ Also, keep it maintainable. We don't wanna end up as the monster Etherpad was!
* Make small pull requests that are easy to review but make sure they do add value by themselves / individually * Make small pull requests that are easy to review but make sure they do add value by themselves / individually
## Coding style ## Coding style
* Do write comments. (You don't have to comment every line, but if you come up with something thats a bit complex/weird, just leave a comment. Bear in mind that you will probably leave the project at some point and that other people will read your code. Undocumented huge amounts of code are worthless!) * Do write comments. (You don't have to comment every line, but if you come up with something that's a bit complex/weird, just leave a comment. Bear in mind that you will probably leave the project at some point and that other people will read your code. Undocumented huge amounts of code are worthless!)
* Never ever use tabs * Never ever use tabs
* Indentation: JS/CSS: 2 spaces; HTML: 4 spaces * Indentation: JS/CSS: 2 spaces; HTML: 4 spaces
* Don't overengineer. Don't try to solve any possible problem in one step, but try to solve problems as easy as possible and improve the solution over time! * Don't overengineer. Don't try to solve any possible problem in one step, but try to solve problems as easy as possible and improve the solution over time!
@ -79,7 +79,7 @@ see git flow http://nvie.com/posts/a-successful-git-branching-model/
### feature branches (in your own repos) ### feature branches (in your own repos)
* these are the branches where you develop your features in * these are the branches where you develop your features in
* If its ready to go out, it will be merged into develop * If it's ready to go out, it will be merged into develop
Over the time we pull features from feature branches into the develop branch. Every month we pull from develop into master. Bugs in master get fixed in hotfix branches. These branches will get merged into master AND develop. There should never be commits in master that aren't in develop Over the time we pull features from feature branches into the develop branch. Every month we pull from develop into master. Bugs in master get fixed in hotfix branches. These branches will get merged into master AND develop. There should never be commits in master that aren't in develop

View File

@ -3,7 +3,7 @@ outdoc_files = $(addprefix out/,$(doc_sources:.md=.html))
docassets = $(addprefix out/,$(wildcard doc/assets/*)) docassets = $(addprefix out/,$(wildcard doc/assets/*))
VERSION = $(shell node -e "console.log( require('./src/package.json').version )") VERSION = $(shell node -e "console.log( require('./src/package.json').version )")
UNAME := $(shell uname -s) UNAME := $(shell uname -s)
docs: $(outdoc_files) $(docassets) docs: $(outdoc_files) $(docassets)

View File

@ -11,7 +11,7 @@ that allows your web application to manage pads, users and groups. It is recomme
There is also a [jQuery plugin](https://github.com/ether/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website. There is also a [jQuery plugin](https://github.com/ether/etherpad-lite-jquery-plugin) that helps you to embed Pads into your website.
There's also a full-featured plugin framework, allowing you to easily add your own features. By default your Etherpad is rather sparse and because Etherpad takes a lot of it's inspiration from Wordpress plugins are really easy to install and update. Once you have Etherpad installed you should visit the plugin page and take control. There's also a full-featured plugin framework, allowing you to easily add your own features. By default your Etherpad is rather sparse and because Etherpad takes a lot of its inspiration from WordPress, plugins are really easy to install and update. Once you have Etherpad installed you should visit the plugin page and take control.
Finally, Etherpad comes with translations into most languages! Users are automatically delivered the correct language for their local settings. Finally, Etherpad comes with translations into most languages! Users are automatically delivered the correct language for their local settings.
@ -35,7 +35,7 @@ This package works out of the box on any windows machine, but it's not very usef
Now, run `start.bat` and open <http://localhost:9001> in your browser. You like it? [Next steps](#next-steps). Now, run `start.bat` and open <http://localhost:9001> in your browser. You like it? [Next steps](#next-steps).
### Fancy install ### Fancy install
You'll need [node.js](http://nodejs.org) and (optionally, though recommended) git. You'll need [node.js](https://nodejs.org) and (optionally, though recommended) git.
1. Grab the source, either 1. Grab the source, either
- download <https://github.com/ether/etherpad-lite/zipball/master> - download <https://github.com/ether/etherpad-lite/zipball/master>
@ -60,7 +60,7 @@ You'll need gzip, git, curl, libssl develop libraries, python and gcc.
- *For Fedora/CentOS*: `yum install gzip git curl python openssl-devel && yum groupinstall "Development Tools"` - *For Fedora/CentOS*: `yum install gzip git curl python openssl-devel && yum groupinstall "Development Tools"`
- *For FreeBSD*: `portinstall node, npm, curl, git (optional)` - *For FreeBSD*: `portinstall node, npm, curl, git (optional)`
Additionally, you'll need [node.js](http://nodejs.org) installed, Ideally the latest stable version, we recommend installing/compiling nodejs from source (avoiding apt). Additionally, you'll need [node.js](https://nodejs.org) installed, Ideally the latest stable version, we recommend installing/compiling nodejs from source (avoiding apt).
**As any user (we recommend creating a separate user called etherpad):** **As any user (we recommend creating a separate user called etherpad):**
@ -92,9 +92,9 @@ Documentation can be found in `docs/`.
# Development # Development
## Things you should know ## Things you should know
Understand [git](https://training.github.com/) and watch this [video on getting started with Etherpad Development](http://youtu.be/67-Q26YH97E). Understand [git](https://training.github.com/) and watch this [video on getting started with Etherpad Development](https://youtu.be/67-Q26YH97E).
If you're new to node.js, start with Ryan Dahl's [Introduction to Node.js](http://youtu.be/jo_B4LTHi3I). If you're new to node.js, start with Ryan Dahl's [Introduction to Node.js](https://youtu.be/jo_B4LTHi3I).
You can debug Etherpad using `bin/debugRun.sh`. You can debug Etherpad using `bin/debugRun.sh`.
@ -108,7 +108,7 @@ Look at the [TODO list](https://github.com/ether/etherpad-lite/wiki/TODO) and ou
Also, and most importantly, read our [**Developer Guidelines**](https://github.com/ether/etherpad-lite/blob/master/CONTRIBUTING.md), really! Also, and most importantly, read our [**Developer Guidelines**](https://github.com/ether/etherpad-lite/blob/master/CONTRIBUTING.md), really!
# Get in touch # Get in touch
Join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) and make some noise on our busy freenode irc channel [#etherpad-lite-dev](http://webchat.freenode.net?channels=#etherpad-lite-dev)! Join the [mailinglist](https://groups.google.com/group/etherpad-lite-dev) and make some noise on our busy freenode irc channel [#etherpad-lite-dev](https://webchat.freenode.net?channels=#etherpad-lite-dev)!
# Modules created for this project # Modules created for this project
@ -117,7 +117,7 @@ Join the [mailinglist](http://groups.google.com/group/etherpad-lite-dev) and mak
* [async-stacktrace](https://github.com/Pita/async-stacktrace) "Improves node.js stacktraces and makes it easier to handle errors" * [async-stacktrace](https://github.com/Pita/async-stacktrace) "Improves node.js stacktraces and makes it easier to handle errors"
# Donate! # Donate!
* [Flattr](http://flattr.com/thing/71378/Etherpad-Foundation) * [Flattr](https://flattr.com/thing/71378/Etherpad-Foundation)
* Paypal - Press the donate button on [etherpad.org](http://etherpad.org) * Paypal - Press the donate button on [etherpad.org](http://etherpad.org)
* [Bitcoin](https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a) * [Bitcoin](https://coinbase.com/checkouts/1e572bf8a82e4663499f7f1f66c2d15a)

View File

@ -1,7 +1,7 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# IMPORTANT # IMPORTANT
# Protect agaisnt mispelling a var and rm -rf / # Protect against misspelling a var and rm -rf /
set -u set -u
set -e set -e

View File

@ -10,7 +10,7 @@ if(process.argv.length != 3)
//get the padID //get the padID
var padId = process.argv[2]; var padId = process.argv[2];
//initalize the variables //initialize the variables
var db, settings, padManager; var db, settings, padManager;
var npm = require("../src/node_modules/npm"); var npm = require("../src/node_modules/npm");
var async = require("../src/node_modules/async"); var async = require("../src/node_modules/async");
@ -29,7 +29,7 @@ async.series([
settings = require('../src/node/utils/Settings'); settings = require('../src/node/utils/Settings');
db = require('../src/node/db/DB'); db = require('../src/node/db/DB');
//intallize the database //initialize the database
db.init(callback); db.init(callback);
}, },
//get the pad //get the pad
@ -54,7 +54,7 @@ async.series([
}, },
function (callback) function (callback)
{ {
//create an array with key kevisions //create an array with key revisions
//key revisions always save the full pad atext //key revisions always save the full pad atext
var head = pad.getHeadRevisionNumber(); var head = pad.getHeadRevisionNumber();
var keyRevisions = []; var keyRevisions = [];
@ -99,7 +99,7 @@ async.series([
process.exit(1); process.exit(1);
} }
//check if there is a atext in the keyRevisions //check if there is an atext in the keyRevisions
if(revisions[keyRev] === undefined || revisions[keyRev].meta === undefined || revisions[keyRev].meta.atext === undefined) if(revisions[keyRev] === undefined || revisions[keyRev].meta === undefined || revisions[keyRev].meta.atext === undefined)
{ {
console.error("No atext in key revision " + keyRev); console.error("No atext in key revision " + keyRev);

View File

@ -16,7 +16,7 @@ do
fi fi
done done
#Stop the script if its started as root #Stop the script if it's started as root
if [ "$(id -u)" -eq 0 ] && [ $ignoreRoot -eq 0 ]; then if [ "$(id -u)" -eq 0 ] && [ $ignoreRoot -eq 0 ]; then
echo "You shouldn't start Etherpad as root!" echo "You shouldn't start Etherpad as root!"
echo "Please type 'Etherpad rocks my socks' or supply the '--root' argument if you still want to start it as root" echo "Please type 'Etherpad rocks my socks' or supply the '--root' argument if you still want to start it as root"
@ -31,7 +31,7 @@ fi
#Clean the current environment #Clean the current environment
rm -rf src/node_modules rm -rf src/node_modules
#Prepare the enviroment #Prepare the environment
bin/installDeps.sh $* || exit 1 bin/installDeps.sh $* || exit 1
#Move to the node folder and start #Move to the node folder and start

View File

@ -22,25 +22,25 @@ TMP_DIR="/tmp/"
echo "WARNING: You can only run this script if your github api token is allowed to create and merge branches on $ETHER_REPO and $ETHER_WEB_REPO." echo "WARNING: You can only run this script if your github api token is allowed to create and merge branches on $ETHER_REPO and $ETHER_WEB_REPO."
echo "This script automatically changes the version number in package.json and adds a text to CHANGELOG.md." echo "This script automatically changes the version number in package.json and adds a text to CHANGELOG.md."
echo "When you use this script you should be in the branch that you want to release (develop probably) on latest version. Any changes that are currently not commited will be commited." echo "When you use this script you should be in the branch that you want to release (develop probably) on latest version. Any changes that are currently not committed will be committed."
echo "-----" echo "-----"
# get the latest version # Get the latest version
LATEST_GIT_TAG=$(git tag | tail -n 1) LATEST_GIT_TAG=$(git tag | tail -n 1)
# current environment # Current environment
echo "Current environment: " echo "Current environment: "
echo "- branch: $(git branch | grep '* ')" echo "- branch: $(git branch | grep '* ')"
echo "- last commit date: $(git show --quiet --pretty=format:%ad)" echo "- last commit date: $(git show --quiet --pretty=format:%ad)"
echo "- current version: $LATEST_GIT_TAG" echo "- current version: $LATEST_GIT_TAG"
echo "- temp dir: $TMP_DIR" echo "- temp dir: $TMP_DIR"
# get new version number # Get new version number
# format: x.x.x # format: x.x.x
echo -n "Enter new version (x.x.x): " echo -n "Enter new version (x.x.x): "
read VERSION read VERSION
# get the message for the changelogs # Get the message for the changelogs
read -p "Enter new changelog entries (press enter): " read -p "Enter new changelog entries (press enter): "
tmp=$(mktemp) tmp=$(mktemp)
"${EDITOR:-vi}" $tmp "${EDITOR:-vi}" $tmp
@ -49,7 +49,7 @@ echo "$changelogText"
rm $tmp rm $tmp
if [ "$changelogText" != "" ]; then if [ "$changelogText" != "" ]; then
changelogText="# $VERSION\n$changelogText" changelogText="# $VERSION\n$changelogText"
fi fi
# get the token for the github api # get the token for the github api
@ -57,114 +57,114 @@ echo -n "Enter your github api token: "
read API_TOKEN read API_TOKEN
function check_api_token { function check_api_token {
echo "Checking if github api token is valid..." echo "Checking if github api token is valid..."
CURL_RESPONSE=$(curl --silent -i https://api.github.com/user?access_token=$API_TOKEN | iconv -f utf8) CURL_RESPONSE=$(curl --silent -i https://api.github.com/user?access_token=$API_TOKEN | iconv -f utf8)
HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/')
[[ $HTTP_STATUS != "200" ]] && echo "Aborting: Invalid github api token" && exit 1 [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Invalid github api token" && exit 1
} }
function modify_files { function modify_files {
# Add changelog text to first line of CHANGELOG.md # Add changelog text to first line of CHANGELOG.md
sed -i "1s/^/${changelogText}\n/" CHANGELOG.md sed -i "1s/^/${changelogText}\n/" CHANGELOG.md
# Replace version number of etherpad in package.json # Replace version number of etherpad in package.json
sed -i -r "s/(\"version\"[ ]*: \").*(\")/\1$VERSION\2/" src/package.json sed -i -r "s/(\"version\"[ ]*: \").*(\")/\1$VERSION\2/" src/package.json
} }
function create_release_branch { function create_release_branch {
echo "Creating new release branch..." echo "Creating new release branch..."
git rev-parse --verify release/$VERSION 2>/dev/null git rev-parse --verify release/$VERSION 2>/dev/null
if [ $? == 0 ]; then if [ $? == 0 ]; then
echo "Aborting: Release branch already present" echo "Aborting: Release branch already present"
exit 1 exit 1
fi fi
git checkout -b release/$VERSION git checkout -b release/$VERSION
[[ $? != 0 ]] && echo "Aborting: Error creating relase branch" && exit 1 [[ $? != 0 ]] && echo "Aborting: Error creating release branch" && exit 1
echo "Commiting CHANGELOG.md and package.json" echo "Committing CHANGELOG.md and package.json"
git add CHANGELOG.md git add CHANGELOG.md
git add src/package.json git add src/package.json
git commit -m "Release version $VERSION" git commit -m "Release version $VERSION"
echo "Pushing release branch to github..." echo "Pushing release branch to github..."
git push -u $ETHER_REPO release/$VERSION git push -u $ETHER_REPO release/$VERSION
[[ $? != 0 ]] && echo "Aborting: Error pushing release branch to github" && exit 1 [[ $? != 0 ]] && echo "Aborting: Error pushing release branch to github" && exit 1
} }
function merge_release_branch { function merge_release_branch {
echo "Merging release to master branch on github..." echo "Merging release to master branch on github..."
API_JSON=$(printf '{"base": "master","head": "release/%s","commit_message": "Merge new release into master branch!"}' $VERSION) API_JSON=$(printf '{"base": "master","head": "release/%s","commit_message": "Merge new release into master branch!"}' $VERSION)
CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/etherpad-lite/merges?access_token=$API_TOKEN | iconv -f utf8) CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/etherpad-lite/merges?access_token=$API_TOKEN | iconv -f utf8)
echo $CURL_RESPONSE echo $CURL_RESPONSE
HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/')
[[ $HTTP_STATUS != "200" ]] && echo "Aborting: Error merging release branch on github" && exit 1 [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Error merging release branch on github" && exit 1
} }
function create_builds { function create_builds {
echo "Cloning etherpad-lite repo and ether.github.com repo..." echo "Cloning etherpad-lite repo and ether.github.com repo..."
cd $TMP_DIR cd $TMP_DIR
rm -rf etherpad-lite ether.github.com rm -rf etherpad-lite ether.github.com
git clone $ETHER_REPO --branch master git clone $ETHER_REPO --branch master
git clone $ETHER_WEB_REPO git clone $ETHER_WEB_REPO
echo "Creating windows build..." echo "Creating windows build..."
cd etherpad-lite cd etherpad-lite
bin/buildForWindows.sh bin/buildForWindows.sh
[[ $? != 0 ]] && echo "Aborting: Error creating build for windows" && exit 1 [[ $? != 0 ]] && echo "Aborting: Error creating build for windows" && exit 1
echo "Creating docs..." echo "Creating docs..."
make docs make docs
[[ $? != 0 ]] && echo "Aborting: Error generating docs" && exit 1 [[ $? != 0 ]] && echo "Aborting: Error generating docs" && exit 1
} }
function push_builds { function push_builds {
cd $TMP_DIR/etherpad-lite/ cd $TMP_DIR/etherpad-lite/
echo "Copying windows build and docs to website repo..." echo "Copying windows build and docs to website repo..."
GIT_SHA=$(git rev-parse HEAD | cut -c1-10) GIT_SHA=$(git rev-parse HEAD | cut -c1-10)
mv etherpad-lite-win.zip $TMP_DIR/ether.github.com/downloads/etherpad-lite-win-$VERSION-$GIT_SHA.zip mv etherpad-lite-win.zip $TMP_DIR/ether.github.com/downloads/etherpad-lite-win-$VERSION-$GIT_SHA.zip
mv out/doc $TMP_DIR/ether.github.com/doc/v$VERSION mv out/doc $TMP_DIR/ether.github.com/doc/v$VERSION
cd $TMP_DIR/ether.github.com/ cd $TMP_DIR/ether.github.com/
sed -i "s/etherpad-lite-win.*\.zip/etherpad-lite-win-$VERSION-$GIT_SHA.zip/" index.html sed -i "s/etherpad-lite-win.*\.zip/etherpad-lite-win-$VERSION-$GIT_SHA.zip/" index.html
sed -i "s/$LATEST_GIT_TAG/$VERSION/g" index.html sed -i "s/$LATEST_GIT_TAG/$VERSION/g" index.html
git checkout -b release_$VERSION git checkout -b release_$VERSION
[[ $? != 0 ]] && echo "Aborting: Error creating new release branch" && exit 1 [[ $? != 0 ]] && echo "Aborting: Error creating new release branch" && exit 1
git add doc/ git add doc/
git add downloads/ git add downloads/
git commit -a -m "Release version $VERSION" git commit -a -m "Release version $VERSION"
git push -u $ETHER_WEB_REPO release_$VERSION git push -u $ETHER_WEB_REPO release_$VERSION
[[ $? != 0 ]] && echo "Aborting: Error pushing release branch to github" && exit 1 [[ $? != 0 ]] && echo "Aborting: Error pushing release branch to github" && exit 1
} }
function merge_web_branch { function merge_web_branch {
echo "Merging release to master branch on github..." echo "Merging release to master branch on github..."
API_JSON=$(printf '{"base": "master","head": "release_%s","commit_message": "Release version %s"}' $VERSION $VERSION) API_JSON=$(printf '{"base": "master","head": "release_%s","commit_message": "Release version %s"}' $VERSION $VERSION)
CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/ether.github.com/merges?access_token=$API_TOKEN | iconv -f utf8) CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/ether.github.com/merges?access_token=$API_TOKEN | iconv -f utf8)
echo $CURL_RESPONSE echo $CURL_RESPONSE
HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/')
[[ $HTTP_STATUS != "200" ]] && echo "Aborting: Error merging release branch" && exit 1 [[ $HTTP_STATUS != "200" ]] && echo "Aborting: Error merging release branch" && exit 1
} }
function publish_release { function publish_release {
echo -n "Do you want to publish a new release on github (y/n)? " echo -n "Do you want to publish a new release on github (y/n)? "
read PUBLISH_RELEASE read PUBLISH_RELEASE
if [ $PUBLISH_RELEASE = "y" ]; then if [ $PUBLISH_RELEASE = "y" ]; then
# create a new release on github # create a new release on github
API_JSON=$(printf '{"tag_name": "%s","target_commitish": "master","name": "Release %s","body": "%s","draft": false,"prerelease": false}' $VERSION $VERSION $changelogText) API_JSON=$(printf '{"tag_name": "%s","target_commitish": "master","name": "Release %s","body": "%s","draft": false,"prerelease": false}' $VERSION $VERSION $changelogText)
CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/etherpad-lite/releases?access_token=$API_TOKEN | iconv -f utf8) CURL_RESPONSE=$(curl --silent -i -N --data "$API_JSON" https://api.github.com/repos/ether/etherpad-lite/releases?access_token=$API_TOKEN | iconv -f utf8)
HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/') HTTP_STATUS=$(echo $CURL_RESPONSE | head -1 | sed -r 's/.* ([0-9]{3}) .*/\1/')
[[ $HTTP_STATUS != "201" ]] && echo "Aborting: Error publishing release on github" && exit 1 [[ $HTTP_STATUS != "201" ]] && echo "Aborting: Error publishing release on github" && exit 1
else else
echo "No release published on github!" echo "No release published on github!"
fi fi
} }
function todo_notification { function todo_notification {
echo "Release procedure was successful, but you have to do some steps manually:" echo "Release procedure was successful, but you have to do some steps manually:"
echo "- Update the wiki at https://github.com/ether/etherpad-lite/wiki" echo "- Update the wiki at https://github.com/ether/etherpad-lite/wiki"
echo "- Create a pull request on github to merge the master branch back to develop" echo "- Create a pull request on github to merge the master branch back to develop"
echo "- Announce the new release on the mailing list, blog.etherpad.org and Twitter" echo "- Announce the new release on the mailing list, blog.etherpad.org and Twitter"
} }
# call functions # Call functions
check_api_token check_api_token
modify_files modify_files
create_release_branch create_release_branch

View File

@ -8,7 +8,7 @@ if [ -d "../bin" ]; then
cd "../" cd "../"
fi fi
#prepare the enviroment #Prepare the environment
bin/installDeps.sh || exit 1 bin/installDeps.sh || exit 1
hash node-inspector > /dev/null 2>&1 || { hash node-inspector > /dev/null 2>&1 || {
@ -20,9 +20,9 @@ hash node-inspector > /dev/null 2>&1 || {
node-inspector & node-inspector &
echo "If you are new to node-inspector, take a look at this video: http://youtu.be/AOnK3NVnxL8" echo "If you are new to node-inspector, take a look at this video: https://youtu.be/AOnK3NVnxL8"
node --debug node_modules/ep_etherpad-lite/node/server.js $* node --debug node_modules/ep_etherpad-lite/node/server.js $*
#kill node-inspector before ending #Kill node-inspector before ending
kill $! kill $!

View File

@ -37,12 +37,12 @@ async.series([
db = require('../src/node/db/DB'); db = require('../src/node/db/DB');
callback(); callback();
}, },
// intallize the database // initialize the database
function (callback) function (callback)
{ {
db.init(callback); db.init(callback);
}, },
// delete the pad and it's links // delete the pad and its links
function (callback) function (callback)
{ {
padManager = require('../src/node/db/PadManager'); padManager = require('../src/node/db/PadManager');

View File

@ -96,7 +96,7 @@ function doJSON(input, filename, cb) {
// a list: starting with list_start, ending with list_end, // a list: starting with list_start, ending with list_end,
// maybe containing other nested lists in each item. // maybe containing other nested lists in each item.
// //
// If one of these isnt' found, then anything that comes between // If one of these isn't found, then anything that comes between
// here and the next heading should be parsed as the desc. // here and the next heading should be parsed as the desc.
var stability var stability
if (state === 'AFTERHEADING') { if (state === 'AFTERHEADING') {
@ -198,7 +198,7 @@ function processList(section) {
var current; var current;
var stack = []; var stack = [];
// for now, *just* build the heirarchical list // for now, *just* build the hierarchical list
list.forEach(function(tok) { list.forEach(function(tok) {
var type = tok.type; var type = tok.type;
if (type === 'space') return; if (type === 'space') return;

View File

@ -1,5 +1,5 @@
/* /*
This is a debug tool. It helps to extract all datas of a pad and move it from an productive enviroment and to a develop enviroment to reproduce bugs there. It outputs a dirtydb file This is a debug tool. It helps to extract all datas of a pad and move it from an productive environment and to a develop environment to reproduce bugs there. It outputs a dirtydb file
*/ */
if(process.argv.length != 3) if(process.argv.length != 3)
@ -38,7 +38,7 @@ async.series([
dirty = require("../node_modules/ep_etherpad-lite/node_modules/ueberDB/node_modules/dirty")(padId + ".db"); dirty = require("../node_modules/ep_etherpad-lite/node_modules/ueberDB/node_modules/dirty")(padId + ".db");
callback(); callback();
}, },
//intallize the database //initialize the database
function (callback) function (callback)
{ {
db.init(callback); db.init(callback);
@ -85,7 +85,7 @@ async.series([
if(err) { callback(err); return} if(err) { callback(err); return}
if(dbvalue && typeof dbvalue != 'object'){ if(dbvalue && typeof dbvalue != 'object'){
dbvalue=JSON.parse(dbvalue); // if its not json then parse it as json dbvalue=JSON.parse(dbvalue); // if it's not json then parse it as json
} }
dirty.set(dbkey, dbvalue, callback); dirty.set(dbkey, dbvalue, callback);
@ -105,5 +105,5 @@ async.series([
//get the pad object //get the pad object
//get all revisions of this pad //get all revisions of this pad
//get all authors related to this pad //get all authors related to this pad
//get the readonly link releated to this pad //get the readonly link related to this pad
//get the chat entrys releated to this pad //get the chat entries related to this pad

View File

@ -30,7 +30,7 @@ require("ep_etherpad-lite/node_modules/npm").load({}, function(er,npm) {
//there was an error while initializing the database, output it and stop //there was an error while initializing the database, output it and stop
if(err) if(err)
{ {
console.error("ERROR: Problem while initalizing the database"); console.error("ERROR: Problem while initializing the database");
console.error(err.stack ? err.stack : err); console.error(err.stack ? err.stack : err);
process.exit(1); process.exit(1);
} }

View File

@ -23,19 +23,19 @@ hash curl > /dev/null 2>&1 || {
} }
#Is node installed? #Is node installed?
#not checking io.js, default installation creates a symbolic link to node #Not checking io.js, default installation creates a symbolic link to node
hash node > /dev/null 2>&1 || { hash node > /dev/null 2>&1 || {
echo "Please install node.js ( http://nodejs.org )" >&2 echo "Please install node.js ( https://nodejs.org )" >&2
exit 1 exit 1
} }
#Is npm installed? #Is npm installed?
hash npm > /dev/null 2>&1 || { hash npm > /dev/null 2>&1 || {
echo "Please install npm ( http://npmjs.org )" >&2 echo "Please install npm ( https://npmjs.org )" >&2
exit 1 exit 1
} }
#check npm version #Check npm version
NPM_VERSION=$(npm --version) NPM_VERSION=$(npm --version)
NPM_MAIN_VERSION=$(echo $NPM_VERSION | cut -d "." -f 1) NPM_MAIN_VERSION=$(echo $NPM_VERSION | cut -d "." -f 1)
if [ $(echo $NPM_MAIN_VERSION) = "0" ]; then if [ $(echo $NPM_MAIN_VERSION) = "0" ]; then
@ -43,7 +43,7 @@ if [ $(echo $NPM_MAIN_VERSION) = "0" ]; then
exit 1 exit 1
fi 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) NODE_V_MAIN=$(echo $NODE_VERSION | cut -d "." -f 1)
@ -61,7 +61,7 @@ for arg in $*; do
a=$arg a=$arg
done done
#Does a $settings exist? if no copy the template #Does a $settings exist? if not copy the template
if [ ! -f $settings ]; then if [ ! -f $settings ]; then
echo "Copy the settings template to $settings..." echo "Copy the settings template to $settings..."
cp settings.json.template $settings || exit 1 cp settings.json.template $settings || exit 1

View File

@ -1,10 +1,10 @@
@echo off @echo off
:: change directory to etherpad-lite root :: Change directory to etherpad-lite root
cd /D "%~dp0\.." 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 ( https://nodejs.org )" && 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.

View File

@ -39,7 +39,7 @@ async.series([
db = require('../src/node/db/DB'); db = require('../src/node/db/DB');
callback(); callback();
}, },
//intallize the database //initialize the database
function (callback) function (callback)
{ {
db.init(callback); db.init(callback);
@ -101,6 +101,6 @@ async.series([
//get the pad object //get the pad object
//get all revisions of this pad //get all revisions of this pad
//get all authors related to this pad //get all authors related to this pad
//get the readonly link releated to this pad //get the readonly link related to this pad
//get the chat entrys releated to this pad //get the chat entries related to this pad
//remove all keys from database and insert them again //remove all keys from database and insert them again

View File

@ -16,19 +16,19 @@ do
fi fi
done done
#Stop the script if its started as root #Stop the script if it's started as root
if [ "$(id -u)" -eq 0 ] && [ $ignoreRoot -eq 0 ]; then if [ "$(id -u)" -eq 0 ] && [ $ignoreRoot -eq 0 ]; then
echo "You shouldn't start Etherpad as root!" echo "You shouldn't start Etherpad as root!"
echo "Please type 'Etherpad rocks my socks' or supply the '--root' argument if you still want to start it as root" echo "Please type 'Etherpad rocks my socks' or supply the '--root' argument if you still want to start it as root"
read rocks read rocks
if [ ! "$rocks" == "Etherpad rocks my socks" ] if [ ! "$rocks" == "Etherpad rocks my socks" ]
then then
echo "Your input was incorrect" echo "Your input was incorrect"
exit 1 exit 1
fi fi
fi fi
#prepare the enviroment #Prepare the environment
bin/installDeps.sh $* || exit 1 bin/installDeps.sh $* || exit 1
#Move to the node folder and start #Move to the node folder and start

View File

@ -6,10 +6,10 @@
# 0 silent # 0 silent
# 1 email # 1 email
ERROR_HANDLING=0 ERROR_HANDLING=0
# Your email address which should recieve the error messages # Your email address which should receive the error messages
EMAIL_ADDRESS="no-reply@example.com" EMAIL_ADDRESS="no-reply@example.com"
# Sets the minimun amount of time betweens the sending of error emails. # Sets the minimum amount of time between the sending of error emails.
# This ensures you not get spamed while a endless reboot loop # This ensures you do not get spammed during an endless reboot loop
# It's the time in seconds # It's the time in seconds
TIME_BETWEEN_EMAILS=600 # 10 minutes TIME_BETWEEN_EMAILS=600 # 10 minutes
@ -26,7 +26,7 @@ if [ -d "../bin" ]; then
cd "../" cd "../"
fi fi
#check if a logfile parameter is set #Check if a logfile parameter is set
if [ -z "${LOG}" ]; then if [ -z "${LOG}" ]; then
echo "Set a logfile as the first parameter" echo "Set a logfile as the first parameter"
exit 1 exit 1
@ -35,18 +35,18 @@ fi
shift shift
while [ 1 ] while [ 1 ]
do do
#try to touch the file if it doesn't exist #Try to touch the file if it doesn't exist
if [ ! -f ${LOG} ]; then if [ ! -f ${LOG} ]; then
touch ${LOG} || ( echo "Logfile '${LOG}' is not writeable" && exit 1 ) touch ${LOG} || ( echo "Logfile '${LOG}' is not writeable" && exit 1 )
fi fi
#check if the file is writeable #Check if the file is writeable
if [ ! -w ${LOG} ]; then if [ ! -w ${LOG} ]; then
echo "Logfile '${LOG}' is not writeable" echo "Logfile '${LOG}' is not writeable"
exit 1 exit 1
fi fi
#start the application #Start the application
bin/run.sh $@ >>${LOG} 2>>${LOG} bin/run.sh $@ >>${LOG} 2>>${LOG}
#Send email #Send email

View File

@ -4,15 +4,15 @@
"Z:z>1|2=m=b*0|1+1$\n" "Z:z>1|2=m=b*0|1+1$\n"
``` ```
This is a Changeset. Its just a string and its very difficult to read in this form. But the Changeset Library gives us some tools to read it. This is a Changeset. It's just a string and it's very difficult to read in this form. But the Changeset Library gives us some tools to read it.
A changeset describes the diff between two revisions of the document. The Browser sends changesets to the server and the server sends them to the clients to update them. This Changesets gets also saved into the history of a pad. Which allows us to go back to every revision from the past. A changeset describes the diff between two revisions of the document. The Browser sends changesets to the server and the server sends them to the clients to update them. These Changesets also get saved into the history of a pad. This allows us to go back to every revision from the past.
## Changeset.unpack(changeset) ## Changeset.unpack(changeset)
* `changeset` {String} * `changeset` {String}
This functions returns an object representaion of the changeset, similar to this: This function returns an object representation of the changeset, similar to this:
``` ```
{ oldLen: 35, newLen: 36, ops: '|2=m=b*0|1+1', charBank: '\n' } { oldLen: 35, newLen: 36, ops: '|2=m=b*0|1+1', charBank: '\n' }
@ -65,7 +65,7 @@ There are 3 types of operators: `+`,`-` and `=`. These operators describe differ
fromJsonable: [Function] } fromJsonable: [Function] }
``` ```
This creates an empty apool. A apool saves which attributes were used during the history of a pad. There is one apool for each pad. It only saves the attributes that were really used, it doesn't save unused attributes. Lets fill this apool with some values This creates an empty apool. An apool saves which attributes were used during the history of a pad. There is one apool for each pad. It only saves the attributes that were really used, it doesn't save unused attributes. Let's fill this apool with some values
``` ```
> apool.fromJsonable({"numToAttrib":{"0":["author","a.kVnWeomPADAT2pn9"],"1":["bold","true"],"2":["italic","true"]},"nextNum":3}); > apool.fromJsonable({"numToAttrib":{"0":["author","a.kVnWeomPADAT2pn9"],"1":["bold","true"],"2":["italic","true"]},"nextNum":3});
@ -88,7 +88,7 @@ This creates an empty apool. A apool saves which attributes were used during the
fromJsonable: [Function] } fromJsonable: [Function] }
``` ```
We used the fromJsonable function to fill the empty apool with values. the fromJsonable and toJsonable functions are used to serialize and deserialize an apool. You can see that it stores the relation between numbers and attributes. So for example the attribute 1 is the attribute bold and vise versa. A attribute is always a key value pair. For stuff like bold and italic its just 'italic':'true'. For authors its author:$AUTHORID. So a character can be bold and italic. But it can't belong to multiple authors We used the fromJsonable function to fill the empty apool with values. the fromJsonable and toJsonable functions are used to serialize and deserialize an apool. You can see that it stores the relation between numbers and attributes. So for example the attribute 1 is the attribute bold and vise versa. An attribute is always a key value pair. For stuff like bold and italic it's just 'italic':'true'. For authors it's author:$AUTHORID. So a character can be bold and italic. But it can't belong to multiple authors
``` ```
> apool.getAttrib(1) > apool.getAttrib(1)

View File

@ -1,5 +1,5 @@
# Embed parameters # Embed parameters
You can easily embed your etherpad-lite into any webpage by using iframes. You can configure the embedded pad using embed paramters. You can easily embed your etherpad-lite into any webpage by using iframes. You can configure the embedded pad using embed parameters.
Example: Example:

View File

@ -125,7 +125,7 @@ Things in context:
1. pad - the pad instance 1. pad - the pad instance
This hook gets called when an pad was loaded. If a new pad was created and loaded this event will be emitted too. This hook gets called when a pad was loaded. If a new pad was created and loaded this event will be emitted too.
## padUpdate ## padUpdate
Called from: src/node/db/Pad.js Called from: src/node/db/Pad.js
@ -219,7 +219,7 @@ Things in context:
1. message - the message being handled 1. message - the message being handled
2. client - the client object from socket.io 2. client - the client object from socket.io
This hook will be called once a message arrive. If a plugin calls `callback(null)` the message will be dropped. However it is not possible to modify the message. This hook will be called once a message arrive. If a plugin calls `callback(null)` the message will be dropped. However, it is not possible to modify the message.
Plugins may also decide to implement custom behavior once a message arrives. Plugins may also decide to implement custom behavior once a message arrives.
@ -272,7 +272,7 @@ Things in context:
1. clientVars - the basic `clientVars` built by the core 1. clientVars - the basic `clientVars` built by the core
2. pad - the pad this session is about 2. pad - the pad this session is about
This hook will be called once a client connects and the `clientVars` are being sent. Plugins can use this hook to give the client a initial configuriation, like the tracking-id of an external analytics-tool that is used on the client-side. You can also overwrite values from the original `clientVars`. This hook will be called once a client connects and the `clientVars` are being sent. Plugins can use this hook to give the client an initial configuration, like the tracking-id of an external analytics-tool that is used on the client-side. You can also overwrite values from the original `clientVars`.
Example: Example:
@ -397,7 +397,7 @@ Things in context:
1. Pad object 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']`. Identical to `exportHtmlAdditionalTags`, but for tags that are stored with a 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: Example:
``` ```

View File

@ -86,19 +86,19 @@ Responses are valid JSON in the following format:
* **2** internal error * **2** internal error
* **3** no such function * **3** no such function
* **4** no or wrong API Key * **4** no or wrong API Key
* **message** a status message. Its ok if everything is fine, else it contains an error message * **message** a status message. It's ok if everything is fine, else it contains an error message
* **data** the payload * **data** the payload
### Overview ### Overview
![API Overview](http://i.imgur.com/d0nWp.png) ![API Overview](https://i.imgur.com/d0nWp.png)
## Data Types ## Data Types
* **groupID** a string, the unique id of a group. Format is g.16RANDOMCHARS, for example g.s8oes9dhwrvt0zif * **groupID** a string, the unique id of a group. Format is g.16RANDOMCHARS, for example g.s8oes9dhwrvt0zif
* **sessionID** a string, the unique id of a session. Format is s.16RANDOMCHARS, for example s.s8oes9dhwrvt0zif * **sessionID** a string, the unique id of a session. Format is s.16RANDOMCHARS, for example s.s8oes9dhwrvt0zif
* **authorID** a string, the unique id of an author. Format is a.16RANDOMCHARS, for example a.s8oes9dhwrvt0zif * **authorID** a string, the unique id of an author. Format is a.16RANDOMCHARS, for example a.s8oes9dhwrvt0zif
* **readOnlyID** a string, the unique id of an readonly relation to a pad. Format is r.16RANDOMCHARS, for example r.s8oes9dhwrvt0zif * **readOnlyID** a string, the unique id of a readonly relation to a pad. Format is r.16RANDOMCHARS, for example r.s8oes9dhwrvt0zif
* **padID** a string, format is GROUPID$PADNAME, for example the pad test of group g.s8oes9dhwrvt0zif has padID g.s8oes9dhwrvt0zif$test * **padID** a string, format is GROUPID$PADNAME, for example the pad test of group g.s8oes9dhwrvt0zif has padID g.s8oes9dhwrvt0zif$test
### Authentication ### Authentication
@ -107,14 +107,14 @@ Authentication works via a token that is sent with each request as a post parame
### Node Interoperability ### Node Interoperability
All functions will also be available through a node module accessable from other node.js applications. All functions will also be available through a node module accessible from other node.js applications.
### JSONP ### JSONP
The API provides _JSONP_ support to allow requests from a server in a different domain. The API provides _JSONP_ support to allow requests from a server in a different domain.
Simply add `&jsonp=?` to the API call. Simply add `&jsonp=?` to the API call.
Example usage: http://api.jquery.com/jQuery.getJSON/ Example usage: https://api.jquery.com/jQuery.getJSON/
## API Methods ## API Methods
@ -213,7 +213,7 @@ Returns the Author Name of the author
-> can't be deleted cause this would involve scanning all the pads where this author was -> can't be deleted cause this would involve scanning all the pads where this author was
### Session ### Session
Sessions can be created between a group and an author. This allows an author to access more than one group. The sessionID will be set as a cookie to the client and is valid until a certain date. The session cookie can also contain multiple comma-seperated sessionIDs, allowing a user to edit pads in different groups at the same time. Only users with a valid session for this group, can access group pads. You can create a session after you authenticated the user at your web application, to give them access to the pads. You should save the sessionID of this session and delete it after the user logged out. Sessions can be created between a group and an author. This allows an author to access more than one group. The sessionID will be set as a cookie to the client and is valid until a certain date. The session cookie can also contain multiple comma-separated sessionIDs, allowing a user to edit pads in different groups at the same time. Only users with a valid session for this group, can access group pads. You can create a session after you authenticated the user at your web application, to give them access to the pads. You should save the sessionID of this session and delete it after the user logged out.
#### createSession(groupID, authorID, validUntil) #### createSession(groupID, authorID, validUntil)
* API >= 1 * API >= 1
@ -307,7 +307,7 @@ returns the text of a pad formatted as HTML
#### setHTML(padID, html) #### setHTML(padID, html)
* API >= 1 * 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. 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:* *Example returns:*
* `{code: 0, message:"ok", data: null}` * `{code: 0, message:"ok", data: null}`
@ -411,7 +411,7 @@ creates a chat message, saves it to the database and sends it to all connected c
* `{code: 1, message:"text is no string", data: null}` * `{code: 1, message:"text is no string", data: null}`
### Pad ### Pad
Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security manager controls access of them and its forbidden for normal pads to include a $ in the name. Group pads are normal pads, but with the name schema GROUPID$PADNAME. A security manager controls access of them and it's forbidden for normal pads to include a $ in the name.
#### createPad(padID [, text]) #### createPad(padID [, text])
* API >= 1 * API >= 1
@ -543,7 +543,7 @@ return true of false
#### setPassword(padID, password) #### setPassword(padID, password)
* API >= 1 * API >= 1
returns ok or a error message returns ok or an error message
*Example returns:* *Example returns:*
* `{code: 0, message:"ok", data: null}` * `{code: 0, message:"ok", data: null}`

View File

@ -3,7 +3,7 @@
## plugins.update ## plugins.update
`require("ep_etherpad-lite/static/js/plugingfw/plugins").update()` will use npm to list all installed modules and read their ep.json files, registering the contained hooks. `require("ep_etherpad-lite/static/js/plugingfw/plugins").update()` will use npm to list all installed modules and read their ep.json files, registering the contained hooks.
A hook registration is a pairs of a hook name and a function reference (filename for require() plus function name) A hook registration is a pair of a hook name and a function reference (filename for require() plus function name)
## hooks.callAll ## hooks.callAll
`require("ep_etherpad-lite/static/js/plugingfw/hooks").callAll("hook_name", {argname:value})` will call all hook functions registered for `hook_name` with `{argname:value}`. `require("ep_etherpad-lite/static/js/plugingfw/hooks").callAll("hook_name", {argname:value})` will call all hook functions registered for `hook_name` with `{argname:value}`.

View File

@ -10,6 +10,6 @@ provided to event handlers are detailed in a list underneath the topic
heading. heading.
Every `.html` file is generated based on the corresponding Every `.html` file is generated based on the corresponding
`.markdown` file in the `doc/api/` folder in the source tree. The `.md` file in the `doc/api/` folder in the source tree. The
documentation is generated using the `bin/doc/generate.js` program. documentation is generated using the `bin/doc/generate.js` program.
The HTML template is located at `doc/template.html`. The HTML template is located at `doc/template.html`.

View File

@ -85,7 +85,7 @@ For any two changesets $A$, $B$ such that
\item[] $A=(n_1\rightarrow n_2)[\cdots]$ \item[] $A=(n_1\rightarrow n_2)[\cdots]$
\item[] $B=(n_2\rightarrow n_3)[\cdots]$ \item[] $B=(n_2\rightarrow n_3)[\cdots]$
\end{itemize} \end{itemize}
it is clear that there is a third changeset $C=(n_1\rightarrow n_3)[\cdots]$ such that applying $C$ to a document $X$ yeilds the same resulting document as does applying $A$ and then $B$. In this case, we write $AB=C$. it is clear that there is a third changeset $C=(n_1\rightarrow n_3)[\cdots]$ such that applying $C$ to a document $X$ yields the same resulting document as does applying $A$ and then $B$. In this case, we write $AB=C$.
Given the representation from Section \ref{representation}, it is straightforward to compute the composition of two changesets. Given the representation from Section \ref{representation}, it is straightforward to compute the composition of two changesets.
@ -93,9 +93,9 @@ Given the representation from Section \ref{representation}, it is straightforwar
Now we come to realtime document editing. Suppose two different users make two different changes to the same document at the same time. It is impossible to compose these changes. For example, if we have the document $X$ of length $n$, we may have $A=(n\rightarrow n_a)[\ldots n_a \mathrm{characters}]$, $B=(n\rightarrow n_b)[\ldots n_b \mathrm{characters}]$ where $n\neq n_a\neq n_b$. Now we come to realtime document editing. Suppose two different users make two different changes to the same document at the same time. It is impossible to compose these changes. For example, if we have the document $X$ of length $n$, we may have $A=(n\rightarrow n_a)[\ldots n_a \mathrm{characters}]$, $B=(n\rightarrow n_b)[\ldots n_b \mathrm{characters}]$ where $n\neq n_a\neq n_b$.
It is impossible to compute $(XA)B$ because $B$ can only be applied to a document of length $n$, and $(XA)$ has length $n_a$. Similarly, $A$ cannot be appliet to $(XB)$ because $(XB)$ has length $n_b$. It is impossible to compute $(XA)B$ because $B$ can only be applied to a document of length $n$, and $(XA)$ has length $n_a$. Similarly, $A$ cannot be applied to $(XB)$ because $(XB)$ has length $n_b$.
This is where \emph{merging} comes in. Merging takes two changesets that apply to the same initial document (and that cannot be composed), and computes a single new changeset that presevers the intent of both changes. The merge of $A$ and $B$ is written as $m(A,B)$. For the Etherpad system to work, we require that $m(A,B)=m(B,A)$. This is where \emph{merging} comes in. Merging takes two changesets that apply to the same initial document (and that cannot be composed), and computes a single new changeset that preserves the intent of both changes. The merge of $A$ and $B$ is written as $m(A,B)$. For the Etherpad system to work, we require that $m(A,B)=m(B,A)$.
Aside from what we have said so far about merging, there are many different implementations that will lead to a workable system. We have created one implementation for text that has the following constraints. Aside from what we have said so far about merging, there are many different implementations that will lead to a workable system. We have created one implementation for text that has the following constraints.
@ -156,7 +156,7 @@ server always. (This may distinguish from prior art?)
The other critical design feature of the system is that The other critical design feature of the system is that
\emph{A client must always be able to edit their local \emph{A client must always be able to edit their local
copy of the document, so the user is never blocked from copy of the document, so the user is never blocked from
typing because of waiting to to send or receive data.} typing because of waiting to send or receive data.}
\section{Client State} \section{Client State}
@ -329,7 +329,7 @@ with:
\end{enumerate} \end{enumerate}
\subsection{Respond to client connect} \subsection{Respond to client connect}
When a server recieves a connection request from a client, When a server receives a connection request from a client,
it receives the client's unique ID and stores that in the it receives the client's unique ID and stores that in the
server's set of connected clients. It then sends the server's set of connected clients. It then sends the
client the contents of HEADTEXT, and the corresponding client the contents of HEADTEXT, and the corresponding

View File

@ -3,9 +3,9 @@ Etherpad provides a multi-language user interface, that's apart from your users'
## Translating ## Translating
We rely on http://translatewiki.net to handle the translation process for us, so if you'd like to help... We rely on https://translatewiki.net to handle the translation process for us, so if you'd like to help...
1. sign up at http://translatewiki.net 1. Sign up at https://translatewiki.net
2. Visit our [TWN project page](https://translatewiki.net/wiki/Translating:Etherpad_lite) 2. Visit our [TWN project page](https://translatewiki.net/wiki/Translating:Etherpad_lite)
3. Click on `Translate Etherpad lite interface` 3. Click on `Translate Etherpad lite interface`
4. Choose a target language, you'd like to translate our interface to, and hit `Fetch` 4. Choose a target language, you'd like to translate our interface to, and hit `Fetch`
@ -62,7 +62,7 @@ alert(window._('pad.chat'));
``` ```
### 2. Create translate files in the locales directory of your plugin ### 2. Create translate files in the locales directory of your plugin
* The name of the file must be the language code of the language it contains translations for (see [supported lang codes](http://joker-x.github.com/languages4translatewiki/test/); e.g. en ? English, es ? Spanish...) * The name of the file must be the language code of the language it contains translations for (see [supported lang codes](https://joker-x.github.com/languages4translatewiki/test/); e.g. en ? English, es ? Spanish...)
* The extension of the file must be `.json` * The extension of the file must be `.json`
* The default language is English, so your plugin should always provide `en.json` * The default language is English, so your plugin should always provide `en.json`
* In order to avoid naming conflicts, your message keys should start with the name of your plugin followed by a dot (see below) * In order to avoid naming conflicts, your message keys should start with the name of your plugin followed by a dot (see below)

View File

@ -1,7 +1,7 @@
# Plugins # Plugins
Etherpad allows you to extend its functionality with plugins. A plugin registers hooks (functions) for certain events (thus certain features) in Etherpad-lite to execute its own functionality based on these events. Etherpad allows you to extend its functionality with plugins. A plugin registers hooks (functions) for certain events (thus certain features) in Etherpad-lite to execute its own functionality based on these events.
Publicly available plugins can be found in the npm registry (see <http://npmjs.org>). Etherpad-lite's naming convention for plugins is to prefix your plugins with `ep_`. So, e.g. it's `ep_flubberworms`. Thus you can install plugins from npm, using `npm install ep_flubberworm` in etherpad-lite's root directory. Publicly available plugins can be found in the npm registry (see <https://npmjs.org>). Etherpad-lite's naming convention for plugins is to prefix your plugins with `ep_`. So, e.g. it's `ep_flubberworms`. Thus you can install plugins from npm, using `npm install ep_flubberworm` in etherpad-lite's root directory.
You can also browse to `http://yourEtherpadInstan.ce/admin/plugins`, which will list all installed plugins and those available on npm. It even provides functionality to search through all available plugins. You can also browse to `http://yourEtherpadInstan.ce/admin/plugins`, which will list all installed plugins and those available on npm. It even provides functionality to search through all available plugins.
@ -17,7 +17,7 @@ ep_<plugin>/
``` ```
If your plugin includes client-side hooks, put them in `static/js/`. If you're adding in CSS or image files, you should put those files in `static/css/ `and `static/image/`, respectively, and templates go into `templates/`. Translations go into `locales/` If your plugin includes client-side hooks, put them in `static/js/`. If you're adding in CSS or image files, you should put those files in `static/css/ `and `static/image/`, respectively, and templates go into `templates/`. Translations go into `locales/`
A Standard directory structure like this makes it easier to navigate through your code. That said, do note, that this is not actually *required* to make your plugin run. If you want to make use of our i18n system, you need to put your translations into `locales/`, though, in order to have them intergated. (See "Localization" for more info on how to localize your plugin) A Standard directory structure like this makes it easier to navigate through your code. That said, do note, that this is not actually *required* to make your plugin run. If you want to make use of our i18n system, you need to put your translations into `locales/`, though, in order to have them integrated. (See "Localization" for more info on how to localize your plugin)
## Plugin definition ## Plugin definition
Your plugin definition goes into `ep.json`. In this file you register your hooks, indicate the parts of your plugin and the order of execution. (A documentation of all available events to hook into can be found in chapter [hooks](#all_hooks).) Your plugin definition goes into `ep.json`. In this file you register your hooks, indicate the parts of your plugin and the order of execution. (A documentation of all available events to hook into can be found in chapter [hooks](#all_hooks).)
@ -41,7 +41,7 @@ A hook registration is a pairs of a hook name and a function reference (filename
} }
``` ```
Etherpad-lite will expect the part of the hook definition before the colon to be a javascript file and will try to require it. The part after the colon is expected to be a valid function identifier of that module. So, you have to export your hooks, using [`module.exports`](http://nodejs.org/docs/latest/api/modules.html#modules_modules) and register it in `ep.json` as `ep_<plugin>/path/to/<file>:FUNCTIONNAME`. Etherpad-lite will expect the part of the hook definition before the colon to be a javascript file and will try to require it. The part after the colon is expected to be a valid function identifier of that module. So, you have to export your hooks, using [`module.exports`](https://nodejs.org/docs/latest/api/modules.html#modules_modules) and register it in `ep.json` as `ep_<plugin>/path/to/<file>:FUNCTIONNAME`.
You can omit the `FUNCTIONNAME` part, if the exported function has got the same name as the hook. So `"authorize" : "ep_flubberworm/foo"` will call the function `exports.authorize` in `ep_flubberworm/foo.js` You can omit the `FUNCTIONNAME` part, if the exported function has got the same name as the hook. So `"authorize" : "ep_flubberworm/foo"` will call the function `exports.authorize` in `ep_flubberworm/foo.js`
### Client hooks and server hooks ### Client hooks and server hooks
@ -89,7 +89,7 @@ Note that it would be far more sane to use `"pre"` in almost any case, but if yo
Also, note that dependencies should *also* be listed in your package.json, so they can be `npm install`'d automagically when your plugin gets installed. Also, note that dependencies should *also* be listed in your package.json, so they can be `npm install`'d automagically when your plugin gets installed.
## Package definition ## Package definition
Your plugin must also contain a [package definition file](http://npmjs.org/doc/json.html), called package.json, in the project root - this file contains various metadata relevant to your plugin, such as the name and version number, author, project hompage, contributors, a short description, etc. If you publish your plugin on npm, these metadata are used for package search etc., but it's necessary for Etherpad-lite plugins, even if you don't publish your plugin. Your plugin must also contain a [package definition file](https://docs.npmjs.com/files/package.json), called package.json, in the project root - this file contains various metadata relevant to your plugin, such as the name and version number, author, project hompage, contributors, a short description, etc. If you publish your plugin on npm, these metadata are used for package search etc., but it's necessary for Etherpad-lite plugins, even if you don't publish your plugin.
```json ```json
{ {