HackMD/public/vendor/ot/wrapped-operation.js
2016-11-14 21:13:02 +08:00

80 lines
No EOL
2 KiB
JavaScript

if (typeof ot === 'undefined') {
// Export for browsers
var ot = {};
}
ot.WrappedOperation = (function (global) {
'use strict';
// A WrappedOperation contains an operation and corresponing metadata.
function WrappedOperation (operation, meta) {
this.wrapped = operation;
this.meta = meta;
}
WrappedOperation.prototype.apply = function () {
return this.wrapped.apply.apply(this.wrapped, arguments);
};
WrappedOperation.prototype.invert = function () {
var meta = this.meta;
return new WrappedOperation(
this.wrapped.invert.apply(this.wrapped, arguments),
meta && typeof meta === 'object' && typeof meta.invert === 'function' ?
meta.invert.apply(meta, arguments) : meta
);
};
// Copy all properties from source to target.
function copy (source, target) {
for (var key in source) {
if (source.hasOwnProperty(key)) {
target[key] = source[key];
}
}
}
function composeMeta (a, b) {
if (a && typeof a === 'object') {
if (typeof a.compose === 'function') { return a.compose(b); }
var meta = {};
copy(a, meta);
copy(b, meta);
return meta;
}
return b;
}
WrappedOperation.prototype.compose = function (other) {
return new WrappedOperation(
this.wrapped.compose(other.wrapped),
composeMeta(this.meta, other.meta)
);
};
function transformMeta (meta, operation) {
if (meta && typeof meta === 'object') {
if (typeof meta.transform === 'function') {
return meta.transform(operation);
}
}
return meta;
}
WrappedOperation.transform = function (a, b) {
var transform = a.wrapped.constructor.transform;
var pair = transform(a.wrapped, b.wrapped);
return [
new WrappedOperation(pair[0], transformMeta(a.meta, b.wrapped)),
new WrappedOperation(pair[1], transformMeta(b.meta, a.wrapped))
];
};
return WrappedOperation;
}(this));
// Export for CommonJS
if (typeof module === 'object') {
module.exports = ot.WrappedOperation;
}