Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make it easier to contribute #374

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# EditorConfig is awesome: http://EditorConfig.org

# top-most EditorConfig file
root = true

# Unix-style newlines with a newline ending every file
[*]
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 2
17 changes: 17 additions & 0 deletions .eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"env": {
"browser": true,
"node": true
},
"rules": {
"eqeqeq": [2, "smart"],
"strict": [2, "global"],
"camelcase": 0,
"no-underscore-dangle": 0,
"quotes": [2, "single"],
"curly": [2, "multi-line"],
"no-unused-vars": [2, {"vars": "all", "args": "none"}],
"no-shadow": 0,
"consistent-return": 0
}
}
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@
node_modules
dist/*
coverage
npm-debug.log
9 changes: 7 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
language: node_js

node_js:
- 0.10
- "io.js"
- "0.12"
- "0.10"

script:
- npm run lint
- npm test

services:
- redis-server

13 changes: 13 additions & 0 deletions CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Contributor Code of Conduct

As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.

We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.

Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.

Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.

Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.

This Code of Conduct is adapted from the [Contributor Covenant](http://contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
37 changes: 37 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# Contributing

Contributions are always welcome, no matter how large or small. Before
contributing, please read the
[code of conduct](CODE_OF_CONDUCT.md).

## Developing

#### Setup

```sh
$ git clone https://github.com/share/ShareJS
$ cd ShareJS
$ npm install
```

#### Running tests

You can run tests via:

```sh
$ npm test
```

#### Workflow

* Fork the repository
* Clone your fork and change directory to it (`git clone [email protected]:yourUserName/ShareJS.git && cd ShareJS`)
* Install the project dependencies (`npm install`)
* Link your forked clone (`npm link`)
* Develop your changes ensuring you're fetching updates from upstream often
* Ensure the test are passing (`npm test`)
* Create new pull request explaining your proposed change or reference an issue in your commit message

#### Code Standards

Run linting via `npm run lint`.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
ShareJS
=======

[![Build Status](https://secure.travis-ci.org/share/ShareJS.svg)](http://travis-ci.org/share/ShareJS) [![Code Climate](https://codeclimate.com/github/share/ShareJS/badges/gpa.svg)](https://codeclimate.com/github/share/ShareJS) [![Dependency Status](https://david-dm.org/share/sharejs.svg)](https://david-dm.org/share/sharejs) [![devDependency Status](https://david-dm.org/share/sharejs/dev-status.svg)](https://david-dm.org/share/sharejs#info=devDependencies)


This is a little server & client library to allow concurrent editing of any
kind of content via OT. The server runs on NodeJS and the client works in NodeJS or a
web browser.
Expand All @@ -11,9 +14,7 @@ ShareJS currently supports operational transform on plain-text and arbitrary JSO

**Check out the [live interactive demos](http://sharejs.org/).**

**Immerse yourself in [API Documentation](https://github.com/josephg/ShareJS/wiki).**

[![Build Status](https://secure.travis-ci.org/share/ShareJS.png)](http://travis-ci.org/share/ShareJS)
**Immerse yourself in [API Documentation](https://github.com/share/ShareJS/wiki).**


Browser support
Expand Down Expand Up @@ -424,7 +425,7 @@ doc.subscribe();
// This will be called when we have a live copy of the server's data.
doc.whenReady(function() {
console.log('doc ready, data: ', doc.getSnapshot());

// Create a JSON document with value x:5
if (!doc.type) doc.create('text');
doc.attachTextarea(document.getElementById('pad'));
Expand All @@ -445,7 +446,7 @@ doc.subscribe();
// This will be called when we have a live copy of the server's data.
doc.whenReady(function() {
console.log('doc ready, data: ', doc.getSnapshot());

// Create a JSON document with value x:5
if (!doc.type) doc.create('json0', {x:5});
});
Expand All @@ -462,4 +463,3 @@ See the [examples directory](https://github.com/share/ShareJS/tree/master/exampl
# License

ShareJS is proudly licensed under the [MIT license](LICENSE).

77 changes: 42 additions & 35 deletions lib/client/connection.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
'use strict';

var Doc = require('./doc').Doc;
var Query = require('./query').Query;
var emitter = require('./emitter');
Expand Down Expand Up @@ -60,7 +62,7 @@ var Connection = exports.Connection = function (socket) {
this.messageBuffer = [];

this.bindToSocket(socket);
}
};
emitter.mixin(Connection);


Expand All @@ -83,10 +85,10 @@ emitter.mixin(Connection);
*/
Connection.prototype.bindToSocket = function(socket) {
if (this.socket) {
delete this.socket.onopen
delete this.socket.onclose
delete this.socket.onmessage
delete this.socket.onerror
delete this.socket.onopen;
delete this.socket.onclose;
delete this.socket.onmessage;
delete this.socket.onerror;
}

// TODO: Check that the socket is in the 'connecting' state.
Expand All @@ -98,7 +100,7 @@ Connection.prototype.bindToSocket = function(socket) {
this.canSend = this.state === 'connecting' && socket.canSendWhileConnecting;
this._setupRetry();

var connection = this
var connection = this;

socket.onmessage = function(msg) {
var data = msg.data;
Expand All @@ -114,7 +116,7 @@ Connection.prototype.bindToSocket = function(socket) {

connection.messageBuffer.push({
t: (new Date()).toTimeString(),
recv:JSON.stringify(data)
recv: JSON.stringify(data)
});
while (connection.messageBuffer.length > 100) {
connection.messageBuffer.shift();
Expand All @@ -128,7 +130,7 @@ Connection.prototype.bindToSocket = function(socket) {
// in infinite reconnection bugs.
throw e;
}
}
};

socket.onopen = function() {
connection._setState('connecting');
Expand Down Expand Up @@ -189,9 +191,9 @@ Connection.prototype.handleMessage = function(msg) {
break;
}

var msg = result[cName][docName];
if (typeof msg === 'object') {
doc._handleSubscribe(msg.error, msg);
var localMsg = result[cName][docName];
if (typeof localMsg === 'object') {
doc._handleSubscribe(localMsg.error, localMsg);
} else {
// The msg will be true if we simply resubscribed.
doc._handleSubscribe(null, null);
Expand All @@ -203,17 +205,17 @@ Connection.prototype.handleMessage = function(msg) {
default:
// Document message. Pull out the referenced document and forward the
// message.
var collection, docName, doc;
var collection, dName;
if (msg.d) {
collection = this._lastReceivedCollection = msg.c;
docName = this._lastReceivedDoc = msg.d;
dName = this._lastReceivedDoc = msg.d;
} else {
collection = msg.c = this._lastReceivedCollection;
docName = msg.d = this._lastReceivedDoc;
dName = msg.d = this._lastReceivedDoc;
}

var doc = this.getExisting(collection, docName);
if (doc) doc._onMessage(msg);
var d = this.getExisting(collection, dName);
if (d) d._onMessage(msg);
}
};

Expand Down Expand Up @@ -256,7 +258,7 @@ Connection.prototype._setState = function(newState, data) {
// 'connected' from anywhere other than 'connecting'.
if ((newState === 'connecting' && (this.state !== 'disconnected' && this.state !== 'stopped'))
|| (newState === 'connected' && this.state !== 'connecting')) {
throw new Error("Cannot transition directly from " + this.state + " to " + newState);
throw new Error('Cannot transition directly from ' + this.state + ' to ' + newState);
}

this.state = newState;
Expand Down Expand Up @@ -301,8 +303,8 @@ Connection.prototype._setState = function(newState, data) {
// originally sent. If we don't sort, an op with a high sequence number will
// convince the server not to accept any ops with earlier sequence numbers.
this.opQueue.sort(function(a, b) { return a.seq - b.seq; });
for (var i = 0; i < this.opQueue.length; i++) {
this.send(this.opQueue[i]);
for (var j = 0; j < this.opQueue.length; j++) {
this.send(this.opQueue[j]);
}

this.opQueue = null;
Expand All @@ -327,10 +329,15 @@ Connection.prototype.bsStart = function() {
this.subscribeData = {};
};

function hasKeys(object) {
for (var key in object) return true; // eslint-disable-line no-unused-vars
return false;
}

Connection.prototype.bsEnd = function() {
// Only send bulk subscribe if not empty
if (hasKeys(this.subscribeData)) {
this.send({a:'bs', s:this.subscribeData});
this.send({a: 'bs', s: this.subscribeData});
}
this.subscribeData = null;
};
Expand All @@ -346,7 +353,7 @@ Connection.prototype.sendSubscribe = function(collection, name, v) {

data[collection][name] = v || null;
} else {
var msg = {a:'sub', c:collection, d:name};
var msg = {a: 'sub', c: collection, d: name};
if (v != null) msg.v = v;
this.send(msg);
}
Expand All @@ -357,8 +364,8 @@ Connection.prototype.sendSubscribe = function(collection, name, v) {
* Sends a message down the socket
*/
Connection.prototype.send = function(msg) {
if (this.debug) console.log("SEND", JSON.stringify(msg));
this.messageBuffer.push({t:Date.now(), send:JSON.stringify(msg)});
if (this.debug) console.log('SEND', JSON.stringify(msg));
this.messageBuffer.push({t: Date.now(), send: JSON.stringify(msg)});
while (this.messageBuffer.length > 100) {
this.messageBuffer.shift();
}
Expand All @@ -375,8 +382,9 @@ Connection.prototype.send = function(msg) {
}
}

if (!this.socket.canSendJSON)
if (!this.socket.canSendJSON) {
msg = JSON.stringify(msg);
}

this.socket.send(msg);
};
Expand Down Expand Up @@ -413,20 +421,23 @@ Connection.prototype.getOrCreate = function(collection, name, data) {
*/
Connection.prototype.get = function(collection, name, data) {
var collectionObject = this.collections[collection];
if (!collectionObject)
if (!collectionObject) {
collectionObject = this.collections[collection] = {};
}

var doc = collectionObject[name];
if (!doc)
if (!doc) {
doc = collectionObject[name] = new Doc(this, collection, name);
}

// Even if the document isn't new, its possible the document was created
// manually and then tried to be re-created with data (suppose a query
// returns with data for the document). We should hydrate the document
// immediately if we can because the query callback will expect the document
// to have data.
if (data && data.data !== undefined && !doc.state)
if (data && data.data !== undefined && !doc.state) {
doc.ingestData(data);
}

return doc;
};
Expand All @@ -446,21 +457,17 @@ Connection.prototype._destroyDoc = function(doc) {
// Delete the collection container if its empty. This could be a source of
// memory leaks if you slowly make a billion collections, which you probably
// won't do anyway, but whatever.
if (!hasKeys(collectionObject))
if (!hasKeys(collectionObject)) {
delete this.collections[doc.collection];
};


function hasKeys(object) {
for (var key in object) return true;
return false;
}
};


// Helper for createFetchQuery and createSubscribeQuery, below.
Connection.prototype._createQuery = function(type, collection, q, options, callback) {
if (type !== 'fetch' && type !== 'sub')
if (type !== 'fetch' && type !== 'sub') {
throw new Error('Invalid query type: ' + type);
}

if (!options) options = {};
var id = this.nextQueryId++;
Expand Down
Loading