Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bbfb1d9bcb | ||
|
|
e1108d4007 | ||
|
|
c00dee819f | ||
|
|
92b9cb8143 | ||
|
|
5dad1ed410 | ||
|
|
b613630cef | ||
|
|
afa05b62a1 | ||
|
|
957d650f81 | ||
|
|
9769968c1c | ||
|
|
1e30a877e6 | ||
|
|
7744993dde | ||
|
|
cf3969dff6 |
@@ -2,7 +2,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<style type="text/css" media="screen">
|
<style type="text/css" media="screen">
|
||||||
#ace {
|
#aceContainer {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
right: 0;
|
right: 0;
|
||||||
@@ -23,10 +23,10 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div id="ace"></div>
|
<div id="aceContainer"></div>
|
||||||
<script src="../bower_components/yjs/y.es6"></script>
|
<script src="../bower_components/yjs/y.es6"></script>
|
||||||
<script src="../bower_components/ace-builds/src/ace.js"></script>
|
<script src="../bower_components/ace-builds/src/ace.js"></script>
|
||||||
|
|
||||||
<script src="./index.js"></script>
|
<script src="./index.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ Y({
|
|||||||
window.yAce = y
|
window.yAce = y
|
||||||
|
|
||||||
// bind the textarea to a shared text element
|
// bind the textarea to a shared text element
|
||||||
var editor = ace.edit('ace')
|
var editor = ace.edit('aceContainer')
|
||||||
editor.setTheme('ace/theme/chrome')
|
editor.setTheme('ace/theme/chrome')
|
||||||
editor.getSession().setMode('ace/mode/javascript')
|
editor.getSession().setMode('ace/mode/javascript')
|
||||||
|
|
||||||
|
|||||||
@@ -36,17 +36,4 @@ Y({
|
|||||||
});
|
});
|
||||||
// bind quill to richtext type
|
// bind quill to richtext type
|
||||||
y.share.richtext.bind(window.quill)
|
y.share.richtext.bind(window.quill)
|
||||||
})
|
})
|
||||||
|
|
||||||
Y({
|
|
||||||
db: {
|
|
||||||
name: 'indexeddb'
|
|
||||||
},
|
|
||||||
connector: {
|
|
||||||
name: 'websockets-client',
|
|
||||||
room: 'test42'
|
|
||||||
},
|
|
||||||
share: {
|
|
||||||
state : 'Map'
|
|
||||||
}
|
|
||||||
}).then((y) => { window.y = y })
|
|
||||||
@@ -8,6 +8,7 @@ Y({
|
|||||||
connector: {
|
connector: {
|
||||||
name: 'websockets-client',
|
name: 'websockets-client',
|
||||||
room: 'Textarea-example'
|
room: 'Textarea-example'
|
||||||
|
// url: '127.0.0.1:1234'
|
||||||
},
|
},
|
||||||
sourceDir: '/bower_components',
|
sourceDir: '/bower_components',
|
||||||
share: {
|
share: {
|
||||||
|
|||||||
31
Examples/WebWorker/index.html
Normal file
31
Examples/WebWorker/index.html
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<!-- quill does not include dist files! We are using the hosted version instead -->
|
||||||
|
<!--link rel="stylesheet" href="../bower_components/quill/dist/quill.snow.css" /-->
|
||||||
|
<link href="https://cdn.quilljs.com/1.0.4/quill.snow.css" rel="stylesheet">
|
||||||
|
<link href="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.css" rel="stylesheet">
|
||||||
|
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/styles/monokai-sublime.min.css" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
#quill-container {
|
||||||
|
border: 1px solid gray;
|
||||||
|
box-shadow: 0px 0px 10px gray;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="quill-container">
|
||||||
|
<div id="quill">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.js" type="text/javascript"></script>
|
||||||
|
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/highlight.min.js" type="text/javascript"></script>
|
||||||
|
<script src="https://cdn.quilljs.com/1.0.4/quill.js"></script>
|
||||||
|
<!-- quill does not include dist files! We are using the hosted version instead (see above)
|
||||||
|
<script src="../bower_components/quill/dist/quill.js"></script>
|
||||||
|
-->
|
||||||
|
<script src="../bower_components/yjs/y.es6"></script>
|
||||||
|
<script src="./index.js"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
39
Examples/WebWorker/index.js
Normal file
39
Examples/WebWorker/index.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
/* global Y, Quill */
|
||||||
|
|
||||||
|
// initialize a shared object. This function call returns a promise!
|
||||||
|
Y({
|
||||||
|
db: {
|
||||||
|
name: 'memory'
|
||||||
|
},
|
||||||
|
connector: {
|
||||||
|
name: 'webworker',
|
||||||
|
url: '../bower_components/y-webworker/yjs-webworker.js',
|
||||||
|
room: 'WebWorkerExample2'
|
||||||
|
},
|
||||||
|
sourceDir: '/bower_components',
|
||||||
|
share: {
|
||||||
|
richtext: 'Richtext' // y.share.richtext is of type Y.Richtext
|
||||||
|
}
|
||||||
|
}).then(function (y) {
|
||||||
|
window.yQuill = y
|
||||||
|
|
||||||
|
// create quill element
|
||||||
|
window.quill = new Quill('#quill', {
|
||||||
|
modules: {
|
||||||
|
formula: true,
|
||||||
|
syntax: true,
|
||||||
|
toolbar: [
|
||||||
|
[{ size: ['small', false, 'large', 'huge'] }],
|
||||||
|
['bold', 'italic', 'underline'],
|
||||||
|
[{ color: [] }, { background: [] }], // Snow theme fills in values
|
||||||
|
[{ script: 'sub' }, { script: 'super' }],
|
||||||
|
['link', 'image'],
|
||||||
|
['link', 'code-block'],
|
||||||
|
[{list: 'ordered' }]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
theme: 'snow'
|
||||||
|
})
|
||||||
|
// bind quill to richtext type
|
||||||
|
y.share.richtext.bind(window.quill)
|
||||||
|
})
|
||||||
109
README.md
109
README.md
@@ -1,13 +1,13 @@
|
|||||||
|
|
||||||
# 
|
# 
|
||||||
|
|
||||||
Yjs is a framework for p2p shared editing on structured data like (rich-)text, json, and XML.
|
Yjs is a framework for offline-first p2p shared editing on structured data like text, richtext, json, or XML.
|
||||||
It is similar to [ShareJs] and [OpenCoweb], but easy to use.
|
It is fairly easy to get started, as Yjs hides most of the complexity of concurrent editing.
|
||||||
For additional information, demos, and tutorials visit [y-js.org](http://y-js.org/).
|
For additional information, demos, and tutorials visit [y-js.org](http://y-js.org/).
|
||||||
|
|
||||||
### Extensions
|
### Extensions
|
||||||
Yjs only knows how to resolve conflicts on shared data. You have to choose a ..
|
Yjs only knows how to resolve conflicts on shared data. You have to choose a ..
|
||||||
* *Connector* - a communication protocol that propagates changes to the clients
|
* *Connector* - a communication protocol that propagates changes to the clients
|
||||||
* *Database* - a database to store your changes
|
* *Database* - a database to store your changes
|
||||||
* one or more *Types* - that represent the shared data
|
* one or more *Types* - that represent the shared data
|
||||||
|
|
||||||
@@ -41,8 +41,14 @@ Connectors, Databases, and Types are available as modules that extend Yjs. Here
|
|||||||
|[text](https://github.com/y-js/y-text) | Collaborate on text. Supports two way binding to the [Ace Editor](https://ace.c9.io), textareas, input elements, and HTML elements (e.g. <*h1*>, or <*p*>) |
|
|[text](https://github.com/y-js/y-text) | Collaborate on text. Supports two way binding to the [Ace Editor](https://ace.c9.io), textareas, input elements, and HTML elements (e.g. <*h1*>, or <*p*>) |
|
||||||
|[richtext](https://github.com/y-js/y-richtext) | Collaborate on rich text. Supports two way binding to the [Quill Rich Text Editor](http://quilljs.com/)|
|
|[richtext](https://github.com/y-js/y-richtext) | Collaborate on rich text. Supports two way binding to the [Quill Rich Text Editor](http://quilljs.com/)|
|
||||||
|
|
||||||
## Use it!
|
##### Other
|
||||||
Install Yjs, and its modules with [bower](http://bower.io/), or [npm](https://www.npmjs.org/package/yjs).
|
|
||||||
|
| Name | Description |
|
||||||
|
|-----------|-------------------|
|
||||||
|
|[y-element](http://y-js.org/y-element/) | Yjs Polymer Element |
|
||||||
|
|
||||||
|
## Use it!
|
||||||
|
Install Yjs, and its modules with [bower](http://bower.io/), or [npm](https://www.npmjs.org/package/yjs).
|
||||||
|
|
||||||
### Bower
|
### Bower
|
||||||
```
|
```
|
||||||
@@ -91,23 +97,23 @@ bower i yjs y-memory y-webrtc y-array y-text
|
|||||||
```
|
```
|
||||||
|
|
||||||
Here is a simple example of a shared textarea
|
Here is a simple example of a shared textarea
|
||||||
```
|
```HTML
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<script src="./bower_components/yjs/y.js"></script>
|
<script src="./bower_components/yjs/y.js"></script>
|
||||||
|
<!-- Yjs automatically includes all missing dependencies (browser only) -->
|
||||||
<script>
|
<script>
|
||||||
Y({
|
Y({
|
||||||
db: {
|
db: {
|
||||||
name: 'memory' // use memory database adapter.
|
name: 'memory' // use memory database adapter.
|
||||||
// name: 'indexeddb'
|
// name: 'indexeddb' // use indexeddb database adapter instead for offline apps
|
||||||
// name: 'leveldb'
|
|
||||||
},
|
},
|
||||||
connector: {
|
connector: {
|
||||||
name: 'webrtc', // use webrtc connector
|
name: 'webrtc', // use webrtc connector
|
||||||
// name: 'websockets-client'
|
// name: 'websockets-client'
|
||||||
// name: 'xmpp'
|
// name: 'xmpp'
|
||||||
room: 'my-room' // clients connecting to the same room share data
|
room: 'my-room' // clients connecting to the same room share data
|
||||||
},
|
},
|
||||||
sourceDir: '/bower_components', // location of the y-* modules (browser only)
|
sourceDir: '/bower_components', // location of the y-* modules (browser only)
|
||||||
share: {
|
share: {
|
||||||
@@ -116,10 +122,10 @@ Here is a simple example of a shared textarea
|
|||||||
}).then(function (y) {
|
}).then(function (y) {
|
||||||
// The Yjs instance `y` is available
|
// The Yjs instance `y` is available
|
||||||
// y.share.* contains the shared types
|
// y.share.* contains the shared types
|
||||||
|
|
||||||
// Bind the textarea to y.share.textarea
|
// Bind `y.share.textarea` to `<textarea/>`
|
||||||
y.share.textarea.bind(document.querySelector('textarea'))
|
y.share.textarea.bind(document.querySelector('textarea'))
|
||||||
}
|
})
|
||||||
</script>
|
</script>
|
||||||
<textarea></textarea>
|
<textarea></textarea>
|
||||||
</body>
|
</body>
|
||||||
@@ -134,6 +140,9 @@ Report _any_ issues to the [Github issue page](https://github.com/y-js/yjs/issue
|
|||||||
# API
|
# API
|
||||||
|
|
||||||
### Y(options)
|
### Y(options)
|
||||||
|
* Y.extend(module1, module2, ..)
|
||||||
|
* Add extensions to Y
|
||||||
|
* `Y.extend(require('y-webrtc'))` has the same semantics as `require('y-webrtc')(Y)`
|
||||||
* options.db
|
* options.db
|
||||||
* Will be forwarded to the database adapter. Specify the database adaper on `options.db.name`.
|
* Will be forwarded to the database adapter. Specify the database adaper on `options.db.name`.
|
||||||
* Have a look at the used database adapter repository to see all available options.
|
* Have a look at the used database adapter repository to see all available options.
|
||||||
@@ -141,7 +150,8 @@ Report _any_ issues to the [Github issue page](https://github.com/y-js/yjs/issue
|
|||||||
* Will be forwarded to the connector adapter. Specify the connector adaper on `options.connector.name`.
|
* Will be forwarded to the connector adapter. Specify the connector adaper on `options.connector.name`.
|
||||||
* All our connectors implement a `room` property. Clients that specify the same room share the same data.
|
* All our connectors implement a `room` property. Clients that specify the same room share the same data.
|
||||||
* All of our connectors specify an `url` property that defines the connection endpoint of the used connector.
|
* All of our connectors specify an `url` property that defines the connection endpoint of the used connector.
|
||||||
* All of our connectors also have a default connection endpoint that you can use for development.
|
* All of our connectors also have a default connection endpoint that you can use for development.
|
||||||
|
* Set `options.connector.generateUserId = true` in order to genenerate a userid, instead of receiving one from the server. This way the `Y(..)` is immediately going to be resolved, without waiting for any confirmation from the server. Use with caution.
|
||||||
* Have a look at the used connector repository to see all available options.
|
* Have a look at the used connector repository to see all available options.
|
||||||
* options.sourceDir (browser only)
|
* options.sourceDir (browser only)
|
||||||
* Path where all y-* modules are stored
|
* Path where all y-* modules are stored
|
||||||
@@ -150,12 +160,12 @@ Report _any_ issues to the [Github issue page](https://github.com/y-js/yjs/issue
|
|||||||
* When using nodejs you need to manually extend Yjs:
|
* When using nodejs you need to manually extend Yjs:
|
||||||
```
|
```
|
||||||
var Y = require('yjs')
|
var Y = require('yjs')
|
||||||
// you have to require a db, connector, and *all* types you use!
|
// you have to require a db, connector, and *all* types you use!
|
||||||
require('y-memory')(Y)
|
require('y-memory')(Y)
|
||||||
require('y-webrtc')(Y)
|
require('y-webrtc')(Y)
|
||||||
require('y-map')(Y)
|
require('y-map')(Y)
|
||||||
// ..
|
// ..
|
||||||
```
|
```
|
||||||
* options.share
|
* options.share
|
||||||
* Specify on `options.share[arbitraryName]` types that are shared among all users.
|
* Specify on `options.share[arbitraryName]` types that are shared among all users.
|
||||||
* E.g. Specify `options.share[arbitraryName] = 'Array'` to require y-array and create an y-array type on `y.share[arbitraryName]`.
|
* E.g. Specify `options.share[arbitraryName] = 'Array'` to require y-array and create an y-array type on `y.share[arbitraryName]`.
|
||||||
@@ -195,61 +205,46 @@ The promise returns an instance of Y. We denote it with a lower case `y`.
|
|||||||
* Force to disconnect this instance from the other instances
|
* Force to disconnect this instance from the other instances
|
||||||
* y.connector.reconnect()
|
* y.connector.reconnect()
|
||||||
* Try to reconnect to the other instances (needs to be supported by the connector)
|
* Try to reconnect to the other instances (needs to be supported by the connector)
|
||||||
* Not supported by y-xmpp
|
* Not supported by y-xmpp
|
||||||
* y.destroy()
|
* y.close()
|
||||||
* Destroy this object.
|
* Destroy this object.
|
||||||
* Destroys all types (they will throw weird errors if you still use them)
|
* Destroys all types (they will throw weird errors if you still use them)
|
||||||
* Disconnects from the other instances (via connector)
|
* Disconnects from the other instances (via connector)
|
||||||
|
* Returns a promise
|
||||||
|
* y.destroy()
|
||||||
|
* calls y.close()
|
||||||
* Removes all data from the database
|
* Removes all data from the database
|
||||||
|
* Returns a promise
|
||||||
* y.db.stopGarbageCollector()
|
* y.db.stopGarbageCollector()
|
||||||
* Stop the garbage collector. Call y.db.garbageCollect() to continue garbage collection
|
* Stop the garbage collector. Call y.db.garbageCollect() to continue garbage collection
|
||||||
|
* y.db.gc :: Boolean
|
||||||
|
* Whether gc is turned on
|
||||||
* y.db.gcTimeout :: Number (defaults to 50000 ms)
|
* y.db.gcTimeout :: Number (defaults to 50000 ms)
|
||||||
* Time interval between two garbage collect cycles
|
* Time interval between two garbage collect cycles
|
||||||
* It is required that all instances exchanged all messages after two garbage collect cycles (after 100000 ms per default)
|
* It is required that all instances exchanged all messages after two garbage collect cycles (after 100000 ms per default)
|
||||||
* y.db.userId :: String
|
* y.db.userId :: String
|
||||||
* The used user id for this client. **Never overwrite this**
|
* The used user id for this client. **Never overwrite this**
|
||||||
|
|
||||||
## Changelog
|
### Logging
|
||||||
|
Yjs uses [debug](https://github.com/visionmedia/debug) for logging. The flag
|
||||||
|
`y*` enables logging for all y-* components. You can selectively remove
|
||||||
|
components you are not interested in: E.g. The flag `y*,-y:connector-message`
|
||||||
|
will not log the long `y:connector-message` messages.
|
||||||
|
|
||||||
### 12.0.0
|
##### Enable logging in Node.js
|
||||||
* **Types are synchronous and never return a promise (except explicitly stated)**
|
```sh
|
||||||
* `y.share.map.get('map type') // => returns a y-map instead of a promise`
|
DEBUG=y* node app.js
|
||||||
* The event property `oldValues`, and `values` contain a list of values (without wrapper)
|
```
|
||||||
* Support for the [y-leveldb](https://github.com/y-js/y-leveldb) database adapter
|
|
||||||
* [y-richtext](https://github.com/y-js/y-richtext) supports Quill@1.0.0-rc.2
|
|
||||||
* Only the types are affected by this release. You have to upgrade y-array@10.0.0, y-map@10.0.0, y-richtext@9.0.0, and y-xml@10.0.0
|
|
||||||
|
|
||||||
### 11.0.0
|
Remove the colors in order to log to a file:
|
||||||
|
```sh
|
||||||
* **All types return a single event instead of list of events**
|
DEBUG_COLORS=0 DEBUG=y* node app.js > log
|
||||||
* Insert events contain a list of values
|
```
|
||||||
* Improved performance for large insertions & deletions
|
|
||||||
* Several bugfixes (offline editing related)
|
|
||||||
* Native support for node 4 (see #49)
|
|
||||||
|
|
||||||
### 10.0.0
|
|
||||||
|
|
||||||
* Support for more complex types (a type can be a composition of several types)
|
|
||||||
* Fixes several memory leaks
|
|
||||||
|
|
||||||
### 9.0.0
|
|
||||||
There were several rolling updates from 0.6 to 0.8. We consider Yjs stable since a long time,
|
|
||||||
and intend to continue stable releases. From this release forward y-* modules will implement peer-dependencies for npm, and dependencies for bower.
|
|
||||||
Furthermore, incompatible yjs instances throw errors now when syncing - this feature was influenced by #48. The versioning jump was influenced by react (see [here](https://facebook.github.io/react/blog/2016/02/19/new-versioning-scheme.html))
|
|
||||||
|
|
||||||
|
|
||||||
### 0.6.0
|
|
||||||
This is a complete rewrite of the 0.5 version of Yjs. Since Yjs 0.6.0 it is possible to work asynchronously on a persistent database, which enables offline support.
|
|
||||||
* Switched to semver versioning
|
|
||||||
* Requires a promise implementation in environment (es6 promises suffice, included in all the major browsers). Otherwise you have to include a polyfill
|
|
||||||
* Y.Object has been renamed to Y.Map
|
|
||||||
* Y.Map exchanges `.val(name [, value])` in favor of `.set(name, value)` and `.get(name)`
|
|
||||||
* Y.Map `.get(name)` returns a promise, if the value is a custom type
|
|
||||||
* The Connector definition slightly changed (I'll update the wiki)
|
|
||||||
* The Type definitions completely changed, so you have to rewrite them (I'll rewrite the article in the wiki)
|
|
||||||
* Support for several packaging systems
|
|
||||||
* Flowtype
|
|
||||||
|
|
||||||
|
##### Enable logging in the browser
|
||||||
|
```js
|
||||||
|
localStorage.debug = 'y*'
|
||||||
|
```
|
||||||
|
|
||||||
## Contribution
|
## Contribution
|
||||||
I created this framework during my bachelor thesis at the chair of computer science 5 [(i5)](http://dbis.rwth-aachen.de/cms), RWTH University. Since December 2014 I'm working on Yjs as a part of my student worker job at the i5.
|
I created this framework during my bachelor thesis at the chair of computer science 5 [(i5)](http://dbis.rwth-aachen.de/cms), RWTH University. Since December 2014 I'm working on Yjs as a part of my student worker job at the i5.
|
||||||
@@ -258,7 +253,3 @@ I created this framework during my bachelor thesis at the chair of computer scie
|
|||||||
Yjs is licensed under the [MIT License](./LICENSE).
|
Yjs is licensed under the [MIT License](./LICENSE).
|
||||||
|
|
||||||
<yjs@dbis.rwth-aachen.de>
|
<yjs@dbis.rwth-aachen.de>
|
||||||
|
|
||||||
[ShareJs]: https://github.com/share/ShareJS
|
|
||||||
[OpenCoweb]: https://github.com/opencoweb/coweb/wiki
|
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "yjs",
|
"name": "yjs",
|
||||||
"version": "12.0.4",
|
"version": "12.1.6",
|
||||||
"homepage": "y-js.org",
|
"homepage": "y-js.org",
|
||||||
"authors": [
|
"authors": [
|
||||||
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"
|
||||||
|
|||||||
Reference in New Issue
Block a user