Compare commits

...

8 Commits

Author SHA1 Message Date
Kevin Jahns
92b9cb8143 Deploy 12.1.3 2016-11-22 13:12:32 +01:00
Kevin Jahns
5dad1ed410 update webworker example 2016-11-21 16:28:20 +01:00
Kevin Jahns
b613630cef improved examples 2016-11-16 18:08:01 +01:00
Kevin Jahns
afa05b62a1 added sw example 2016-11-14 16:29:04 +01:00
Kevin Jahns
957d650f81 Deploy 12.1.2 2016-11-10 17:01:53 +01:00
Kevin Jahns
9769968c1c Deploy 12.1.1 2016-11-09 14:26:32 +01:00
Kevin Jahns
1e30a877e6 merge 2016-11-09 14:17:00 +01:00
Kevin Jahns
549ab76b42 Deploy 12.0.4 2016-10-12 15:52:00 +02:00
8 changed files with 203 additions and 65 deletions

View 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>

View 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)
})

View File

@@ -198,14 +198,20 @@ The promise returns an instance of Y. We denote it with a lower case `y`.
* Force to disconnect this instance from the other instances
* y.connector.reconnect()
* Try to reconnect to the other instances (needs to be supported by the connector)
* Not supported by y-xmpp
* y.destroy()
* Not supported by y-xmpp
* y.close()
* Destroy this object.
* Destroys all types (they will throw weird errors if you still use them)
* Disconnects from the other instances (via connector)
* Returns a promise
* y.destroy()
* calls y.close()
* Removes all data from the database
* Returns a promise
* y.db.stopGarbageCollector()
* 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)
* 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)

View File

