update quill example
This commit is contained in:
parent
59d859b38b
commit
4726c71dd0
@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<!-- 1.0.0-rc.0 does currently not include dist files! We are using the hosted version instead -->
|
<!-- 1.0.0-rc.0 does currently not include dist files! We are using the hosted version instead -->
|
||||||
<!--link rel="stylesheet" href="../bower_components/quill/dist/quill.snow.css" /-->
|
<!--link rel="stylesheet" href="../bower_components/quill/dist/quill.snow.css" /-->
|
||||||
<link href="//cdn.quilljs.com/1.0.0-rc.0/quill.snow.css" rel="stylesheet">
|
<link href="//cdn.quilljs.com/1.0.0-rc.2/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/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">
|
<link href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/styles/monokai-sublime.min.css" rel="stylesheet">
|
||||||
<style>
|
<style>
|
||||||
@ -21,7 +21,7 @@
|
|||||||
|
|
||||||
<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/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="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.2.0/highlight.min.js" type="text/javascript"></script>
|
||||||
<script src="//cdn.quilljs.com/1.0.0-rc.0/quill.js"></script>
|
<script src="//cdn.quilljs.com/1.0.0-rc.2/quill.js"></script>
|
||||||
<!-- 1.0.0-rc.0 does currently not include dist files! We are using the hosted version instead (see above)
|
<!-- 1.0.0-rc.0 does currently 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/quill/dist/quill.js"></script>
|
||||||
-->
|
-->
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
"y-text": "latest",
|
"y-text": "latest",
|
||||||
"y-indexeddb": "latest",
|
"y-indexeddb": "latest",
|
||||||
"y-xml": "latest",
|
"y-xml": "latest",
|
||||||
"quill": "^1.0.0-rc.0",
|
"quill": "^1.0.0-rc.2",
|
||||||
"ace": "~1.2.3",
|
"ace": "~1.2.3",
|
||||||
"ace-builds": "~1.2.3",
|
"ace-builds": "~1.2.3",
|
||||||
"jquery": "~2.2.2",
|
"jquery": "~2.2.2",
|
||||||
|
35
README.md
35
README.md
@ -39,6 +39,7 @@ You are not limited to use a specific database to store the shared data. We prov
|
|||||||
|----------------|-----------------------------------|
|
|----------------|-----------------------------------|
|
||||||
|[memory](https://github.com/y-js/y-memory) | In-memory storage. |
|
|[memory](https://github.com/y-js/y-memory) | In-memory storage. |
|
||||||
|[indexeddb](https://github.com/y-js/y-indexeddb) | Offline storage for the browser |
|
|[indexeddb](https://github.com/y-js/y-indexeddb) | Offline storage for the browser |
|
||||||
|
|[leveldb](https://github.com/y-js/y-leveldb) | Persistent storage for node apps |
|
||||||
|
|
||||||
The advantages over similar frameworks are support for
|
The advantages over similar frameworks are support for
|
||||||
* .. P2P message propagation and arbitrary communication protocols
|
* .. P2P message propagation and arbitrary communication protocols
|
||||||
@ -46,26 +47,28 @@ The advantages over similar frameworks are support for
|
|||||||
* .. offline support: Changes are stored persistently and only relevant changes are propagated on rejoin
|
* .. offline support: Changes are stored persistently and only relevant changes are propagated on rejoin
|
||||||
* .. Intention Preservation: When working on Text, the intention of your changes are preserved. This is particularily important when working offline. Every type has a notion on how we define Intention Preservation on it.
|
* .. Intention Preservation: When working on Text, the intention of your changes are preserved. This is particularily important when working offline. Every type has a notion on how we define Intention Preservation on it.
|
||||||
|
|
||||||
## Use it!
|
## Use it!
|
||||||
Install yjs and its modules with [bower](http://bower.io/), or with [npm](https://www.npmjs.org/package/yjs).
|
Install Yjs, and its modules with [bower](http://bower.io/), or [npm](https://www.npmjs.org/package/yjs).
|
||||||
|
|
||||||
### Bower
|
### Bower
|
||||||
```
|
```
|
||||||
bower install yjs --save
|
bower install --save yjs y-array % add all y-* modules you want to use
|
||||||
```
|
```
|
||||||
Then you include the libraries directly from the installation folder.
|
You only need to include the `y.js` file. Yjs is able to automatically require missing modules.
|
||||||
```
|
```
|
||||||
<script src="./bower_components/yjs/y.js"></script>
|
<script src="./bower_components/yjs/y.js"></script>
|
||||||
```
|
```
|
||||||
|
|
||||||
### Npm
|
### Npm
|
||||||
```
|
```
|
||||||
npm install yjs --save
|
npm install --save yjs % add all y-* modules you want to use
|
||||||
```
|
```
|
||||||
|
|
||||||
And use it like this with *npm*:
|
When using npm, you also need to import all modules you want to use.
|
||||||
```
|
```
|
||||||
Y = require("yjs");
|
Y = require('yjs')
|
||||||
|
require('y-array')(Y) // add the y-array type to Yjs
|
||||||
|
// require('y-websockets-client')(Y) // do the same for all modules you want to use
|
||||||
```
|
```
|
||||||
|
|
||||||
# Text editing example
|
# Text editing example
|
||||||
@ -74,6 +77,7 @@ Y({
|
|||||||
db: {
|
db: {
|
||||||
name: 'memory' // store in memory.
|
name: 'memory' // store in memory.
|
||||||
// name: 'indexeddb'
|
// name: 'indexeddb'
|
||||||
|
// name: 'leveldb'
|
||||||
},
|
},
|
||||||
connector: {
|
connector: {
|
||||||
name: 'websockets-client', // choose the websockets connector
|
name: 'websockets-client', // choose the websockets connector
|
||||||
@ -81,11 +85,11 @@ Y({
|
|||||||
// name: 'xmpp'
|
// name: 'xmpp'
|
||||||
room: 'Textarea-example-dev'
|
room: 'Textarea-example-dev'
|
||||||
},
|
},
|
||||||
sourceDir: '/bower_components', // location of the y-* modules
|
sourceDir: '/bower_components', // location of the y-* modules (bower only)
|
||||||
share: {
|
share: {
|
||||||
textarea: 'Text' // y.share.textarea is of type Y.Text
|
textarea: 'Text' // y.share.textarea is of type Y.Text
|
||||||
}
|
}
|
||||||
// types: ['Richtext', 'Array'] // optional list of types you want to import
|
// types: ['Richtext', 'Array'] // optional list of types you want to import (bower only)
|
||||||
}).then(function (y) {
|
}).then(function (y) {
|
||||||
// bind the textarea to a shared text element
|
// bind the textarea to a shared text element
|
||||||
y.share.textarea.bind(document.getElementById('textfield'))
|
y.share.textarea.bind(document.getElementById('textfield'))
|
||||||
@ -174,14 +178,19 @@ The promise returns an instance of Y. We denote it with a lower case `y`.
|
|||||||
There are some friendly people on [](https://gitter.im/y-js/yjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) who may help you with your problem, and answer your questions.
|
There are some friendly people on [](https://gitter.im/y-js/yjs?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge) who may help you with your problem, and answer your questions.
|
||||||
|
|
||||||
Please report _any_ issues to the [Github issue page](https://github.com/y-js/yjs/issues)! I try to fix them very soon, if possible.
|
Please report _any_ issues to the [Github issue page](https://github.com/y-js/yjs/issues)! I try to fix them very soon, if possible.
|
||||||
If you want to see an issue fixed, please subscribe to the thread (or remind me via gitter).
|
|
||||||
|
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
### 12.0.0
|
||||||
|
* **Types work are synchronous and never return a promise (except explicitly stated)**
|
||||||
|
* `y.share.map.get('map type') // => returns a Y.Map instead of a promise`
|
||||||
|
* The event property `oldValues` also contains a list of types/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
|
||||||
|
|
||||||
### 11.0.0
|
### 11.0.0
|
||||||
|
|
||||||
* **All types now return a single event instead of list of events**
|
* **All types return a single event instead of list of events**
|
||||||
* Insert events contain a list of values
|
* Insert events contain a list of values
|
||||||
* Improved performance for large insertions & deletions
|
* Improved performance for large insertions & deletions
|
||||||
* Several bugfixes (offline editing related)
|
* Several bugfixes (offline editing related)
|
||||||
@ -195,7 +204,7 @@ If you want to see an issue fixed, please subscribe to the thread (or remind me
|
|||||||
### 9.0.0
|
### 9.0.0
|
||||||
There were several rolling updates from 0.6 to 0.8. We consider Yjs stable since a long time,
|
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.
|
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 will now throw errors 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))
|
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
|
### 0.6.0
|
||||||
|
138
y.es6
138
y.es6
@ -1089,6 +1089,53 @@ module.exports = function (Y /* :any */) {
|
|||||||
}, 0)
|
}, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
Get a created/initialized type.
|
||||||
|
*/
|
||||||
|
getType (id) {
|
||||||
|
return this.initializedTypes[JSON.stringify(id)]
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Init type. This is called when a remote operation is retrieved, and transformed to a type
|
||||||
|
TODO: delete type from store.initializedTypes[id] when corresponding id was deleted!
|
||||||
|
*/
|
||||||
|
* initType (id, args) {
|
||||||
|
var sid = JSON.stringify(id)
|
||||||
|
var t = this.store.initializedTypes[sid]
|
||||||
|
if (t == null) {
|
||||||
|
var op/* :MapStruct | ListStruct */ = yield* this.getOperation(id)
|
||||||
|
if (op != null) {
|
||||||
|
t = yield* Y[op.type].typeDefinition.initType.call(this, this.store, op, args)
|
||||||
|
this.store.initializedTypes[sid] = t
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return t
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Create type. This is called when the local user creates a type (which is a synchronous action)
|
||||||
|
*/
|
||||||
|
createType (typedefinition, id) {
|
||||||
|
var structname = typedefinition[0].struct
|
||||||
|
id = id || this.getNextOpId(1)
|
||||||
|
var op = Y.Struct[structname].create(id)
|
||||||
|
op.type = typedefinition[0].name
|
||||||
|
|
||||||
|
/* TODO: implement for y-xml support
|
||||||
|
if (typedefinition[0].appendAdditionalInfo != null) {
|
||||||
|
yield* typedefinition[0].appendAdditionalInfo.call(this, op, typedefinition[1])
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
this.requestTransaction(function * () {
|
||||||
|
if (op.id[0] === '_') {
|
||||||
|
yield* this.setOperation(op)
|
||||||
|
} else {
|
||||||
|
yield* this.applyCreatedOperations([op])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
var t = Y[op.type].typeDefinition.createType(this, op, typedefinition[1])
|
||||||
|
this.initializedTypes[JSON.stringify(op.id)] = t
|
||||||
|
return t
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Y.AbstractDatabase = AbstractDatabase
|
Y.AbstractDatabase = AbstractDatabase
|
||||||
}
|
}
|
||||||
@ -1590,57 +1637,6 @@ module.exports = function (Y/* :any */) {
|
|||||||
os: Store;
|
os: Store;
|
||||||
ss: Store;
|
ss: Store;
|
||||||
*/
|
*/
|
||||||
/*
|
|
||||||
Get a type based on the id of its model.
|
|
||||||
If it does not exist yes, create it.
|
|
||||||
TODO: delete type from store.initializedTypes[id] when corresponding id was deleted!
|
|
||||||
*/
|
|
||||||
* getType (id, args) {
|
|
||||||
var sid = JSON.stringify(id)
|
|
||||||
var t = this.store.initializedTypes[sid]
|
|
||||||
if (t == null) {
|
|
||||||
var op/* :MapStruct | ListStruct */ = yield* this.getOperation(id)
|
|
||||||
if (op != null) {
|
|
||||||
t = yield* Y[op.type].typeDefinition.initType.call(this, this.store, op, args)
|
|
||||||
this.store.initializedTypes[sid] = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return t
|
|
||||||
}
|
|
||||||
* createType (typedefinition, id) {
|
|
||||||
var structname = typedefinition[0].struct
|
|
||||||
id = id || this.store.getNextOpId(1)
|
|
||||||
var op
|
|
||||||
if (id[0] === '_') {
|
|
||||||
op = yield* this.getOperation(id)
|
|
||||||
} else {
|
|
||||||
op = Y.Struct[structname].create(id)
|
|
||||||
op.type = typedefinition[0].name
|
|
||||||
}
|
|
||||||
if (typedefinition[0].appendAdditionalInfo != null) {
|
|
||||||
yield* typedefinition[0].appendAdditionalInfo.call(this, op, typedefinition[1])
|
|
||||||
}
|
|
||||||
if (op[0] === '_') {
|
|
||||||
yield* this.setOperation(op)
|
|
||||||
} else {
|
|
||||||
yield* this.applyCreatedOperations([op])
|
|
||||||
}
|
|
||||||
return yield* this.getType(id, typedefinition[1])
|
|
||||||
}
|
|
||||||
/* createType (typedefinition, id) {
|
|
||||||
var structname = typedefinition[0].struct
|
|
||||||
id = id || this.store.getNextOpId(1)
|
|
||||||
var op = Y.Struct[structname].create(id)
|
|
||||||
op.type = typedefinition[0].name
|
|
||||||
if (typedefinition[0].appendAdditionalInfo != null) {
|
|
||||||
yield* typedefinition[0].appendAdditionalInfo.call(this, op, typedefinition[1])
|
|
||||||
}
|
|
||||||
// yield* this.applyCreatedOperations([op])
|
|
||||||
yield* Y.Struct[op.struct].execute.call(this, op)
|
|
||||||
yield* this.addOperation(op)
|
|
||||||
yield* this.store.operationAdded(this, op)
|
|
||||||
return yield* this.getType(id, typedefinition[1])
|
|
||||||
}*/
|
|
||||||
/*
|
/*
|
||||||
Apply operations that this user created (no remote ones!)
|
Apply operations that this user created (no remote ones!)
|
||||||
* does not check for Struct.*.requiredOps()
|
* does not check for Struct.*.requiredOps()
|
||||||
@ -2843,7 +2839,13 @@ module.exports = function (Y /* : any*/) {
|
|||||||
// finished with remaining operations
|
// finished with remaining operations
|
||||||
self.waiting.push(d)
|
self.waiting.push(d)
|
||||||
}
|
}
|
||||||
checkDelete(op)
|
if (op.key == null) {
|
||||||
|
// deletes in list
|
||||||
|
checkDelete(op)
|
||||||
|
} else {
|
||||||
|
// deletes in map
|
||||||
|
this.waiting.push(op)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this.waiting.push(op)
|
this.waiting.push(op)
|
||||||
}
|
}
|
||||||
@ -2892,7 +2894,11 @@ module.exports = function (Y /* : any*/) {
|
|||||||
var o = this.waiting[i]
|
var o = this.waiting[i]
|
||||||
if (o.struct === 'Insert') {
|
if (o.struct === 'Insert') {
|
||||||
var _o = yield* transaction.getInsertion(o.id)
|
var _o = yield* transaction.getInsertion(o.id)
|
||||||
if (!Y.utils.compareIds(_o.id, o.id)) {
|
if (_o.parentSub != null && _o.left != null) {
|
||||||
|
// if o is an insertion of a map struc (parentSub is defined), then it shouldn't be necessary to compute left
|
||||||
|
this.waiting.splice(i,1)
|
||||||
|
i-- // update index
|
||||||
|
} else if (!Y.utils.compareIds(_o.id, o.id)) {
|
||||||
// o got extended
|
// o got extended
|
||||||
o.left = [o.id[0], o.id[1] - 1]
|
o.left = [o.id[0], o.id[1] - 1]
|
||||||
} else if (_o.left == null) {
|
} else if (_o.left == null) {
|
||||||
@ -3052,6 +3058,14 @@ module.exports = function (Y /* : any*/) {
|
|||||||
}
|
}
|
||||||
Y.utils.EventHandler = EventHandler
|
Y.utils.EventHandler = EventHandler
|
||||||
|
|
||||||
|
/*
|
||||||
|
Default class of custom types!
|
||||||
|
*/
|
||||||
|
class CustomType {
|
||||||
|
|
||||||
|
}
|
||||||
|
Y.utils.CustomType = CustomType
|
||||||
|
|
||||||
/*
|
/*
|
||||||
A wrapper for the definition of a custom type.
|
A wrapper for the definition of a custom type.
|
||||||
Every custom type must have three properties:
|
Every custom type must have three properties:
|
||||||
@ -3063,7 +3077,7 @@ module.exports = function (Y /* : any*/) {
|
|||||||
* class
|
* class
|
||||||
- the constructor of the custom type (e.g. in order to inherit from a type)
|
- the constructor of the custom type (e.g. in order to inherit from a type)
|
||||||
*/
|
*/
|
||||||
class CustomType { // eslint-disable-line
|
class CustomTypeDefinition { // eslint-disable-line
|
||||||
/* ::
|
/* ::
|
||||||
struct: any;
|
struct: any;
|
||||||
initType: any;
|
initType: any;
|
||||||
@ -3074,12 +3088,14 @@ module.exports = function (Y /* : any*/) {
|
|||||||
if (def.struct == null ||
|
if (def.struct == null ||
|
||||||
def.initType == null ||
|
def.initType == null ||
|
||||||
def.class == null ||
|
def.class == null ||
|
||||||
def.name == null
|
def.name == null ||
|
||||||
|
def.createType == null
|
||||||
) {
|
) {
|
||||||
throw new Error('Custom type was not initialized correctly!')
|
throw new Error('Custom type was not initialized correctly!')
|
||||||
}
|
}
|
||||||
this.struct = def.struct
|
this.struct = def.struct
|
||||||
this.initType = def.initType
|
this.initType = def.initType
|
||||||
|
this.createType = def.createType
|
||||||
this.class = def.class
|
this.class = def.class
|
||||||
this.name = def.name
|
this.name = def.name
|
||||||
if (def.appendAdditionalInfo != null) {
|
if (def.appendAdditionalInfo != null) {
|
||||||
@ -3091,13 +3107,13 @@ module.exports = function (Y /* : any*/) {
|
|||||||
this.parseArguments.typeDefinition = this
|
this.parseArguments.typeDefinition = this
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Y.utils.CustomType = CustomType
|
Y.utils.CustomTypeDefinition = CustomTypeDefinition
|
||||||
|
|
||||||
Y.utils.isTypeDefinition = function isTypeDefinition (v) {
|
Y.utils.isTypeDefinition = function isTypeDefinition (v) {
|
||||||
if (v != null) {
|
if (v != null) {
|
||||||
if (v instanceof Y.utils.CustomType) return [v]
|
if (v instanceof Y.utils.CustomTypeDefinition) return [v]
|
||||||
else if (v.constructor === Array && v[0] instanceof Y.utils.CustomType) return v
|
else if (v.constructor === Array && v[0] instanceof Y.utils.CustomTypeDefinition) return v
|
||||||
else if (v instanceof Function && v.typeDefinition instanceof Y.utils.CustomType) return [v.typeDefinition]
|
else if (v instanceof Function && v.typeDefinition instanceof Y.utils.CustomTypeDefinition) return [v.typeDefinition]
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -3357,7 +3373,7 @@ module.exports = Y
|
|||||||
Y.requiringModules = requiringModules
|
Y.requiringModules = requiringModules
|
||||||
|
|
||||||
Y.extend = function (name, value) {
|
Y.extend = function (name, value) {
|
||||||
if (value instanceof Y.utils.CustomType) {
|
if (value instanceof Y.utils.CustomTypeDefinition) {
|
||||||
Y[name] = value.parseArguments
|
Y[name] = value.parseArguments
|
||||||
} else {
|
} else {
|
||||||
Y[name] = value
|
Y[name] = value
|
||||||
@ -3494,7 +3510,7 @@ class YConfig {
|
|||||||
var type = Y[typeName]
|
var type = Y[typeName]
|
||||||
var typedef = type.typeDefinition
|
var typedef = type.typeDefinition
|
||||||
var id = ['_', typedef.struct + '_' + typeName + '_' + propertyname + '_' + typeConstructor]
|
var id = ['_', typedef.struct + '_' + typeName + '_' + propertyname + '_' + typeConstructor]
|
||||||
share[propertyname] = yield* this.createType(type.apply(typedef, args), id)
|
share[propertyname] = this.store.createType(type.apply(typedef, args), id)
|
||||||
}
|
}
|
||||||
this.store.whenTransactionsFinished()
|
this.store.whenTransactionsFinished()
|
||||||
.then(callback)
|
.then(callback)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user