@@ -1,6 +1,6 @@
{
"name": "yjs",
"version": "12.1.0",
"version": "12.1.3",
"homepage": "y-js.org",
"authors": [
"Kevin Jahns <kevin.jahns@rwth-aachen.de>"

170
y.es6
View File

@@ -1,4 +1,10 @@
(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/**
* yjs - A framework for real-time p2p shared editing on any data
* @version v12.1.2
* @link http://y-js.org
* @license MIT
*/
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Y = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/* @flow */
'use strict'
@@ -61,6 +67,15 @@ module.exports = function (Y/* :any */) {
this.authInfo = opts.auth || null
this.checkAuth = opts.checkAuth || function () { return Promise.resolve('write') } // default is everyone has write access
}
resetAuth (auth) {
if (this.authInfo !== auth) {
this.authInfo = auth
this.broadcast({
type: 'auth',
auth: this.authInfo
})
}
}
reconnect () {
}
disconnect () {
@@ -145,13 +160,8 @@ module.exports = function (Y/* :any */) {
this.whenSyncedListeners.push(f)
}
}
/*
returns false, if there is no sync target
true otherwise
*/
findNextSyncTarget () {
if (this.currentSyncTarget != null || this.isSynced) {
if (this.currentSyncTarget != null) {
return // "The current sync has not finished!"
}
@@ -177,16 +187,20 @@ module.exports = function (Y/* :any */) {
})
})
} else {
this.y.db.requestTransaction(function *() {
// it is crucial that isSynced is set at the time garbageCollectAfterSync is called
conn.isSynced = true
yield* this.garbageCollectAfterSync()
// call whensynced listeners
for (var f of conn.whenSyncedListeners) {
f()
}
conn.whenSyncedListeners = []
})
if (!conn.isSynced) {
this.y.db.requestTransaction(function *() {
if (!conn.isSynced) {
// it is crucial that isSynced is set at the time garbageCollectAfterSync is called
conn.isSynced = true
yield* this.garbageCollectAfterSync()
// call whensynced listeners
for (var f of conn.whenSyncedListeners) {
f()
}
conn.whenSyncedListeners = []
}
})
}
}
}
send (uid, message) {
@@ -298,7 +312,6 @@ module.exports = function (Y/* :any */) {
type: 'sync done'
})
}
conn._setSyncedWith(sender)
})
} else if (message.type === 'sync step 2' && canWrite(auth)) {
let conn = this
@@ -714,12 +727,18 @@ module.exports = function (Y /* :any */) {
}
this.gc1 = [] // first stage
this.gc2 = [] // second stage -> after that, remove the op
this.gcTimeout = !opts.gcTimeout ? 50000 : opts.gcTimeouts
this.gc = opts.gc == null || opts.gc
if (this.gc) {
this.gcTimeout = !opts.gcTimeout ? 50000 : opts.gcTimeout
} else {
this.gcTimeout = -1
}
function garbageCollect () {
return os.whenTransactionsFinished().then(function () {
if (os.gc1.length > 0 || os.gc2.length > 0) {
if (!os.y.isConnected()) {
console.warn('gc should be empty when disconnected!')
if (!os.y.connector.isSynced) {
console.warn('gc should be empty when not synced!')
}
return new Promise((resolve) => {
os.requestTransaction(function * () {
@@ -788,7 +807,7 @@ module.exports = function (Y /* :any */) {
clearInterval(this.repairCheckIntervalHandler)
}
queueGarbageCollector (id) {
if (this.y.isConnected()) {
if (this.y.connector.isSynced && this.gc) {
this.gc1.push(id)
}
}
@@ -821,6 +840,8 @@ module.exports = function (Y /* :any */) {
}
stopGarbageCollector () {
var self = this
this.gc = false
this.gcTimeout = -1
return new Promise(function (resolve) {
self.requestTransaction(function * () {
var ungc /* :Array<Struct> */ = self.gc1.concat(self.gc2)
@@ -843,7 +864,7 @@ module.exports = function (Y /* :any */) {
TODO: rename this function
Rulez:
* Only gc if this user is online
* Only gc if this user is online & gc turned on
* The most left element in a list must not be gc'd.
=> There is at least one element in the list
@@ -852,7 +873,9 @@ module.exports = function (Y /* :any */) {
* addToGarbageCollector (op, left) {
if (
op.gc == null &&
op.deleted === true
op.deleted === true &&
this.store.gc &&
this.store.y.connector.isSynced
) {
var gc = false
if (left != null && left.deleted === true) {
@@ -878,10 +901,7 @@ module.exports = function (Y /* :any */) {
this.gc2 = this.gc2.filter(filter)
delete op.gc
}
* destroy () {
clearInterval(this.gcInterval)
this.gcInterval = null
this.stopRepairCheck()
destroyTypes () {
for (var key in this.initializedTypes) {
var type = this.initializedTypes[key]
if (type._destroy != null) {
@@ -891,6 +911,11 @@ module.exports = function (Y /* :any */) {
}
}
}
* destroy () {
clearInterval(this.gcInterval)
this.gcInterval = null
this.stopRepairCheck()
}
setUserId (userId) {
if (!this.userIdPromise.inProgress) {
this.userIdPromise.inProgress = true
@@ -1073,8 +1098,7 @@ module.exports = function (Y /* :any */) {
*/
* operationAdded (transaction, op) {
if (op.struct === 'Delete') {
var target = yield* transaction.getInsertion(op.target)
var type = this.initializedTypes[JSON.stringify(target.parent)]
var type = this.initializedTypes[JSON.stringify(op.targetParent)]
if (type != null) {
yield* type._changed(transaction, op)
}
@@ -1142,10 +1166,8 @@ module.exports = function (Y /* :any */) {
resolve: resolve,
promise: promise
}
return promise
} else {
return this.transactionsFinished.promise
}
return this.transactionsFinished.promise
} else {
return Promise.resolve()
}
@@ -1261,7 +1283,11 @@ module.exports = function (Y/* :any */) {
*/
Delete: {
encode: function (op) {
return op
return {
target: op.target,
length: op.length || 0,
struct: 'Delete'
}
},
requiredOps: function (op) {
return [] // [op.target]
@@ -1739,7 +1765,7 @@ module.exports = function (Y/* :any */) {
send.push(Y.Struct[op.struct].encode(op))
}
}
if (!this.store.y.connector.isDisconnected() && send.length > 0) { // TODO: && !this.store.forwardAppliedOperations (but then i don't send delete ops)
if (this.store.y.connector.isSynced && send.length > 0) { // TODO: && !this.store.forwardAppliedOperations (but then i don't send delete ops)
// is connected, and this is not going to be send in addOperation
this.store.y.connector.broadcastOps(send)
}
@@ -1849,7 +1875,8 @@ module.exports = function (Y/* :any */) {
yield* this.store.operationAdded(this, {
struct: 'Delete',
target: target.id,
length: targetLength
length: targetLength,
targetParent: target.parent
})
}
// need to gc in the end!
@@ -2011,6 +2038,9 @@ module.exports = function (Y/* :any */) {
if (this.store.gc1.length > 0 || this.store.gc2.length > 0) {
console.warn('gc should be empty after sync')
}
if (!this.store.gc) {
return
}
yield* this.os.iterate(this, null, null, function * (op) {
if (op.gc) {
delete op.gc
@@ -2356,7 +2386,7 @@ module.exports = function (Y/* :any */) {
}
* addOperation (op) {
yield* this.os.put(op)
if (!this.store.y.connector.isDisconnected() && this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') {
if (this.store.y.connector.isSynced && this.store.forwardAppliedOperations && typeof op.id[1] !== 'string') {
// is connected, and this is not going to be send in addOperation
this.store.y.connector.broadcastOps([op])
}
@@ -2771,7 +2801,6 @@ module.exports = function (Y /* : any*/) {
destroy () {
super.destroy()
this.waiting = null
this.awaiting = null
this.onevent = null
}
/*
@@ -3485,7 +3514,12 @@ Y.extend = function (name, value) {
Y.requestModules = requestModules
function requestModules (modules) {
var sourceDir = Y.sourceDir || '/bower_components'
var sourceDir
if (Y.sourceDir === null) {
sourceDir = null
} else {
sourceDir = Y.sourceDir || '/bower_components'
}
// determine if this module was compiled for es5 or es6 (y.js vs. y.es6)
// if Insert.execute is a Function, then it isnt a generator..
// then load the es5(.js) files..
@@ -3498,10 +3532,11 @@ function requestModules (modules) {
if (requiringModules[module] == null) {
// module does not exist
if (typeof window !== 'undefined' && window.Y !== 'undefined') {
var imported = document.createElement('script')
imported.src = sourceDir + '/' + modulename + '/' + modulename + extention
document.head.appendChild(imported)
if (sourceDir != null) {
var imported = document.createElement('script')
imported.src = sourceDir + '/' + modulename + '/' + modulename + extention
document.head.appendChild(imported)
}
let requireModule = {}
requiringModules[module] = requireModule
requireModule.promise = new Promise(function (resolve) {
@@ -3550,7 +3585,7 @@ type YOptions = {
*/
function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
if (opts.sourceDir != null) {
if (opts.hasOwnProperty('sourceDir')) {
Y.sourceDir = opts.sourceDir
}
opts.types = opts.types != null ? opts.types : []
@@ -3564,7 +3599,6 @@ function Y (opts/* :YOptions */) /* :Promise<YConfig> */ {
else if (opts.connector.name == null) reject('You must specify connector name! (missing connector.name property)')
else if (opts.db == null) reject('You must specify a database! (missing db property)')
else if (opts.connector.name == null) reject('You must specify db name! (missing db.name property)')
else if (opts.share == null) reject('You must specify a set of shared types!')
else {
opts = Y.utils.copyObject(opts)
opts.connector = Y.utils.copyObject(opts.connector)
@@ -3595,6 +3629,7 @@ class YConfig {
this.options = opts
this.db = new Y[opts.db.name](this, opts.db)
this.connector = new Y[opts.connector.name](this, opts.connector)
this.connected = true
}
init (callback) {
var opts = this.options
@@ -3631,29 +3666,50 @@ class YConfig {
return this.connector.isSynced
}
disconnect () {
return this.connector.disconnect()
if (this.connected) {
this.connected = false
return this.connector.disconnect()
} else {
return Promise.resolve()
}
}
reconnect () {
return this.connector.reconnect()
if (!this.connected) {
this.connected = true
return this.connector.reconnect()
} else {
return Promise.resolve()
}
}
destroy () {
var self = this
return this.close().then(function () {
if (self.db.deleteDB != null) {
return self.db.deleteDB()
} else {
return Promise.resolve()
}
})
}
close () {
var self = this
this.share = null
if (this.connector.destroy != null) {
this.connector.destroy()
} else {
this.connector.disconnect()
}
var self = this
this.db.requestTransaction(function * () {
yield* self.db.destroy()
self.connector = null
self.db = null
return this.db.whenTransactionsFinished(function () {
this.db.destroyTypes()
// make sure to wait for all transactions before destroying the db
this.db.requestTransaction(function * () {
yield* self.db.destroy()
})
return this.db.whenTransactionsFinished()
})
}
}
if (typeof window !== 'undefined') {
window.Y = Y
}
},{"./Connector.js":1,"./Connectors/Test.js":2,"./Database.js":3,"./Struct.js":4,"./Transaction.js":5,"./Utils.js":6}]},{},[7])
},{"./Connector.js":1,"./Connectors/Test.js":2,"./Database.js":3,"./Struct.js":4,"./Transaction.js":5,"./Utils.js":6}]},{},[7])(7)
});

File diff suppressed because one or more lines are too long

12
y.js

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long