JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
/*!
|
2013-01-15 23:38:49 +00:00
|
|
|
* VisualEditor DataModel Transaction class.
|
2012-07-19 21:25:16 +00:00
|
|
|
*
|
2013-02-19 23:37:34 +00:00
|
|
|
* @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
|
2012-07-19 00:11:26 +00:00
|
|
|
* @license The MIT License (MIT); see LICENSE.txt
|
|
|
|
*/
|
|
|
|
|
2011-11-02 21:00:55 +00:00
|
|
|
/**
|
2012-06-20 01:20:28 +00:00
|
|
|
* DataModel transaction.
|
|
|
|
*
|
2011-11-02 21:00:55 +00:00
|
|
|
* @class
|
|
|
|
* @constructor
|
|
|
|
*/
|
2012-09-06 23:15:55 +00:00
|
|
|
ve.dm.Transaction = function VeDmTransaction() {
|
2012-06-20 01:20:28 +00:00
|
|
|
this.operations = [];
|
2011-11-22 22:57:23 +00:00
|
|
|
this.lengthDifference = 0;
|
2012-10-23 00:28:37 +00:00
|
|
|
this.applied = false;
|
2011-11-02 21:00:55 +00:00
|
|
|
};
|
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
/* Static Methods */
|
2011-11-02 21:00:55 +00:00
|
|
|
|
2011-11-04 21:06:06 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Generate a transaction that inserts data at an offset.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
|
|
|
* @static
|
2011-11-04 21:06:06 +00:00
|
|
|
* @method
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {ve.dm.Document} doc Document to create transaction for
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @param {number} offset Offset to insert at
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {Array} data Data to insert
|
2013-02-14 23:21:53 +00:00
|
|
|
* @returns {ve.dm.Transaction} Transaction that inserts data
|
2011-11-04 21:06:06 +00:00
|
|
|
*/
|
2013-09-18 14:38:46 +00:00
|
|
|
ve.dm.Transaction.newFromInsertion = function ( doc, offset, data ) {
|
|
|
|
var insertion, tx = new ve.dm.Transaction();
|
2012-06-20 01:20:28 +00:00
|
|
|
// Fix up the insertion
|
2013-09-18 14:38:46 +00:00
|
|
|
insertion = doc.fixupInsertion( data, offset );
|
2012-06-20 01:20:28 +00:00
|
|
|
// Retain up to insertion point, if needed
|
2013-04-26 18:41:27 +00:00
|
|
|
tx.pushRetain( insertion.offset );
|
2012-06-20 01:20:28 +00:00
|
|
|
// Insert data
|
2013-05-20 16:24:33 +00:00
|
|
|
tx.pushReplace( doc, insertion.offset, insertion.remove, insertion.data );
|
2012-06-20 01:20:28 +00:00
|
|
|
// Retain to end of document, if needed (for completeness)
|
2013-09-10 18:49:31 +00:00
|
|
|
tx.pushFinalRetain( doc, insertion.offset + insertion.remove );
|
2012-06-20 01:20:28 +00:00
|
|
|
return tx;
|
2011-11-02 21:00:55 +00:00
|
|
|
};
|
|
|
|
|
2011-11-17 22:42:18 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Generate a transaction that removes data from a range.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
|
|
|
* There are three possible results from a removal:
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
*
|
|
|
|
* - Remove content only
|
|
|
|
* - Occurs when the range starts and ends on elements of different type, depth or ancestry
|
|
|
|
* - Remove entire elements and their content
|
|
|
|
* - Occurs when the range spans across an entire element
|
|
|
|
* - Merge two elements by removing the end of one and the beginning of another
|
|
|
|
* - Occurs when the range starts and ends on elements of similar type, depth and ancestry
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
|
|
|
* This function uses the following logic to decide what to actually remove:
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
*
|
|
|
|
* 1. Elements are only removed if range being removed covers the entire element
|
|
|
|
* 2. Elements can only be merged if {@link ve.dm.Node#canBeMergedWith} returns true
|
|
|
|
* 3. Merges take place at the highest common ancestor
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-17 22:42:18 +00:00
|
|
|
* @method
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {ve.dm.Document} doc Document to create transaction for
|
|
|
|
* @param {ve.Range} range Range of data to remove
|
2013-02-14 23:21:53 +00:00
|
|
|
* @returns {ve.dm.Transaction} Transaction that removes data
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @throws {Error} Invalid range
|
2011-11-17 22:42:18 +00:00
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.dm.Transaction.newFromRemoval = function ( doc, range ) {
|
2012-08-02 18:46:13 +00:00
|
|
|
var i, selection, first, last, nodeStart, nodeEnd,
|
|
|
|
offset = 0,
|
|
|
|
removeStart = null,
|
|
|
|
removeEnd = null,
|
2013-09-10 18:49:31 +00:00
|
|
|
tx = new ve.dm.Transaction();
|
2013-01-16 20:22:07 +00:00
|
|
|
// Validate range
|
|
|
|
if ( range.isCollapsed() ) {
|
2012-06-20 01:20:28 +00:00
|
|
|
// Empty range, nothing to remove, retain up to the end of the document (for completeness)
|
2013-09-10 18:49:31 +00:00
|
|
|
tx.pushFinalRetain( doc, 0 );
|
2012-06-20 01:20:28 +00:00
|
|
|
return tx;
|
|
|
|
}
|
|
|
|
// Select nodes and validate selection
|
2012-08-02 18:46:13 +00:00
|
|
|
selection = doc.selectNodes( range, 'covered' );
|
2012-06-20 01:20:28 +00:00
|
|
|
if ( selection.length === 0 ) {
|
|
|
|
// Empty selection? Something is wrong!
|
2012-08-08 17:48:53 +00:00
|
|
|
throw new Error( 'Invalid range, cannot remove from ' + range.start + ' to ' + range.end );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
first = selection[0];
|
|
|
|
last = selection[selection.length - 1];
|
|
|
|
// If the first and last node are mergeable, merge them
|
|
|
|
if ( first.node.canBeMergedWith( last.node ) ) {
|
|
|
|
if ( !first.range && !last.range ) {
|
|
|
|
// First and last node are both completely covered, remove them
|
|
|
|
removeStart = first.nodeOuterRange.start;
|
|
|
|
removeEnd = last.nodeOuterRange.end;
|
|
|
|
} else {
|
|
|
|
// Either the first node or the last node is partially covered, so remove
|
|
|
|
// the selected content
|
|
|
|
removeStart = ( first.range || first.nodeRange ).start;
|
|
|
|
removeEnd = ( last.range || last.nodeRange ).end;
|
|
|
|
}
|
|
|
|
tx.pushRetain( removeStart );
|
2013-04-17 17:53:26 +00:00
|
|
|
tx.addSafeRemoveOps( doc, removeStart, removeEnd );
|
2013-09-10 18:49:31 +00:00
|
|
|
tx.pushFinalRetain( doc, removeEnd );
|
2012-06-20 01:20:28 +00:00
|
|
|
// All done
|
|
|
|
return tx;
|
|
|
|
}
|
|
|
|
|
|
|
|
// The selection wasn't mergeable, so remove nodes that are completely covered, and strip
|
|
|
|
// nodes that aren't
|
|
|
|
for ( i = 0; i < selection.length; i++ ) {
|
|
|
|
if ( !selection[i].range ) {
|
|
|
|
// Entire node is covered, remove it
|
|
|
|
nodeStart = selection[i].nodeOuterRange.start;
|
|
|
|
nodeEnd = selection[i].nodeOuterRange.end;
|
|
|
|
} else {
|
|
|
|
// Part of the node is covered, remove that range
|
|
|
|
nodeStart = selection[i].range.start;
|
|
|
|
nodeEnd = selection[i].range.end;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Merge contiguous removals. Only apply a removal when a gap appears, or at the
|
|
|
|
// end of the loop
|
|
|
|
if ( removeEnd === null ) {
|
|
|
|
// First removal
|
|
|
|
removeStart = nodeStart;
|
|
|
|
removeEnd = nodeEnd;
|
|
|
|
} else if ( removeEnd === nodeStart ) {
|
|
|
|
// Merge this removal into the previous one
|
|
|
|
removeEnd = nodeEnd;
|
|
|
|
} else {
|
|
|
|
// There is a gap between the previous removal and this one
|
|
|
|
|
|
|
|
// Push the previous removal first
|
|
|
|
tx.pushRetain( removeStart - offset );
|
2013-04-17 17:53:26 +00:00
|
|
|
tx.addSafeRemoveOps( doc, removeStart, removeEnd );
|
2012-06-20 01:20:28 +00:00
|
|
|
offset = removeEnd;
|
|
|
|
|
|
|
|
// Now start this removal
|
|
|
|
removeStart = nodeStart;
|
|
|
|
removeEnd = nodeEnd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Apply the last removal, if any
|
|
|
|
if ( removeEnd !== null ) {
|
|
|
|
tx.pushRetain( removeStart - offset );
|
2013-04-17 17:53:26 +00:00
|
|
|
tx.addSafeRemoveOps( doc, removeStart, removeEnd );
|
2012-06-20 01:20:28 +00:00
|
|
|
offset = removeEnd;
|
|
|
|
}
|
|
|
|
// Retain up to the end of the document
|
2013-09-10 18:49:31 +00:00
|
|
|
tx.pushFinalRetain( doc, offset );
|
2012-06-20 01:20:28 +00:00
|
|
|
return tx;
|
2011-11-17 22:42:18 +00:00
|
|
|
};
|
|
|
|
|
2013-05-20 18:51:59 +00:00
|
|
|
/**
|
Introduce newFromDocumentReplace() transaction builder
Replaces newFromNodeReplacement(). newFromNodeReplacement was very
simplistic and didn't support metadata or internal list items, so
if you had comments or references inside of the data you were editing
(reference contents or an image caption), they'd get mangled.
With this, you can do:
newDoc = doc.getDocumentSlice( node );
// Edit newDoc
tx = ve.dm.Transaction.newFromDocumentReplace( doc, node, newDoc );
surface.change( newDoc );
and that takes care of metadata, internal list items, and things like
references that reference internal list items.
ve.dm.Document.js:
* In getDocumentSlice(), store a reference to the original document
and the number of items in its InternalList at the time of slicing
in the created slice. This is used for reconciliation when the
modified slice is injected back into the parent document with
newFromDocumentReplace().
ve.dm.InternalList.js:
* Add a method for merging in another InternalList. This provides a
mapping from old to new InternalList indexes so the linear model data
being injected by newFromDocumentReplace() can have its InternalList
indexes remapped.
ve.dm.Transaction.js:
* Replace newFromNodeReplacement() with newFromDocumentReplace()
ve.ui.MWMediaEditDialog.js, ve.ui.MWReferenceDialog.js:
* Use getDocumentSlice/newFromDocumentReplace for editing captions/refs
* Change insertion code path to insert an empty internalItem/caption, then
newFromDocumentReplace into that
* Add empty internalList to new mini-documents
ve/test/dm/ve.dm.Transaction.test.js:
* Replace newFromNodeReplacement tests with newFromDocumentReplace tests
ve-mw/test/dm/ve.dm.Transaction.test.js (new):
* Add tests for newFromDocumentReplace with mwReference nodes
ve.dm.mwExample.js:
* Add data for newFromDocumentReplace with mwReference tests
VisualEditor.hooks.php:
* Add new test file
Bug: 52102
Change-Id: I4aa980780114b391924f04df588e81c990c32983
2013-09-05 01:05:07 +00:00
|
|
|
* Build a transaction that replaces the contents of a node with the contents of a document.
|
2013-05-20 18:51:59 +00:00
|
|
|
*
|
Introduce newFromDocumentReplace() transaction builder
Replaces newFromNodeReplacement(). newFromNodeReplacement was very
simplistic and didn't support metadata or internal list items, so
if you had comments or references inside of the data you were editing
(reference contents or an image caption), they'd get mangled.
With this, you can do:
newDoc = doc.getDocumentSlice( node );
// Edit newDoc
tx = ve.dm.Transaction.newFromDocumentReplace( doc, node, newDoc );
surface.change( newDoc );
and that takes care of metadata, internal list items, and things like
references that reference internal list items.
ve.dm.Document.js:
* In getDocumentSlice(), store a reference to the original document
and the number of items in its InternalList at the time of slicing
in the created slice. This is used for reconciliation when the
modified slice is injected back into the parent document with
newFromDocumentReplace().
ve.dm.InternalList.js:
* Add a method for merging in another InternalList. This provides a
mapping from old to new InternalList indexes so the linear model data
being injected by newFromDocumentReplace() can have its InternalList
indexes remapped.
ve.dm.Transaction.js:
* Replace newFromNodeReplacement() with newFromDocumentReplace()
ve.ui.MWMediaEditDialog.js, ve.ui.MWReferenceDialog.js:
* Use getDocumentSlice/newFromDocumentReplace for editing captions/refs
* Change insertion code path to insert an empty internalItem/caption, then
newFromDocumentReplace into that
* Add empty internalList to new mini-documents
ve/test/dm/ve.dm.Transaction.test.js:
* Replace newFromNodeReplacement tests with newFromDocumentReplace tests
ve-mw/test/dm/ve.dm.Transaction.test.js (new):
* Add tests for newFromDocumentReplace with mwReference nodes
ve.dm.mwExample.js:
* Add data for newFromDocumentReplace with mwReference tests
VisualEditor.hooks.php:
* Add new test file
Bug: 52102
Change-Id: I4aa980780114b391924f04df588e81c990c32983
2013-09-05 01:05:07 +00:00
|
|
|
* This is typically used to merge changes to a document slice back into the main document. If newDoc
|
|
|
|
* is a document slice of doc, it's assumed that there were no changes to doc's internal list since
|
|
|
|
* the slice, so any differences between internal items that doc and newDoc have in common will
|
|
|
|
* be resolved in newDoc's favor.
|
2013-05-20 18:51:59 +00:00
|
|
|
*
|
Introduce newFromDocumentReplace() transaction builder
Replaces newFromNodeReplacement(). newFromNodeReplacement was very
simplistic and didn't support metadata or internal list items, so
if you had comments or references inside of the data you were editing
(reference contents or an image caption), they'd get mangled.
With this, you can do:
newDoc = doc.getDocumentSlice( node );
// Edit newDoc
tx = ve.dm.Transaction.newFromDocumentReplace( doc, node, newDoc );
surface.change( newDoc );
and that takes care of metadata, internal list items, and things like
references that reference internal list items.
ve.dm.Document.js:
* In getDocumentSlice(), store a reference to the original document
and the number of items in its InternalList at the time of slicing
in the created slice. This is used for reconciliation when the
modified slice is injected back into the parent document with
newFromDocumentReplace().
ve.dm.InternalList.js:
* Add a method for merging in another InternalList. This provides a
mapping from old to new InternalList indexes so the linear model data
being injected by newFromDocumentReplace() can have its InternalList
indexes remapped.
ve.dm.Transaction.js:
* Replace newFromNodeReplacement() with newFromDocumentReplace()
ve.ui.MWMediaEditDialog.js, ve.ui.MWReferenceDialog.js:
* Use getDocumentSlice/newFromDocumentReplace for editing captions/refs
* Change insertion code path to insert an empty internalItem/caption, then
newFromDocumentReplace into that
* Add empty internalList to new mini-documents
ve/test/dm/ve.dm.Transaction.test.js:
* Replace newFromNodeReplacement tests with newFromDocumentReplace tests
ve-mw/test/dm/ve.dm.Transaction.test.js (new):
* Add tests for newFromDocumentReplace with mwReference nodes
ve.dm.mwExample.js:
* Add data for newFromDocumentReplace with mwReference tests
VisualEditor.hooks.php:
* Add new test file
Bug: 52102
Change-Id: I4aa980780114b391924f04df588e81c990c32983
2013-09-05 01:05:07 +00:00
|
|
|
* @param {ve.dm.Document} doc Main document
|
|
|
|
* @param {ve.Range|ve.dm.Node} removeNodeOrRange Node or range to remove
|
|
|
|
* @param {ve.dm.Document} newDoc Document to insert
|
|
|
|
* @returns {ve.dm.Transaction} Transaction that replaces the node and updates the internal list
|
|
|
|
* @throws {Error} removeNodeOrRange must be a ve.dm.Node or a ve.Range
|
2013-05-20 18:51:59 +00:00
|
|
|
*/
|
Introduce newFromDocumentReplace() transaction builder
Replaces newFromNodeReplacement(). newFromNodeReplacement was very
simplistic and didn't support metadata or internal list items, so
if you had comments or references inside of the data you were editing
(reference contents or an image caption), they'd get mangled.
With this, you can do:
newDoc = doc.getDocumentSlice( node );
// Edit newDoc
tx = ve.dm.Transaction.newFromDocumentReplace( doc, node, newDoc );
surface.change( newDoc );
and that takes care of metadata, internal list items, and things like
references that reference internal list items.
ve.dm.Document.js:
* In getDocumentSlice(), store a reference to the original document
and the number of items in its InternalList at the time of slicing
in the created slice. This is used for reconciliation when the
modified slice is injected back into the parent document with
newFromDocumentReplace().
ve.dm.InternalList.js:
* Add a method for merging in another InternalList. This provides a
mapping from old to new InternalList indexes so the linear model data
being injected by newFromDocumentReplace() can have its InternalList
indexes remapped.
ve.dm.Transaction.js:
* Replace newFromNodeReplacement() with newFromDocumentReplace()
ve.ui.MWMediaEditDialog.js, ve.ui.MWReferenceDialog.js:
* Use getDocumentSlice/newFromDocumentReplace for editing captions/refs
* Change insertion code path to insert an empty internalItem/caption, then
newFromDocumentReplace into that
* Add empty internalList to new mini-documents
ve/test/dm/ve.dm.Transaction.test.js:
* Replace newFromNodeReplacement tests with newFromDocumentReplace tests
ve-mw/test/dm/ve.dm.Transaction.test.js (new):
* Add tests for newFromDocumentReplace with mwReference nodes
ve.dm.mwExample.js:
* Add data for newFromDocumentReplace with mwReference tests
VisualEditor.hooks.php:
* Add new test file
Bug: 52102
Change-Id: I4aa980780114b391924f04df588e81c990c32983
2013-09-05 01:05:07 +00:00
|
|
|
ve.dm.Transaction.newFromDocumentReplace = function ( doc, removeNodeOrRange, newDoc ) {
|
|
|
|
var i, len, range, merge, data, metadata, listData, listMetadata, oldEndOffset, newEndOffset,
|
|
|
|
listNode = doc.internalList.getListNode(),
|
|
|
|
listNodeRange = listNode.getRange(),
|
|
|
|
newListNode = newDoc.internalList.getListNode(),
|
|
|
|
newListNodeRange = newListNode.getRange(),
|
|
|
|
newListNodeOuterRange = newListNode.getOuterRange(),
|
|
|
|
tx = new ve.dm.Transaction();
|
|
|
|
|
|
|
|
if ( removeNodeOrRange instanceof ve.dm.Node ) {
|
|
|
|
range = removeNodeOrRange.getRange();
|
|
|
|
} else if ( removeNodeOrRange instanceof ve.Range ) {
|
|
|
|
range = removeNodeOrRange;
|
|
|
|
} else {
|
|
|
|
throw new Error( 'removeNodeOrRange must be a ve.dm.Node or a ve.Range' );
|
|
|
|
}
|
|
|
|
|
|
|
|
// Get the data and the metadata, but skip over the internal list
|
|
|
|
data = new ve.dm.ElementLinearData( doc.getStore(),
|
|
|
|
newDoc.getData( new ve.Range( 0, newListNodeOuterRange.start ), true ).concat(
|
|
|
|
newDoc.getData( new ve.Range( newListNodeOuterRange.end, newDoc.data.getLength() ), true )
|
|
|
|
)
|
|
|
|
);
|
|
|
|
metadata = new ve.dm.MetaLinearData( doc.getStore(),
|
|
|
|
newDoc.getMetadata( new ve.Range( 0, newListNodeOuterRange.start ), true ).concat(
|
|
|
|
// Merge the metadata immediately before and immediately after the internal list
|
|
|
|
ve.copy( ve.dm.MetaLinearData.static.merge( [
|
|
|
|
newDoc.metadata.getData( newListNodeOuterRange.start ),
|
|
|
|
newDoc.metadata.getData( newListNodeOuterRange.end )
|
|
|
|
] ) )
|
|
|
|
).concat( newDoc.getMetadata(
|
|
|
|
new ve.Range( newListNodeOuterRange.end, newDoc.data.getLength() ), true
|
|
|
|
) )
|
|
|
|
);
|
|
|
|
// Merge the stores
|
|
|
|
merge = doc.getStore().merge( newDoc.getStore() );
|
|
|
|
// Remap the store indexes in the data
|
|
|
|
data.remapStoreIndexes( merge );
|
|
|
|
|
|
|
|
merge = doc.internalList.merge( newDoc.internalList, newDoc.origInternalListLength || 0 );
|
|
|
|
// Remap the indexes in the data
|
|
|
|
data.remapInteralListIndexes( merge.mapping );
|
|
|
|
// Get data for the new internal list
|
|
|
|
if ( newDoc.origDoc === doc ) {
|
|
|
|
// newDoc is a document slice based on doc, so all the internal list items present in doc
|
|
|
|
// when it was cloned are also in newDoc. We need to get the newDoc version of these items
|
|
|
|
// so that changes made in newDoc are reflected.
|
|
|
|
if ( newDoc.origInternalListLength > 0 ) {
|
|
|
|
oldEndOffset = doc.internalList.getItemNode( newDoc.origInternalListLength - 1 ).getOuterRange().end;
|
|
|
|
newEndOffset = newDoc.internalList.getItemNode( newDoc.origInternalListLength - 1 ).getOuterRange().end;
|
|
|
|
} else {
|
|
|
|
oldEndOffset = listNodeRange.start;
|
|
|
|
newEndOffset = newListNodeRange.start;
|
|
|
|
}
|
|
|
|
listData = newDoc.getData( new ve.Range( newListNodeRange.start, newEndOffset ), true )
|
|
|
|
.concat( doc.getData( new ve.Range( oldEndOffset, listNodeRange.end ), true ) );
|
|
|
|
listMetadata = newDoc.getMetadata( new ve.Range( newListNodeRange.start, newEndOffset ), true )
|
|
|
|
.concat( doc.getMetadata( new ve.Range( oldEndOffset, listNodeRange.end ) , true ) );
|
|
|
|
} else {
|
|
|
|
// newDoc is brand new, so use doc's internal list as a base
|
|
|
|
listData = doc.getData( listNodeRange, true );
|
|
|
|
listMetadata = doc.getMetadata( listNodeRange, true );
|
2013-05-20 18:51:59 +00:00
|
|
|
}
|
Introduce newFromDocumentReplace() transaction builder
Replaces newFromNodeReplacement(). newFromNodeReplacement was very
simplistic and didn't support metadata or internal list items, so
if you had comments or references inside of the data you were editing
(reference contents or an image caption), they'd get mangled.
With this, you can do:
newDoc = doc.getDocumentSlice( node );
// Edit newDoc
tx = ve.dm.Transaction.newFromDocumentReplace( doc, node, newDoc );
surface.change( newDoc );
and that takes care of metadata, internal list items, and things like
references that reference internal list items.
ve.dm.Document.js:
* In getDocumentSlice(), store a reference to the original document
and the number of items in its InternalList at the time of slicing
in the created slice. This is used for reconciliation when the
modified slice is injected back into the parent document with
newFromDocumentReplace().
ve.dm.InternalList.js:
* Add a method for merging in another InternalList. This provides a
mapping from old to new InternalList indexes so the linear model data
being injected by newFromDocumentReplace() can have its InternalList
indexes remapped.
ve.dm.Transaction.js:
* Replace newFromNodeReplacement() with newFromDocumentReplace()
ve.ui.MWMediaEditDialog.js, ve.ui.MWReferenceDialog.js:
* Use getDocumentSlice/newFromDocumentReplace for editing captions/refs
* Change insertion code path to insert an empty internalItem/caption, then
newFromDocumentReplace into that
* Add empty internalList to new mini-documents
ve/test/dm/ve.dm.Transaction.test.js:
* Replace newFromNodeReplacement tests with newFromDocumentReplace tests
ve-mw/test/dm/ve.dm.Transaction.test.js (new):
* Add tests for newFromDocumentReplace with mwReference nodes
ve.dm.mwExample.js:
* Add data for newFromDocumentReplace with mwReference tests
VisualEditor.hooks.php:
* Add new test file
Bug: 52102
Change-Id: I4aa980780114b391924f04df588e81c990c32983
2013-09-05 01:05:07 +00:00
|
|
|
for ( i = 0, len = merge.newItemRanges.length; i < len; i++ ) {
|
|
|
|
listData = listData.concat( newDoc.getData( merge.newItemRanges[i], true ) );
|
|
|
|
// We don't have to worry about merging metadata at the edges, because there can't be
|
|
|
|
// metadata between internal list items
|
|
|
|
listMetadata = listMetadata.concat( newDoc.getMetadata( merge.newItemRanges[i], true ) );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( range.end <= listNodeRange.start ) {
|
|
|
|
// range is entirely before listNodeRange
|
|
|
|
// First replace the node, then the internal list
|
|
|
|
tx.pushRetain( range.start );
|
|
|
|
tx.pushReplace( doc, range.start, range.end - range.start, data.data, metadata.data );
|
|
|
|
tx.pushRetain( listNodeRange.start - range.end );
|
|
|
|
tx.pushReplace( doc, listNodeRange.start, listNodeRange.end - listNodeRange.start,
|
|
|
|
listData, listMetadata
|
|
|
|
);
|
|
|
|
tx.pushRetain( doc.data.getLength() - listNodeRange.end );
|
|
|
|
} else if ( listNodeRange.end <= range.start ) {
|
|
|
|
// range is entirely after listNodeRange
|
|
|
|
// First replace the internal list, then the node
|
|
|
|
tx.pushRetain( listNodeRange.start );
|
|
|
|
tx.pushReplace( doc, listNodeRange.start, listNodeRange.end - listNodeRange.start,
|
|
|
|
listData, listMetadata
|
|
|
|
);
|
|
|
|
tx.pushRetain( range.start - listNodeRange.end );
|
|
|
|
tx.pushReplace( doc, range.start, range.end - range.start, data.data, metadata.data );
|
|
|
|
tx.pushRetain( doc.data.getLength() - range.end );
|
|
|
|
} else if ( range.start >= listNodeRange.start && range.end <= listNodeRange.end ) {
|
|
|
|
// range is entirely within listNodeRange
|
|
|
|
// Merge data into listData, then only replace the internal list
|
|
|
|
ve.batchSplice( listData, range.start - listNodeRange.start,
|
|
|
|
range.end - range.start, data.data );
|
|
|
|
ve.batchSplice( listMetadata, range.start - listNodeRange.start,
|
|
|
|
range.end - range.start + 1, metadata.data );
|
|
|
|
tx.pushRetain( listNodeRange.start );
|
|
|
|
tx.pushReplace( doc, listNodeRange.start, listNodeRange.end - listNodeRange.start,
|
|
|
|
listData, listMetadata
|
|
|
|
);
|
|
|
|
tx.pushRetain( doc.data.getLength() - listNodeRange.end );
|
ve.dm.Transaction: Implement newFromDocumentInsertion
This function builds a transaction that takes a document slice and
inserts it back into the document it came from, applying any changes
that were made.
This makes editing document slices simple:
slicedDoc = doc.getDocumentSlice( captionNode );
// Edit slicedDoc using a surface
tx = ve.dm.Transaction.newFromDocumentInsertion( doc, captionNode, slicedDoc );
surface.change( tx );
Specifically, newFromDocumentInsertion replaces the node's contents
with the document's contents (meaning any changes made to the node in
the meantime are lost). It also merges the stores internal lists
of the two documents and remaps indexes accordingly. This means editing
of references inside of references is supported.
This functionality is not specific to slices, and can also be used to
safely insert data from a paste buffer, with internal list data being
transplanted correctly.
ve.dm.MetaLinearData:
* Make merge( [ undefined, undefined, ... ] ) return undefined rather
than [].
ve.dm.Document:
* In getDocumentSlice, store a pointer to the original dm.Document in
the new one, and also store the length of the internal list. This
allows us to figure out which internal list items the two documents
have in common when we insert the modified slice back into the main
document.
* In getMetadataReplace, optionally take the inserted metadata as a
parameter, to allow for operations that insert both data and metadata.
Per Ed's review, rewrite this function to return null rather than {}
if no metadata needs to be replaced.
ve.dm.InternalList:
* Add method to merge two internal lists
ve.dm.Transaction:
* Remove newFromNodeReplacement and replace it with newFromDocumentInsertion.
* In pushReplace, optionally take the inserted metadata as a parameter.
Change-Id: I786ee7bad796aa54bc242993b4de3ad18ad0773e
2013-05-22 15:06:25 +00:00
|
|
|
}
|
2013-05-20 18:51:59 +00:00
|
|
|
return tx;
|
|
|
|
};
|
|
|
|
|
2011-11-04 21:06:06 +00:00
|
|
|
/**
|
2013-06-14 19:07:55 +00:00
|
|
|
* Generate a transaction that changes one or more attributes.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
|
|
|
* @static
|
2011-11-04 21:06:06 +00:00
|
|
|
* @method
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {ve.dm.Document} doc Document to create transaction for
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @param {number} offset Offset of element
|
2013-06-14 19:07:55 +00:00
|
|
|
* @param {Object.<string,Mixed>} attr List of attribute key and value pairs, use undefined value
|
2013-07-25 02:02:50 +00:00
|
|
|
* to remove an attribute
|
2013-02-14 23:21:53 +00:00
|
|
|
* @returns {ve.dm.Transaction} Transaction that changes an element
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @throws {Error} Cannot set attributes to non-element data
|
|
|
|
* @throws {Error} Cannot set attributes on closing element
|
2011-11-04 21:06:06 +00:00
|
|
|
*/
|
2013-06-14 19:07:55 +00:00
|
|
|
ve.dm.Transaction.newFromAttributeChanges = function ( doc, offset, attr ) {
|
|
|
|
var key,
|
|
|
|
tx = new ve.dm.Transaction(),
|
2012-06-20 01:20:28 +00:00
|
|
|
data = doc.getData();
|
|
|
|
// Verify element exists at offset
|
|
|
|
if ( data[offset].type === undefined ) {
|
2012-12-07 21:38:00 +00:00
|
|
|
throw new Error( 'Cannot set attributes to non-element data' );
|
2011-11-23 23:54:36 +00:00
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
// Verify element is not a closing
|
|
|
|
if ( data[offset].type.charAt( 0 ) === '/' ) {
|
2012-12-07 21:38:00 +00:00
|
|
|
throw new Error( 'Cannot set attributes on closing element' );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
// Retain up to element
|
|
|
|
tx.pushRetain( offset );
|
|
|
|
// Change attribute
|
2013-06-14 19:07:55 +00:00
|
|
|
for ( key in attr ) {
|
|
|
|
tx.pushReplaceElementAttribute(
|
|
|
|
key, 'attributes' in data[offset] ? data[offset].attributes[key] : undefined, attr[key]
|
|
|
|
);
|
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
// Retain to end of document
|
2013-09-10 18:49:31 +00:00
|
|
|
tx.pushFinalRetain( doc, offset );
|
2012-06-20 01:20:28 +00:00
|
|
|
return tx;
|
2011-11-02 21:00:55 +00:00
|
|
|
};
|
|
|
|
|
2011-11-04 21:06:06 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Generate a transaction that annotates content.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
|
|
|
* @static
|
2011-11-04 21:06:06 +00:00
|
|
|
* @method
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {ve.dm.Document} doc Document to create transaction for
|
|
|
|
* @param {ve.Range} range Range to annotate
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @param {string} method Annotation mode
|
|
|
|
* - `set`: Adds annotation to all content in range
|
|
|
|
* - `clear`: Removes instances of annotation from content in range
|
2013-04-25 21:55:43 +00:00
|
|
|
* @param {ve.dm.Annotation} annotation Annotation to set or clear
|
2012-08-24 02:06:36 +00:00
|
|
|
* @returns {ve.dm.Transaction} Transaction that annotates content
|
2011-11-04 21:06:06 +00:00
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.dm.Transaction.newFromAnnotation = function ( doc, range, method, annotation ) {
|
2013-09-19 18:00:23 +00:00
|
|
|
var covered, type, annotatable,
|
2012-08-02 18:46:13 +00:00
|
|
|
tx = new ve.dm.Transaction(),
|
2013-03-20 22:35:05 +00:00
|
|
|
data = doc.data,
|
2012-08-02 18:46:13 +00:00
|
|
|
i = range.start,
|
2012-06-20 01:20:28 +00:00
|
|
|
span = i,
|
2013-05-01 00:21:40 +00:00
|
|
|
on = false,
|
|
|
|
insideContentNode = false;
|
2012-08-02 18:46:13 +00:00
|
|
|
// Iterate over all data in range, annotating where appropriate
|
2012-06-20 01:20:28 +00:00
|
|
|
while ( i < range.end ) {
|
2013-09-19 18:00:23 +00:00
|
|
|
if ( data.isElementData( i ) ) {
|
|
|
|
type = data.getType( i );
|
|
|
|
if ( ve.dm.nodeFactory.isNodeContent( type ) ) {
|
|
|
|
if ( method === 'set' && !ve.dm.nodeFactory.canNodeTakeAnnotationType( type, annotation ) ) {
|
|
|
|
// Blacklisted annotations can't be set
|
|
|
|
annotatable = false;
|
|
|
|
} else {
|
|
|
|
annotatable = true;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Structural nodes are never annotatable
|
|
|
|
annotatable = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Text is always annotatable
|
|
|
|
annotatable = true;
|
|
|
|
}
|
2013-05-01 00:21:40 +00:00
|
|
|
if (
|
2013-09-19 18:00:23 +00:00
|
|
|
!annotatable ||
|
2013-05-01 00:21:40 +00:00
|
|
|
( insideContentNode && !data.isCloseElementData( i ) )
|
|
|
|
) {
|
|
|
|
// Structural element opening or closing, or entering a content node
|
2012-06-20 01:20:28 +00:00
|
|
|
if ( on ) {
|
|
|
|
tx.pushRetain( span );
|
|
|
|
tx.pushStopAnnotating( method, annotation );
|
|
|
|
span = 0;
|
|
|
|
on = false;
|
|
|
|
}
|
2013-05-01 00:21:40 +00:00
|
|
|
} else if (
|
|
|
|
( !data.isElementData( i ) || !data.isCloseElementData( i ) ) &&
|
|
|
|
!insideContentNode
|
|
|
|
) {
|
2012-11-23 21:07:20 +00:00
|
|
|
// Character or content element opening
|
2013-05-01 00:21:40 +00:00
|
|
|
if ( data.isElementData( i ) ) {
|
|
|
|
insideContentNode = true;
|
|
|
|
}
|
2013-03-20 22:35:05 +00:00
|
|
|
covered = data.getAnnotationsFromOffset( i ).contains( annotation );
|
Remainder JSHint fixes on modules/ve/*
[jshint]
ce/ve.ce.Surface.js: line 670, col 9, Too many var statements.
ce/ve.ce.Surface.js: line 695, col 6, Missing semicolon.
ce/ve.ce.Surface.js: line 726, col 22, Expected '===' and instead saw '=='.
ce/ve.ce.Surface.js: line 726, col 41, Expected '===' and instead saw '=='.
ce/ve.ce.Surface.js: line 733, col 13, Too many var statements.
ce/ve.ce.Surface.js: line 734, col 24, Expected '===' and instead saw '=='.
ce/ve.ce.Surface.js: line 1013, col 13, Too many var statements.
ce/ve.ce.Surface.js: line 1019, col 17, Too many var statements.
ce/ve.ce.Surface.js: line 1023, col 18, Too many ar statements.
ce/ve.ce.Surface.js: line 1027, col 13, Too many var statements.
dm/annotations/ve.dm.LinkAnnotation.js: line 70, col 52, Insecure '.'.
dm/ve.dm.Converter.js: line 383, col 29, Empty block.
dm/ve.dm.Converter.js: line 423, col 33, Empty block.
Commands:
* jshint .
* ack '(if|else|function|switch|for|while)\('
* Sublime Text 2:
Find(*): (if|else|function|switch|for|while)\(
Replace: $1 (
* ack ' ' -Q # double spaces, except in certain comments
Change-Id: I8e34bf2924bc8688fdf8acef08bbc4f6707e93be
2012-09-02 21:45:01 +00:00
|
|
|
if ( ( covered && method === 'set' ) || ( !covered && method === 'clear' ) ) {
|
2012-06-20 01:20:28 +00:00
|
|
|
// Skip annotated content
|
|
|
|
if ( on ) {
|
|
|
|
tx.pushRetain( span );
|
|
|
|
tx.pushStopAnnotating( method, annotation );
|
|
|
|
span = 0;
|
|
|
|
on = false;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Cover non-annotated content
|
|
|
|
if ( !on ) {
|
|
|
|
tx.pushRetain( span );
|
|
|
|
tx.pushStartAnnotating( method, annotation );
|
|
|
|
span = 0;
|
|
|
|
on = true;
|
|
|
|
}
|
|
|
|
}
|
2013-05-01 00:21:40 +00:00
|
|
|
} else if ( data.isCloseElementData( i ) ) {
|
|
|
|
// Content closing, skip
|
|
|
|
insideContentNode = false;
|
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
span++;
|
|
|
|
i++;
|
2011-11-23 23:54:36 +00:00
|
|
|
}
|
2012-06-20 01:20:28 +00:00
|
|
|
tx.pushRetain( span );
|
|
|
|
if ( on ) {
|
|
|
|
tx.pushStopAnnotating( method, annotation );
|
|
|
|
}
|
2013-09-10 18:49:31 +00:00
|
|
|
tx.pushFinalRetain( doc, range.end );
|
2012-06-20 01:20:28 +00:00
|
|
|
return tx;
|
2011-11-02 21:00:55 +00:00
|
|
|
};
|
|
|
|
|
2013-02-14 23:21:53 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate a transaction that inserts metadata elements.
|
|
|
|
*
|
|
|
|
* @static
|
|
|
|
* @method
|
|
|
|
* @param {ve.dm.Document} doc Document to create transaction for
|
|
|
|
* @param {number} offset Offset of element
|
|
|
|
* @param {number} index Index of metadata cursor within element
|
|
|
|
* @param {Array} newElements New elements to insert
|
|
|
|
* @returns {ve.dm.Transaction} Transaction that inserts the metadata elements
|
|
|
|
*/
|
|
|
|
ve.dm.Transaction.newFromMetadataInsertion = function ( doc, offset, index, newElements ) {
|
|
|
|
var tx = new ve.dm.Transaction(),
|
2013-03-20 22:35:05 +00:00
|
|
|
data = doc.metadata,
|
|
|
|
elements = data.getData( offset ) || [];
|
2013-02-14 23:21:53 +00:00
|
|
|
|
|
|
|
// Retain up to element
|
|
|
|
tx.pushRetain( offset );
|
|
|
|
// Retain up to metadata element (second dimension)
|
|
|
|
tx.pushRetainMetadata( index );
|
|
|
|
// Insert metadata elements
|
|
|
|
tx.pushReplaceMetadata(
|
|
|
|
[], newElements
|
|
|
|
);
|
|
|
|
// Retain up to end of metadata elements (second dimension)
|
|
|
|
tx.pushRetainMetadata( elements.length - index );
|
|
|
|
// Retain to end of document
|
2013-09-10 18:49:31 +00:00
|
|
|
tx.pushFinalRetain( doc, offset, elements.length );
|
2013-02-14 23:21:53 +00:00
|
|
|
return tx;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Generate a transaction that removes metadata elements.
|
|
|
|
*
|
|
|
|
* @static
|
|
|
|
* @method
|
|
|
|
* @param {ve.dm.Document} doc Document to create transaction for
|
|
|
|
* @param {number} offset Offset of element
|
|
|
|
* @param {ve.Range} range Range of metadata to remove
|
2013-09-16 21:13:38 +00:00
|
|
|
* @returns {ve.dm.Transaction} Transaction that removes metadata elements
|
2013-02-14 23:21:53 +00:00
|
|
|
* @throws {Error} Cannot remove metadata from empty list
|
|
|
|
* @throws {Error} Range out of bounds
|
|
|
|
*/
|
|
|
|
ve.dm.Transaction.newFromMetadataRemoval = function ( doc, offset, range ) {
|
|
|
|
var selection,
|
|
|
|
tx = new ve.dm.Transaction(),
|
2013-03-20 22:35:05 +00:00
|
|
|
data = doc.metadata,
|
|
|
|
elements = data.getData( offset ) || [];
|
2013-02-14 23:21:53 +00:00
|
|
|
|
|
|
|
if ( !elements.length ) {
|
|
|
|
throw new Error( 'Cannot remove metadata from empty list' );
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( range.start < 0 || range.end > elements.length ) {
|
|
|
|
throw new Error( 'Range out of bounds' );
|
|
|
|
}
|
|
|
|
|
|
|
|
selection = elements.slice( range.start, range.end );
|
|
|
|
|
|
|
|
// Retain up to element
|
|
|
|
tx.pushRetain( offset );
|
|
|
|
// Retain up to metadata element (second dimension)
|
|
|
|
tx.pushRetainMetadata( range.start );
|
|
|
|
// Remove metadata elements
|
|
|
|
tx.pushReplaceMetadata(
|
|
|
|
selection, []
|
|
|
|
);
|
|
|
|
// Retain up to end of metadata elements (second dimension)
|
|
|
|
tx.pushRetainMetadata( elements.length - range.end );
|
2013-09-10 18:49:31 +00:00
|
|
|
// Retain to end of document (unless we're already off the end )
|
|
|
|
tx.pushFinalRetain( doc, offset, elements.length );
|
2013-02-14 23:21:53 +00:00
|
|
|
return tx;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-09-10 17:36:23 +00:00
|
|
|
* Generate a transaction that replaces a single metadata element.
|
2013-02-14 23:21:53 +00:00
|
|
|
*
|
|
|
|
* @static
|
|
|
|
* @method
|
|
|
|
* @param {ve.dm.Document} doc Document to create transaction for
|
|
|
|
* @param {number} offset Offset of element
|
|
|
|
* @param {number} index Index of metadata cursor within element
|
|
|
|
* @param {Object} newElement New element to insert
|
2013-09-16 21:13:38 +00:00
|
|
|
* @returns {ve.dm.Transaction} Transaction that replaces a metadata element
|
2013-02-14 23:21:53 +00:00
|
|
|
* @throws {Error} Metadata index out of bounds
|
|
|
|
*/
|
|
|
|
ve.dm.Transaction.newFromMetadataElementReplacement = function ( doc, offset, index, newElement ) {
|
|
|
|
var oldElement,
|
|
|
|
tx = new ve.dm.Transaction(),
|
|
|
|
data = doc.getMetadata(),
|
|
|
|
elements = data[offset] || [];
|
|
|
|
|
|
|
|
if ( index >= elements.length ) {
|
|
|
|
throw new Error( 'Metadata index out of bounds' );
|
|
|
|
}
|
|
|
|
|
|
|
|
oldElement = elements[index];
|
|
|
|
|
|
|
|
// Retain up to element
|
|
|
|
tx.pushRetain( offset );
|
|
|
|
// Retain up to metadata element (second dimension)
|
|
|
|
tx.pushRetainMetadata( index );
|
|
|
|
// Remove metadata elements
|
|
|
|
tx.pushReplaceMetadata(
|
|
|
|
[ oldElement ], [ newElement ]
|
|
|
|
);
|
|
|
|
// Retain up to end of metadata elements (second dimension)
|
|
|
|
tx.pushRetainMetadata( elements.length - index - 1 );
|
2013-09-10 18:49:31 +00:00
|
|
|
// Retain to end of document (unless we're already off the end )
|
|
|
|
tx.pushFinalRetain( doc, offset, elements.length );
|
2013-02-14 23:21:53 +00:00
|
|
|
return tx;
|
|
|
|
};
|
|
|
|
|
2011-11-04 21:06:06 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Generate a transaction that converts elements that can contain content.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
|
|
|
* @static
|
2011-11-04 21:06:06 +00:00
|
|
|
* @method
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {ve.dm.Document} doc Document to create transaction for
|
|
|
|
* @param {ve.Range} range Range to convert
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @param {string} type Symbolic name of element type to convert to
|
2012-06-20 01:20:28 +00:00
|
|
|
* @param {Object} attr Attributes to initialize element with
|
2012-08-24 02:06:36 +00:00
|
|
|
* @returns {ve.dm.Transaction} Transaction that converts content branches
|
2011-11-04 21:06:06 +00:00
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.dm.Transaction.newFromContentBranchConversion = function ( doc, range, type, attr ) {
|
2012-08-02 18:46:13 +00:00
|
|
|
var i, selected, branch, branchOuterRange,
|
|
|
|
tx = new ve.dm.Transaction(),
|
2012-06-20 01:20:28 +00:00
|
|
|
selection = doc.selectNodes( range, 'leaves' ),
|
|
|
|
opening = { 'type': type },
|
|
|
|
closing = { 'type': '/' + type },
|
|
|
|
previousBranch,
|
|
|
|
previousBranchOuterRange;
|
|
|
|
// Add attributes to opening if needed
|
|
|
|
if ( ve.isPlainObject( attr ) ) {
|
|
|
|
opening.attributes = attr;
|
2012-10-01 23:27:56 +00:00
|
|
|
} else {
|
|
|
|
attr = {};
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
// Replace the wrappings of each content branch in the range
|
2012-08-02 18:46:13 +00:00
|
|
|
for ( i = 0; i < selection.length; i++ ) {
|
|
|
|
selected = selection[i];
|
2013-04-26 23:49:43 +00:00
|
|
|
branch = selected.node.isContent() ? selected.node.getParent() : selected.node;
|
|
|
|
if ( branch.canContainContent() ) {
|
2012-08-10 22:35:48 +00:00
|
|
|
// Skip branches that are already of the target type and have identical attributes
|
2013-05-28 23:10:19 +00:00
|
|
|
if ( branch.getType() === type && ve.compare( branch.getAttributes(), attr ) ) {
|
2012-08-10 22:35:48 +00:00
|
|
|
continue;
|
|
|
|
}
|
2012-08-02 18:46:13 +00:00
|
|
|
branchOuterRange = branch.getOuterRange();
|
2012-06-20 01:20:28 +00:00
|
|
|
// Don't convert the same branch twice
|
|
|
|
if ( branch === previousBranch ) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
// Retain up to this branch, considering where the previous one left off
|
|
|
|
tx.pushRetain(
|
|
|
|
branchOuterRange.start - ( previousBranch ? previousBranchOuterRange.end : 0 )
|
|
|
|
);
|
|
|
|
// Replace the opening
|
2013-07-28 20:51:32 +00:00
|
|
|
tx.pushReplace( doc, branchOuterRange.start, 1, [ ve.copy( opening ) ] );
|
2012-06-20 01:20:28 +00:00
|
|
|
// Retain the contents
|
|
|
|
tx.pushRetain( branch.getLength() );
|
|
|
|
// Replace the closing
|
2013-07-28 20:51:32 +00:00
|
|
|
tx.pushReplace( doc, branchOuterRange.end - 1, 1, [ ve.copy( closing ) ] );
|
2012-06-20 01:20:28 +00:00
|
|
|
// Remember this branch and its range for next time
|
|
|
|
previousBranch = branch;
|
|
|
|
previousBranchOuterRange = branchOuterRange;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
// Retain until the end
|
2013-09-10 18:49:31 +00:00
|
|
|
tx.pushFinalRetain( doc, previousBranch ? previousBranchOuterRange.end : 0 );
|
2012-06-20 01:20:28 +00:00
|
|
|
return tx;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Generate a transaction that wraps, unwraps or replaces structure.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
|
|
|
* The unwrap parameters are checked against the actual model data, and
|
|
|
|
* an exception is thrown if the type fields don't match. This means you
|
|
|
|
* can omit attributes from the unwrap parameters, those are automatically
|
|
|
|
* picked up from the model data instead.
|
|
|
|
*
|
|
|
|
* NOTE: This function currently does not fix invalid parent/child relationships, so it will
|
|
|
|
* happily convert paragraphs to listItems without wrapping them in a list if that's what you
|
|
|
|
* ask it to do. We'll probably fix this later but for now the caller is responsible for giving
|
|
|
|
* valid instructions.
|
|
|
|
*
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* Changing a paragraph to a header:
|
2012-06-20 01:20:28 +00:00
|
|
|
* Before: [ {'type': 'paragraph'}, 'a', 'b', 'c', {'type': '/paragraph'} ]
|
|
|
|
* newFromWrap( new ve.Range( 1, 4 ), [ {'type': 'paragraph'} ], [ {'type': 'heading', 'level': 1 } ] );
|
|
|
|
* After: [ {'type': 'heading', 'level': 1 }, 'a', 'b', 'c', {'type': '/heading'} ]
|
|
|
|
*
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* Changing a set of paragraphs to a list:
|
2012-06-20 01:20:28 +00:00
|
|
|
* Before: [ {'type': 'paragraph'}, 'a', {'type': '/paragraph'}, {'type':'paragraph'}, 'b', {'type':'/paragraph'} ]
|
|
|
|
* newFromWrap( new ve.Range( 0, 6 ), [], [ {'type': 'list' } ], [], [ {'type': 'listItem', 'attributes': {'styles': ['bullet']}} ] );
|
|
|
|
* After: [ {'type': 'list'}, {'type': 'listItem', 'attributes': {'styles': ['bullet']}}, {'type':'paragraph'} 'a',
|
|
|
|
* {'type': '/paragraph'}, {'type': '/listItem'}, {'type': 'listItem', 'attributes': {'styles': ['bullet']}},
|
|
|
|
* {'type': 'paragraph'}, 'b', {'type': '/paragraph'}, {'type': '/listItem'}, {'type': '/list'} ]
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
*
|
|
|
|
* @param {ve.dm.Document} doc Document to generate a transaction for
|
|
|
|
* @param {ve.Range} range Range to wrap/unwrap/replace around
|
2013-03-20 17:03:27 +00:00
|
|
|
* @param {Array} unwrapOuter Opening elements to unwrap. These must be immediately *outside* the range
|
|
|
|
* @param {Array} wrapOuter Opening elements to wrap around the range
|
|
|
|
* @param {Array} unwrapEach Opening elements to unwrap from each top-level element in the range
|
|
|
|
* @param {Array} wrapEach Opening elements to wrap around each top-level element in the range
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {ve.dm.Transaction}
|
2012-06-20 01:20:28 +00:00
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.dm.Transaction.newFromWrap = function ( doc, range, unwrapOuter, wrapOuter, unwrapEach, wrapEach ) {
|
2012-08-02 18:46:13 +00:00
|
|
|
var i, j, unwrapOuterData, startOffset, unwrapEachData, closingUnwrapEach, closingWrapEach,
|
|
|
|
tx = new ve.dm.Transaction(),
|
|
|
|
depth = 0;
|
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
// Function to generate arrays of closing elements in reverse order
|
|
|
|
function closingArray( openings ) {
|
|
|
|
var closings = [], i, len = openings.length;
|
|
|
|
for ( i = 0; i < len; i++ ) {
|
|
|
|
closings[closings.length] = { 'type': '/' + openings[len - i - 1].type };
|
|
|
|
}
|
|
|
|
return closings;
|
|
|
|
}
|
2012-08-02 18:46:13 +00:00
|
|
|
closingUnwrapEach = closingArray( unwrapEach );
|
|
|
|
closingWrapEach = closingArray( wrapEach );
|
2012-06-20 01:20:28 +00:00
|
|
|
|
|
|
|
// TODO: check for and fix nesting validity like fixupInsertion does
|
|
|
|
if ( range.start > unwrapOuter.length ) {
|
|
|
|
// Retain up to the first thing we're unwrapping
|
|
|
|
// The outer unwrapping takes place *outside*
|
|
|
|
// the range, so compensate for that
|
|
|
|
tx.pushRetain( range.start - unwrapOuter.length );
|
|
|
|
} else if ( range.start < unwrapOuter.length ) {
|
2012-08-08 17:48:53 +00:00
|
|
|
throw new Error( 'unwrapOuter is longer than the data preceding the range' );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Replace the opening elements for the outer unwrap&wrap
|
|
|
|
if ( wrapOuter.length > 0 || unwrapOuter.length > 0 ) {
|
|
|
|
// Verify that wrapOuter matches the data at this position
|
|
|
|
unwrapOuterData = doc.data.slice( range.start - unwrapOuter.length, range.start );
|
|
|
|
for ( i = 0; i < unwrapOuterData.length; i++ ) {
|
|
|
|
if ( unwrapOuterData[i].type !== unwrapOuter[i].type ) {
|
2012-08-08 17:48:53 +00:00
|
|
|
throw new Error( 'Element in unwrapOuter does not match: expected ' +
|
2012-08-06 20:38:00 +00:00
|
|
|
unwrapOuter[i].type + ' but found ' + unwrapOuterData[i].type );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Instead of putting in unwrapOuter as given, put it in the
|
2013-04-06 16:45:26 +00:00
|
|
|
// way it appears in the model so we pick up any attributes
|
2013-07-28 20:51:32 +00:00
|
|
|
tx.pushReplace( doc, range.start - unwrapOuter.length, unwrapOuter.length, ve.copy( wrapOuter ) );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if ( wrapEach.length > 0 || unwrapEach.length > 0 ) {
|
|
|
|
// Visit each top-level child and wrap/unwrap it
|
|
|
|
// TODO figure out if we should use the tree/node functions here
|
|
|
|
// rather than iterating over offsets, it may or may not be faster
|
|
|
|
for ( i = range.start; i < range.end; i++ ) {
|
2013-03-20 22:35:05 +00:00
|
|
|
if ( doc.data.isElementData( i ) ) {
|
2012-06-20 01:20:28 +00:00
|
|
|
// This is a structural offset
|
2013-03-20 22:35:05 +00:00
|
|
|
if ( !doc.data.isCloseElementData( i ) ) {
|
2012-06-20 01:20:28 +00:00
|
|
|
// This is an opening element
|
|
|
|
if ( depth === 0 ) {
|
|
|
|
// We are at the start of a top-level element
|
|
|
|
// Replace the opening elements
|
|
|
|
|
|
|
|
// Verify that unwrapEach matches the data at this position
|
|
|
|
unwrapEachData = doc.data.slice( i, i + unwrapEach.length );
|
|
|
|
for ( j = 0; j < unwrapEachData.length; j++ ) {
|
|
|
|
if ( unwrapEachData[j].type !== unwrapEach[j].type ) {
|
2012-08-08 17:48:53 +00:00
|
|
|
throw new Error( 'Element in unwrapEach does not match: expected ' +
|
2012-06-20 01:20:28 +00:00
|
|
|
unwrapEach[j].type + ' but found ' +
|
2012-08-06 20:38:00 +00:00
|
|
|
unwrapEachData[j].type );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
// Instead of putting in unwrapEach as given, put it in the
|
|
|
|
// way it appears in the model, so we pick up any attributes
|
2013-07-28 20:51:32 +00:00
|
|
|
tx.pushReplace( doc, i, unwrapEach.length, ve.copy( wrapEach ) );
|
2012-06-20 01:20:28 +00:00
|
|
|
|
|
|
|
// Store this offset for later
|
2013-09-01 14:53:37 +00:00
|
|
|
startOffset = i + unwrapEach.length;
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
depth++;
|
|
|
|
} else {
|
|
|
|
// This is a closing element
|
|
|
|
depth--;
|
|
|
|
if ( depth === 0 ) {
|
|
|
|
// We are at the end of a top-level element
|
2013-09-01 14:53:37 +00:00
|
|
|
// Advance past the element, then back up past the unwrapEach
|
|
|
|
j = ( i + 1 ) - unwrapEach.length;
|
2012-06-20 01:20:28 +00:00
|
|
|
// Retain the contents of what we're wrapping
|
2013-09-01 14:53:37 +00:00
|
|
|
tx.pushRetain( j - startOffset );
|
2012-06-20 01:20:28 +00:00
|
|
|
// Replace the closing elements
|
2013-09-01 14:53:37 +00:00
|
|
|
tx.pushReplace( doc, j, unwrapEach.length, ve.copy( closingWrapEach ) );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2011-11-23 23:54:36 +00:00
|
|
|
} else {
|
2012-06-20 01:20:28 +00:00
|
|
|
// There is no wrapEach/unwrapEach to be done, just retain
|
|
|
|
// up to the end of the range
|
|
|
|
tx.pushRetain( range.end - range.start );
|
|
|
|
}
|
|
|
|
|
2013-09-01 14:53:37 +00:00
|
|
|
// this is a no-op if unwrapOuter.length===0 and wrapOuter.length===0
|
|
|
|
tx.pushReplace( doc, range.end, unwrapOuter.length, closingArray( wrapOuter ) );
|
2012-06-20 01:20:28 +00:00
|
|
|
|
|
|
|
// Retain up to the end of the document
|
2013-09-10 18:49:31 +00:00
|
|
|
tx.pushFinalRetain( doc, range.end + unwrapOuter.length );
|
2012-06-20 01:20:28 +00:00
|
|
|
|
|
|
|
return tx;
|
|
|
|
};
|
|
|
|
|
Get rid of 'reversed' flag on transactions
The way we implemented undoing transactions was horrible. We'd process
the original transaction, but with a reversed=true flag. That meant we
had to keep track of the 'reversed' flag everywhere, and use ternaries
like insert = reversed ? op.remove : op.insert; all over the place to
access transaction operations. Redo then worked by reapplying the
transaction. We would verify that this was OK by tracking whether the
transaction was in an applied state or an undone state.
This commit makes it so every transaction can only be applied once. To
undo, you obtain a mirror image of the transaction with tx.reverse(),
then apply that. To redo, you clone the original transaction with
tx.clone() and apply that. All the code that had to use ternaries to
check whether the transaction was being applied in reverse or not is
gone now, because you can only apply a given transaction forwards,
never in reverse.
Bonus:
* Make ve.dm.Document's .completeHistory a simple array of
transactions, rather than transaction/boolean pairs
* In the protection of double application test, clone the example
document properly; it modified ve.dm.example.data, which was "fine"
because it ran .commit() and .rollback() the same number of times
Change-Id: I3050c5430be4a12510f22e20853560b92acebb67
2013-10-03 00:43:56 +00:00
|
|
|
/**
|
|
|
|
* Specification for how each type of operation should be reversed.
|
|
|
|
*
|
|
|
|
* This object maps operation types to objects, which map property names to reversal instructions.
|
|
|
|
* A reversal instruction is either a string (which means the value of that property should be used)
|
|
|
|
* or an object (which maps old values to new values). For instance, { 'from': 'to' }
|
|
|
|
* means that the .from property of the reversed operation should be set to the .to property of the
|
|
|
|
* original operation, and { 'method': { 'set': 'clear' } } means that if the .method property of
|
|
|
|
* the original operation was 'set', the reversed operation's .method property should be 'clear'.
|
|
|
|
*
|
|
|
|
* If a property's treatment isn't specified, its value is simply copied without modification.
|
|
|
|
* If an operation type's treatment isn't specified, all properties are copied without modification.
|
|
|
|
*
|
|
|
|
* @type {Object.<string,Object.<string,string|Object.<string, string>>>}
|
|
|
|
*/
|
|
|
|
ve.dm.Transaction.reversers = {
|
|
|
|
'annotate': { 'method': { 'set': 'clear', 'clear': 'set' } }, // swap 'set' with 'clear'
|
|
|
|
'attribute': { 'from': 'to', 'to': 'from' }, // swap .from with .to
|
|
|
|
'replace': { // swap .insert with .remove and .insertMetadata with .removeMetadata
|
|
|
|
'insert': 'remove',
|
|
|
|
'remove': 'insert',
|
|
|
|
'insertMetadata': 'removeMetadata',
|
|
|
|
'removeMetadata': 'insertMetadata'
|
|
|
|
},
|
|
|
|
'replaceMetadata': { 'insert': 'remove', 'remove': 'insert' } // swap .insert with .remove
|
|
|
|
};
|
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
/* Methods */
|
|
|
|
|
Get rid of 'reversed' flag on transactions
The way we implemented undoing transactions was horrible. We'd process
the original transaction, but with a reversed=true flag. That meant we
had to keep track of the 'reversed' flag everywhere, and use ternaries
like insert = reversed ? op.remove : op.insert; all over the place to
access transaction operations. Redo then worked by reapplying the
transaction. We would verify that this was OK by tracking whether the
transaction was in an applied state or an undone state.
This commit makes it so every transaction can only be applied once. To
undo, you obtain a mirror image of the transaction with tx.reverse(),
then apply that. To redo, you clone the original transaction with
tx.clone() and apply that. All the code that had to use ternaries to
check whether the transaction was being applied in reverse or not is
gone now, because you can only apply a given transaction forwards,
never in reverse.
Bonus:
* Make ve.dm.Document's .completeHistory a simple array of
transactions, rather than transaction/boolean pairs
* In the protection of double application test, clone the example
document properly; it modified ve.dm.example.data, which was "fine"
because it ran .commit() and .rollback() the same number of times
Change-Id: I3050c5430be4a12510f22e20853560b92acebb67
2013-10-03 00:43:56 +00:00
|
|
|
/**
|
|
|
|
* Create a clone of this transaction.
|
|
|
|
*
|
|
|
|
* The returned transaction will be exactly the same as this one, except that its 'applied' flag
|
|
|
|
* will be cleared. This means that if a transaction has already been committed, it will still
|
|
|
|
* be possible to commit the clone. This is used for redoing transactions that were undone.
|
|
|
|
*
|
|
|
|
* @returns {ve.dm.Transaction} Clone of this transaction
|
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.clone = function () {
|
|
|
|
var tx = new this.constructor();
|
|
|
|
tx.operations = ve.copy( this.operations );
|
|
|
|
tx.lengthDifference = this.lengthDifference;
|
|
|
|
return tx;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Create a reversed version of this transaction.
|
|
|
|
*
|
|
|
|
* The returned transaction will be the same as this one but with all operations reversed. This
|
|
|
|
* means that applying the original transaction and then applying the reversed transaction will
|
|
|
|
* result in no net changes. This is used to undo transactions.
|
|
|
|
*
|
|
|
|
* @returns {ve.dm.Transaction} Reverse of this transaction
|
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.reversed = function () {
|
|
|
|
var i, len, op, newOp, reverse, prop, tx = new this.constructor();
|
|
|
|
for ( i = 0, len = this.operations.length; i < len; i++ ) {
|
|
|
|
op = this.operations[i];
|
|
|
|
newOp = ve.copy( op );
|
|
|
|
reverse = this.constructor.reversers[op.type] || {};
|
|
|
|
for ( prop in reverse ) {
|
|
|
|
if ( typeof reverse[prop] === 'string' ) {
|
|
|
|
newOp[prop] = op[reverse[prop]];
|
|
|
|
} else {
|
|
|
|
newOp[prop] = reverse[prop][op[prop]];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
tx.operations.push( newOp );
|
|
|
|
}
|
|
|
|
tx.lengthDifference = -this.lengthDifference;
|
|
|
|
return tx;
|
|
|
|
};
|
|
|
|
|
2012-08-10 22:35:48 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Check if the transaction would make any actual changes if processed.
|
2012-08-10 22:35:48 +00:00
|
|
|
*
|
|
|
|
* There may be more sophisticated checks that can be done, like looking for things being replaced
|
|
|
|
* with identical content, but such transactions probably should not be created in the first place.
|
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {boolean} Transaction is no-op
|
2012-08-10 22:35:48 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.isNoOp = function () {
|
|
|
|
return (
|
|
|
|
this.operations.length === 0 ||
|
|
|
|
( this.operations.length === 1 && this.operations[0].type === 'retain' )
|
|
|
|
);
|
|
|
|
};
|
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Get all operations.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @returns {Object[]} List of operations
|
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.dm.Transaction.prototype.getOperations = function () {
|
2012-06-20 01:20:28 +00:00
|
|
|
return this.operations;
|
|
|
|
};
|
|
|
|
|
2012-11-26 23:57:02 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Check if the transaction has any operations with a certain type.
|
2012-11-26 23:57:02 +00:00
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {boolean} Has operations of a given type
|
2012-11-26 23:57:02 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.hasOperationWithType = function ( type ) {
|
|
|
|
var i, len;
|
|
|
|
for ( i = 0, len = this.operations.length; i < len; i++ ) {
|
2013-04-06 16:45:26 +00:00
|
|
|
if ( this.operations[i].type === type ) {
|
2012-11-26 23:57:02 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Check if the transaction has any content data operations, such as insertion or deletion.
|
2012-11-26 23:57:02 +00:00
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {boolean} Has content data operations
|
2012-11-26 23:57:02 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.hasContentDataOperations = function () {
|
|
|
|
return this.hasOperationWithType( 'replace' );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Check if the transaction has any element attribute operations.
|
2012-11-26 23:57:02 +00:00
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {boolean} Has element attribute operations
|
2012-11-26 23:57:02 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.hasElementAttributeOperations = function () {
|
|
|
|
return this.hasOperationWithType( 'attribute' );
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Check if the transaction has any annotation operations.
|
2012-11-26 23:57:02 +00:00
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {boolean} Has annotation operations
|
2012-11-26 23:57:02 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.hasAnnotationOperations = function () {
|
|
|
|
return this.hasOperationWithType( 'annotate' );
|
|
|
|
};
|
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Get the difference in content length the transaction will cause if applied.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {number} Difference in content length
|
2012-06-20 01:20:28 +00:00
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.dm.Transaction.prototype.getLengthDifference = function () {
|
2012-06-20 01:20:28 +00:00
|
|
|
return this.lengthDifference;
|
|
|
|
};
|
|
|
|
|
2012-10-23 00:28:37 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Check whether the transaction has already been applied.
|
2012-10-23 00:28:37 +00:00
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {boolean}
|
2012-10-23 00:28:37 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.hasBeenApplied = function () {
|
|
|
|
return this.applied;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
Get rid of 'reversed' flag on transactions
The way we implemented undoing transactions was horrible. We'd process
the original transaction, but with a reversed=true flag. That meant we
had to keep track of the 'reversed' flag everywhere, and use ternaries
like insert = reversed ? op.remove : op.insert; all over the place to
access transaction operations. Redo then worked by reapplying the
transaction. We would verify that this was OK by tracking whether the
transaction was in an applied state or an undone state.
This commit makes it so every transaction can only be applied once. To
undo, you obtain a mirror image of the transaction with tx.reverse(),
then apply that. To redo, you clone the original transaction with
tx.clone() and apply that. All the code that had to use ternaries to
check whether the transaction was being applied in reverse or not is
gone now, because you can only apply a given transaction forwards,
never in reverse.
Bonus:
* Make ve.dm.Document's .completeHistory a simple array of
transactions, rather than transaction/boolean pairs
* In the protection of double application test, clone the example
document properly; it modified ve.dm.example.data, which was "fine"
because it ran .commit() and .rollback() the same number of times
Change-Id: I3050c5430be4a12510f22e20853560b92acebb67
2013-10-03 00:43:56 +00:00
|
|
|
* Mark the transaction as having been applied.
|
2013-01-15 23:38:49 +00:00
|
|
|
*
|
Get rid of 'reversed' flag on transactions
The way we implemented undoing transactions was horrible. We'd process
the original transaction, but with a reversed=true flag. That meant we
had to keep track of the 'reversed' flag everywhere, and use ternaries
like insert = reversed ? op.remove : op.insert; all over the place to
access transaction operations. Redo then worked by reapplying the
transaction. We would verify that this was OK by tracking whether the
transaction was in an applied state or an undone state.
This commit makes it so every transaction can only be applied once. To
undo, you obtain a mirror image of the transaction with tx.reverse(),
then apply that. To redo, you clone the original transaction with
tx.clone() and apply that. All the code that had to use ternaries to
check whether the transaction was being applied in reverse or not is
gone now, because you can only apply a given transaction forwards,
never in reverse.
Bonus:
* Make ve.dm.Document's .completeHistory a simple array of
transactions, rather than transaction/boolean pairs
* In the protection of double application test, clone the example
document properly; it modified ve.dm.example.data, which was "fine"
because it ran .commit() and .rollback() the same number of times
Change-Id: I3050c5430be4a12510f22e20853560b92acebb67
2013-10-03 00:43:56 +00:00
|
|
|
* Should only be called after committing the transaction.
|
2013-01-15 23:38:49 +00:00
|
|
|
*
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @see ve.dm.Transaction#hasBeenApplied
|
2012-10-23 00:28:37 +00:00
|
|
|
*/
|
Get rid of 'reversed' flag on transactions
The way we implemented undoing transactions was horrible. We'd process
the original transaction, but with a reversed=true flag. That meant we
had to keep track of the 'reversed' flag everywhere, and use ternaries
like insert = reversed ? op.remove : op.insert; all over the place to
access transaction operations. Redo then worked by reapplying the
transaction. We would verify that this was OK by tracking whether the
transaction was in an applied state or an undone state.
This commit makes it so every transaction can only be applied once. To
undo, you obtain a mirror image of the transaction with tx.reverse(),
then apply that. To redo, you clone the original transaction with
tx.clone() and apply that. All the code that had to use ternaries to
check whether the transaction was being applied in reverse or not is
gone now, because you can only apply a given transaction forwards,
never in reverse.
Bonus:
* Make ve.dm.Document's .completeHistory a simple array of
transactions, rather than transaction/boolean pairs
* In the protection of double application test, clone the example
document properly; it modified ve.dm.example.data, which was "fine"
because it ran .commit() and .rollback() the same number of times
Change-Id: I3050c5430be4a12510f22e20853560b92acebb67
2013-10-03 00:43:56 +00:00
|
|
|
ve.dm.Transaction.prototype.markAsApplied = function () {
|
|
|
|
this.applied = true;
|
2012-11-26 21:36:07 +00:00
|
|
|
};
|
2012-10-23 00:28:37 +00:00
|
|
|
|
2012-06-20 21:37:13 +00:00
|
|
|
/**
|
2012-06-21 07:08:23 +00:00
|
|
|
* Translate an offset based on a transaction.
|
2012-06-20 21:37:13 +00:00
|
|
|
*
|
2012-06-21 07:08:23 +00:00
|
|
|
* This is useful when you want to anticipate what an offset will be after a transaction is
|
|
|
|
* processed.
|
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @param {number} offset Offset in the linear model before the transaction has been processed
|
2013-02-23 01:13:43 +00:00
|
|
|
* @param {boolean} [excludeInsertion] Map the offset immediately before an insertion to
|
|
|
|
* right before the insertion rather than right after
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @returns {number} Translated offset, as it will be after processing transaction
|
2012-06-20 21:37:13 +00:00
|
|
|
*/
|
Get rid of 'reversed' flag on transactions
The way we implemented undoing transactions was horrible. We'd process
the original transaction, but with a reversed=true flag. That meant we
had to keep track of the 'reversed' flag everywhere, and use ternaries
like insert = reversed ? op.remove : op.insert; all over the place to
access transaction operations. Redo then worked by reapplying the
transaction. We would verify that this was OK by tracking whether the
transaction was in an applied state or an undone state.
This commit makes it so every transaction can only be applied once. To
undo, you obtain a mirror image of the transaction with tx.reverse(),
then apply that. To redo, you clone the original transaction with
tx.clone() and apply that. All the code that had to use ternaries to
check whether the transaction was being applied in reverse or not is
gone now, because you can only apply a given transaction forwards,
never in reverse.
Bonus:
* Make ve.dm.Document's .completeHistory a simple array of
transactions, rather than transaction/boolean pairs
* In the protection of double application test, clone the example
document properly; it modified ve.dm.example.data, which was "fine"
because it ran .commit() and .rollback() the same number of times
Change-Id: I3050c5430be4a12510f22e20853560b92acebb67
2013-10-03 00:43:56 +00:00
|
|
|
ve.dm.Transaction.prototype.translateOffset = function ( offset, excludeInsertion ) {
|
2013-02-22 20:01:02 +00:00
|
|
|
var i, op, insertLength, removeLength, prevAdjustment, cursor = 0, adjustment = 0;
|
2012-06-20 21:37:13 +00:00
|
|
|
for ( i = 0; i < this.operations.length; i++ ) {
|
|
|
|
op = this.operations[i];
|
|
|
|
if ( op.type === 'replace' ) {
|
Get rid of 'reversed' flag on transactions
The way we implemented undoing transactions was horrible. We'd process
the original transaction, but with a reversed=true flag. That meant we
had to keep track of the 'reversed' flag everywhere, and use ternaries
like insert = reversed ? op.remove : op.insert; all over the place to
access transaction operations. Redo then worked by reapplying the
transaction. We would verify that this was OK by tracking whether the
transaction was in an applied state or an undone state.
This commit makes it so every transaction can only be applied once. To
undo, you obtain a mirror image of the transaction with tx.reverse(),
then apply that. To redo, you clone the original transaction with
tx.clone() and apply that. All the code that had to use ternaries to
check whether the transaction was being applied in reverse or not is
gone now, because you can only apply a given transaction forwards,
never in reverse.
Bonus:
* Make ve.dm.Document's .completeHistory a simple array of
transactions, rather than transaction/boolean pairs
* In the protection of double application test, clone the example
document properly; it modified ve.dm.example.data, which was "fine"
because it ran .commit() and .rollback() the same number of times
Change-Id: I3050c5430be4a12510f22e20853560b92acebb67
2013-10-03 00:43:56 +00:00
|
|
|
insertLength = op.insert.length;
|
|
|
|
removeLength = op.remove.length;
|
2013-02-22 20:01:02 +00:00
|
|
|
prevAdjustment = adjustment;
|
2012-10-10 18:08:33 +00:00
|
|
|
adjustment += insertLength - removeLength;
|
|
|
|
if ( offset === cursor + removeLength ) {
|
2013-02-23 01:13:43 +00:00
|
|
|
// Offset points to right after the removal or right before the insertion
|
|
|
|
if ( excludeInsertion && insertLength > removeLength ) {
|
|
|
|
// Translate it to before the insertion
|
|
|
|
return offset + adjustment - insertLength + removeLength;
|
|
|
|
} else {
|
|
|
|
// Translate it to after the removal/insertion
|
|
|
|
return offset + adjustment;
|
|
|
|
}
|
2013-02-22 20:01:02 +00:00
|
|
|
} else if ( offset === cursor ) {
|
|
|
|
// The offset points to right before the removal or replacement
|
|
|
|
if ( insertLength === 0 ) {
|
|
|
|
// Translate it to after the removal
|
|
|
|
return cursor + removeLength + adjustment;
|
|
|
|
} else {
|
|
|
|
// Translate it to before the replacement
|
|
|
|
// To translate this correctly, we have to use adjustment as it was before
|
|
|
|
// we adjusted it for this replacement
|
|
|
|
return cursor + prevAdjustment;
|
|
|
|
}
|
|
|
|
} else if ( offset > cursor && offset < cursor + removeLength ) {
|
2012-06-20 21:37:13 +00:00
|
|
|
// The offset points inside of the removal
|
2013-02-22 20:01:02 +00:00
|
|
|
// Translate it to after the removal
|
2012-10-10 18:08:33 +00:00
|
|
|
return cursor + removeLength + adjustment;
|
2012-06-20 21:37:13 +00:00
|
|
|
}
|
2012-10-10 18:08:33 +00:00
|
|
|
cursor += removeLength;
|
2012-06-20 21:37:13 +00:00
|
|
|
} else if ( op.type === 'retain' ) {
|
2012-08-30 22:26:43 +00:00
|
|
|
if ( offset >= cursor && offset < cursor + op.length ) {
|
2012-06-20 21:37:13 +00:00
|
|
|
return offset + adjustment;
|
|
|
|
}
|
|
|
|
cursor += op.length;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return offset + adjustment;
|
|
|
|
};
|
|
|
|
|
|
|
|
/**
|
2012-06-21 07:08:23 +00:00
|
|
|
* Translate a range based on a transaction.
|
|
|
|
*
|
|
|
|
* This is useful when you want to anticipate what a selection will be after a transaction is
|
|
|
|
* processed.
|
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @see #translateOffset
|
2012-06-21 07:08:23 +00:00
|
|
|
* @param {ve.Range} range Range in the linear model before the transaction has been processed
|
|
|
|
* @returns {ve.Range} Translated range, as it will be after processing transaction
|
2012-06-20 21:37:13 +00:00
|
|
|
*/
|
Get rid of 'reversed' flag on transactions
The way we implemented undoing transactions was horrible. We'd process
the original transaction, but with a reversed=true flag. That meant we
had to keep track of the 'reversed' flag everywhere, and use ternaries
like insert = reversed ? op.remove : op.insert; all over the place to
access transaction operations. Redo then worked by reapplying the
transaction. We would verify that this was OK by tracking whether the
transaction was in an applied state or an undone state.
This commit makes it so every transaction can only be applied once. To
undo, you obtain a mirror image of the transaction with tx.reverse(),
then apply that. To redo, you clone the original transaction with
tx.clone() and apply that. All the code that had to use ternaries to
check whether the transaction was being applied in reverse or not is
gone now, because you can only apply a given transaction forwards,
never in reverse.
Bonus:
* Make ve.dm.Document's .completeHistory a simple array of
transactions, rather than transaction/boolean pairs
* In the protection of double application test, clone the example
document properly; it modified ve.dm.example.data, which was "fine"
because it ran .commit() and .rollback() the same number of times
Change-Id: I3050c5430be4a12510f22e20853560b92acebb67
2013-10-03 00:43:56 +00:00
|
|
|
ve.dm.Transaction.prototype.translateRange = function ( range ) {
|
|
|
|
var start = this.translateOffset( range.start, true ),
|
|
|
|
end = this.translateOffset( range.end, false );
|
2013-02-23 01:13:43 +00:00
|
|
|
return range.isBackwards() ? new ve.Range( end, start ) : new ve.Range( start, end );
|
2012-06-20 21:37:13 +00:00
|
|
|
};
|
|
|
|
|
2013-09-10 18:49:31 +00:00
|
|
|
/**
|
|
|
|
* Add a final retain operation to finish off a transaction (internal helper).
|
|
|
|
*
|
|
|
|
* @private
|
|
|
|
* @method
|
|
|
|
* @param {ve.dm.Document} doc Document to finish off.
|
|
|
|
* @param {number} Final offset edited by the transaction up to this point.
|
|
|
|
* @param {number} [metaOffset=0] Final metadata offset edited, if nonzero.
|
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.pushFinalRetain = function ( doc, offset, metaOffset ) {
|
|
|
|
var data = doc.data,
|
|
|
|
metadata = doc.metadata,
|
|
|
|
finalMetadata = metadata.getData( data.getLength() );
|
|
|
|
if ( offset < doc.data.getLength() ) {
|
|
|
|
this.pushRetain( doc.data.getLength() - offset );
|
|
|
|
metaOffset = 0;
|
|
|
|
}
|
|
|
|
// if there is trailing metadata, push a final retainMetadata
|
|
|
|
if ( finalMetadata !== undefined && finalMetadata.length > 0 ) {
|
|
|
|
this.pushRetainMetadata( finalMetadata.length - ( metaOffset || 0 ) );
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-06-20 01:20:28 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Add a retain operation.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @param {number} length Length of content data to retain
|
2013-03-20 17:03:27 +00:00
|
|
|
* @throws {Error} Cannot retain backwards
|
2012-06-20 01:20:28 +00:00
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.dm.Transaction.prototype.pushRetain = function ( length ) {
|
2012-06-20 01:20:28 +00:00
|
|
|
if ( length < 0 ) {
|
2012-12-07 21:38:00 +00:00
|
|
|
throw new Error( 'Invalid retain length, cannot retain backwards:' + length );
|
2012-06-20 01:20:28 +00:00
|
|
|
}
|
|
|
|
if ( length ) {
|
|
|
|
var end = this.operations.length - 1;
|
|
|
|
if ( this.operations.length && this.operations[end].type === 'retain' ) {
|
|
|
|
this.operations[end].length += length;
|
|
|
|
} else {
|
|
|
|
this.operations.push( {
|
|
|
|
'type': 'retain',
|
|
|
|
'length': length
|
|
|
|
} );
|
|
|
|
}
|
2011-11-23 23:54:36 +00:00
|
|
|
}
|
2011-11-02 21:00:55 +00:00
|
|
|
};
|
|
|
|
|
2013-02-14 23:21:53 +00:00
|
|
|
/**
|
|
|
|
* Add a retain metadata operation.
|
|
|
|
* // TODO: this is a copy/paste of pushRetain (at the moment). Consider a refactor.
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {number} length Length of content data to retain
|
2013-03-20 17:03:27 +00:00
|
|
|
* @throws {Error} Cannot retain backwards
|
2013-02-14 23:21:53 +00:00
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.pushRetainMetadata = function ( length ) {
|
|
|
|
if ( length < 0 ) {
|
|
|
|
throw new Error( 'Invalid retain length, cannot retain backwards:' + length );
|
|
|
|
}
|
|
|
|
if ( length ) {
|
|
|
|
var end = this.operations.length - 1;
|
|
|
|
if ( this.operations.length && this.operations[end].type === 'retainMetadata' ) {
|
|
|
|
this.operations[end].length += length;
|
|
|
|
} else {
|
|
|
|
this.operations.push( {
|
|
|
|
'type': 'retainMetadata',
|
|
|
|
'length': length
|
|
|
|
} );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-04-17 17:53:26 +00:00
|
|
|
/**
|
|
|
|
* Adds a replace op to remove the desired range and, where required, splices in retain ops
|
|
|
|
* to prevent the deletion of internal data.
|
|
|
|
*
|
2013-08-30 22:24:43 +00:00
|
|
|
* An extra `replaceMetadata` operation might be pushed at the end if the
|
|
|
|
* affected region contains metadata; see
|
|
|
|
* {@link ve.dm.Transaction#pushReplace} for details.
|
|
|
|
*
|
2013-04-17 17:53:26 +00:00
|
|
|
* @param {ve.dm.Document} doc Document
|
|
|
|
* @param {number} removeStart Offset to start removing from
|
|
|
|
* @param {number} removeEnd Offset to remove to
|
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.addSafeRemoveOps = function ( doc, removeStart, removeEnd ) {
|
|
|
|
var i, retainStart, internalStackDepth = 0;
|
|
|
|
// Iterate over removal range and use a stack counter to determine if
|
|
|
|
// we are inside an internal node
|
ve.ce.ProtectedNode
Objective:
Generalize the shield and phantom magic, so we can use it for pretty much
any node we like. Usually this will be used with generated content nodes,
but also with aliens (of course) and possible other stuff in the future.
Bonus:
Also fixes a bug in DM that would crash VE when you selected to the end
and hit backspace.
Changes:
*.php
* Added links to files
aliens.html
* Added attributes to aliens to make them aliens again
ve.ce.AlienNode.js
* Moved shield and phantom functionality to ve.ce.ProtectedNode
ve.ce.AlienNode.js, ve.ce.MWReferenceListNode.js,
ve.ce.MWReferenceNode.js, ve.ce.MWTemplateNode.js
* Mixed in ve.ce.ProtectedNode
ve.ce.Node.css
* Reorganized styles and updated class names
* Added simple light blue hover with outline (using inset box shadow) for
protected nodes, same style as before for aliens
ve.ce.Surface.css
* Moved phantom styles to ve.ce.Node.css
ve.ce.BranchNode.js
* Moved call to setLive(false) to happen before detach() so that the
surface object is still available and events can be disconnected
ve.ce.BranchNode.js, ve.ce.Document.js, ve.ce.js, ve.ce.Surface.js, ve.ce.SurfaceObserver.js
* Adjusted CSS class names
ve.ce.Node.js
* Moved shield template to ve.ce.ProtectedNode
ve.ce.ProtectedNode.js
* New class, mix into another class to protect it from editing
ve.ce.RelocatableNode.js
* Renamed temporary surface property to relocatingSurface to avoid
confusion when debugging
ve.ce.Surface.js
* Moved phantom template to ve.ce.ProtectedNode
ve.dm.Transaction.js
* Fixed bug where most of the internal list was being deleted when the
end of the document was selected and the user pressed backspace
Change-Id: I2468b16e1ba6785ad298e38190e33493135719c3
2013-05-07 00:07:01 +00:00
|
|
|
for ( i = removeStart; i < removeEnd; i++ ) {
|
2013-04-17 17:53:26 +00:00
|
|
|
if ( doc.data.isElementData( i ) && ve.dm.nodeFactory.isNodeInternal( doc.data.getType( i ) ) ) {
|
|
|
|
if ( !doc.data.isCloseElementData( i ) ) {
|
|
|
|
if ( internalStackDepth === 0 ) {
|
|
|
|
this.pushReplace( doc, removeStart, i - removeStart, [] );
|
|
|
|
retainStart = i;
|
|
|
|
}
|
|
|
|
internalStackDepth++;
|
|
|
|
} else {
|
|
|
|
internalStackDepth--;
|
|
|
|
if ( internalStackDepth === 0 ) {
|
|
|
|
this.pushRetain( i + 1 - retainStart );
|
|
|
|
removeStart = i + 1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
this.pushReplace( doc, removeStart, removeEnd - removeStart, [] );
|
|
|
|
};
|
|
|
|
|
2012-03-08 23:21:17 +00:00
|
|
|
/**
|
2013-08-30 22:24:43 +00:00
|
|
|
* Add a replace operation, keeping metadata in sync if required.
|
|
|
|
*
|
|
|
|
* Note that metadata attached to removed content is moved so that it
|
|
|
|
* attaches just before the inserted content. If there is
|
|
|
|
* metadata attached to the removed content but there is no inserted
|
|
|
|
* content, then an extra `replaceMetadata` operation is pushed in order
|
|
|
|
* to properly insert the merged metadata before the character immediately
|
|
|
|
* after the removed content. (Note that there is an extra metadata element
|
|
|
|
* after the final data element; if the removed region is at the very end of
|
|
|
|
* the document, the inserted `replaceMetadata` operation targets this
|
|
|
|
* final metadata element.)
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2012-03-08 23:21:17 +00:00
|
|
|
* @method
|
2013-04-06 16:45:26 +00:00
|
|
|
* @param {ve.dm.Document} doc Document model
|
|
|
|
* @param {number} offset Offset to start at
|
|
|
|
* @param {number} removeLength Number of data items to remove
|
|
|
|
* @param {Array} insert Data to insert
|
2013-09-04 20:14:02 +00:00
|
|
|
* @param {Array} [insertMetadata] Overwrite the metadata with this data, rather than collapsing it
|
2012-03-08 23:21:17 +00:00
|
|
|
*/
|
2013-09-04 20:14:02 +00:00
|
|
|
ve.dm.Transaction.prototype.pushReplace = function ( doc, offset, removeLength, insert, insertMetadata ) {
|
2013-04-06 16:45:26 +00:00
|
|
|
if ( removeLength === 0 && insert.length === 0 ) {
|
2012-06-20 01:20:28 +00:00
|
|
|
// Don't push no-ops
|
|
|
|
return;
|
|
|
|
}
|
2013-04-06 16:45:26 +00:00
|
|
|
|
2013-09-04 20:14:02 +00:00
|
|
|
var op, extraMetadata, end = this.operations.length - 1,
|
2013-04-06 16:45:26 +00:00
|
|
|
lastOp = end >= 0 ? this.operations[end] : null,
|
2013-08-30 22:24:43 +00:00
|
|
|
penultOp = end >= 1 ? this.operations[ end - 1 ] : null,
|
|
|
|
range = new ve.Range( offset, offset + removeLength ),
|
|
|
|
remove = doc.getData( range ),
|
|
|
|
removeMetadata = doc.getMetadata( range ),
|
2013-09-04 20:14:02 +00:00
|
|
|
isRemoveEmpty = ve.compare( removeMetadata, new Array( removeMetadata.length ) ),
|
|
|
|
isInsertEmpty = insertMetadata && ve.compare( insertMetadata, new Array( insertMetadata.length ) );
|
2013-08-30 22:24:43 +00:00
|
|
|
|
2013-09-04 20:14:02 +00:00
|
|
|
if ( !insertMetadata && !isRemoveEmpty ) {
|
2013-08-30 22:24:43 +00:00
|
|
|
// if we are removing a range which includes metadata, we need to
|
|
|
|
// collapse it. If there's nothing to insert, we also need to add
|
|
|
|
// an extra `replaceMetadata` operation later in order to insert the
|
|
|
|
// collapsed metadata.
|
|
|
|
insertMetadata = ve.dm.MetaLinearData.static.merge( removeMetadata );
|
|
|
|
if ( insert.length === 0 ) {
|
|
|
|
extraMetadata = insertMetadata[0];
|
|
|
|
insertMetadata = [];
|
|
|
|
} else {
|
|
|
|
// pad out at end so insert metadata is the same length as insert data
|
|
|
|
ve.batchSplice( insertMetadata, 1, 0, new Array( insert.length - 1 ) );
|
|
|
|
}
|
2013-09-04 20:14:02 +00:00
|
|
|
} else if ( isInsertEmpty && isRemoveEmpty ) {
|
|
|
|
// No metadata changes, don't pollute the transaction with [undefined, undefined, ...]
|
|
|
|
insertMetadata = undefined;
|
2013-08-30 22:24:43 +00:00
|
|
|
}
|
2013-04-06 16:45:26 +00:00
|
|
|
|
2013-09-02 18:51:23 +00:00
|
|
|
// simple replaces can be combined
|
|
|
|
// (but don't do this if there is metadata to be removed and the previous
|
|
|
|
// replace had a non-zero insertion, because that would shift the metadata
|
|
|
|
// location.)
|
2013-08-30 22:24:43 +00:00
|
|
|
if (
|
|
|
|
lastOp && lastOp.type === 'replaceMetadata' &&
|
|
|
|
lastOp.insert.length > 0 && lastOp.remove.length === 0 &&
|
|
|
|
penultOp && penultOp.type === 'replace' &&
|
|
|
|
penultOp.insert.length === 0 /* this is always true */
|
|
|
|
) {
|
|
|
|
this.operations.pop();
|
|
|
|
lastOp = penultOp;
|
|
|
|
/* fall through */
|
|
|
|
}
|
2013-09-02 18:51:23 +00:00
|
|
|
if (
|
|
|
|
lastOp && lastOp.type === 'replace' &&
|
2013-08-30 22:24:43 +00:00
|
|
|
!( lastOp.insert.length > 0 && insertMetadata !== undefined )
|
2013-09-02 18:51:23 +00:00
|
|
|
) {
|
|
|
|
lastOp = this.operations.pop();
|
|
|
|
this.lengthDifference -= lastOp.insert.length - lastOp.remove.length;
|
|
|
|
this.pushReplace(
|
|
|
|
doc,
|
|
|
|
offset - lastOp.remove.length,
|
|
|
|
lastOp.remove.length + removeLength,
|
|
|
|
lastOp.insert.concat( insert )
|
|
|
|
);
|
2013-08-30 22:24:43 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ( lastOp && lastOp.type === 'replaceMetadata' ) {
|
|
|
|
// `replace` operates on the metadata at the given offset; the transaction
|
|
|
|
// touches the same region twice if `replace` follows a `replaceMetadata`
|
|
|
|
// without a `retain` in between.
|
|
|
|
throw new Error( 'replace after replaceMetadata not allowed' );
|
|
|
|
}
|
|
|
|
|
|
|
|
op = {
|
|
|
|
'type': 'replace',
|
|
|
|
'remove': remove,
|
|
|
|
'insert': insert
|
|
|
|
};
|
|
|
|
if ( insertMetadata !== undefined ) {
|
|
|
|
op.removeMetadata = removeMetadata;
|
|
|
|
op.insertMetadata = insertMetadata;
|
|
|
|
}
|
|
|
|
this.operations.push( op );
|
|
|
|
this.lengthDifference += insert.length - remove.length;
|
|
|
|
if ( extraMetadata !== undefined ) {
|
|
|
|
this.pushReplaceMetadata( [], extraMetadata );
|
2013-02-23 00:40:53 +00:00
|
|
|
}
|
2012-03-08 23:21:17 +00:00
|
|
|
};
|
|
|
|
|
2013-02-14 23:21:53 +00:00
|
|
|
/**
|
|
|
|
* Add a replace metadata operation
|
|
|
|
*
|
|
|
|
* @method
|
|
|
|
* @param {Array} remove Metadata to remove
|
|
|
|
* @param {Array} insert Metadata to replace 'remove' with
|
|
|
|
*/
|
|
|
|
ve.dm.Transaction.prototype.pushReplaceMetadata = function ( remove, insert ) {
|
|
|
|
if ( remove.length === 0 && insert.length === 0 ) {
|
|
|
|
// Don't push no-ops
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
this.operations.push( {
|
|
|
|
'type': 'replaceMetadata',
|
|
|
|
'remove': remove,
|
|
|
|
'insert': insert
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
2011-11-04 21:06:06 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Add an element attribute change operation.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-04 21:06:06 +00:00
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @param {string} key Name of attribute to change
|
2012-06-21 01:40:24 +00:00
|
|
|
* @param {Mixed} from Value change attribute from, or undefined if not previously set
|
|
|
|
* @param {Mixed} to Value to change attribute to, or undefined to remove
|
2011-11-04 21:06:06 +00:00
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.dm.Transaction.prototype.pushReplaceElementAttribute = function ( key, from, to ) {
|
2011-11-02 21:00:55 +00:00
|
|
|
this.operations.push( {
|
|
|
|
'type': 'attribute',
|
|
|
|
'key': key,
|
2012-02-22 21:23:28 +00:00
|
|
|
'from': from,
|
|
|
|
'to': to
|
2011-11-02 21:00:55 +00:00
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
2011-11-04 21:06:06 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Add a start annotating operation.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-04 21:06:06 +00:00
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @param {string} method Method to use, either "set" or "clear"
|
2011-11-04 21:06:06 +00:00
|
|
|
* @param {Object} annotation Annotation object to start setting or clearing from content data
|
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.dm.Transaction.prototype.pushStartAnnotating = function ( method, annotation ) {
|
2011-11-02 21:00:55 +00:00
|
|
|
this.operations.push( {
|
|
|
|
'type': 'annotate',
|
|
|
|
'method': method,
|
|
|
|
'bias': 'start',
|
|
|
|
'annotation': annotation
|
|
|
|
} );
|
|
|
|
};
|
|
|
|
|
2011-11-04 21:06:06 +00:00
|
|
|
/**
|
2013-01-15 23:38:49 +00:00
|
|
|
* Add a stop annotating operation.
|
2012-06-20 01:20:28 +00:00
|
|
|
*
|
2011-11-04 21:06:06 +00:00
|
|
|
* @method
|
JSDuck: Generated code documentation!
See CODING.md for how to run it.
Mistakes fixed:
* Warning: Unknown type function
-> Function
* Warning: Unknown type DOMElement
-> HTMLElement
* Warning: Unknown type DOM Node
-> HTMLElement
* Warning: Unknown type Integer
-> Mixed
* Warning: Unknown type Command
-> ve.Command
* Warning: Unknown type any
-> number
* Warning: Unknown type ve.Transaction
-> ve.dm.Transaction
* Warning: Unknown type ve.dm.AnnotationSet
-> ve.AnnotationSet
* Warning: Unknown type false
-> boolean
* Warning: Unknown type ve.dm.AlienNode
ve.dm doesn't have a generic AlienNode like ve.ce
-> Unknown type ve.dm.AlienInlineNode|ve.dm.AlienBlockNode
* Warning: Unknown type ve.ve.Surface
-> ve.ce.Surface
* ve.example.lookupNode:
-> Last @param should be @return
* ve.dm.Transaction.prototype.pushReplace:
-> @param {Array] should be @param {Array}
* Warning: ve.BranchNode.js:27: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
* Warning: ve.LeafNode.js:21: {@link ve.Node#hasChildren} links to non-existing member
-> (removed)
Differences fixed:
* Variadic arguments are like @param {Type...} [name]
instead of @param {Type} [name...]
* Convert all file headers from /** to /*! because JSDuck tries
to parse all /** blocks and fails to parse with all sorts of
errors for "Global property", "Unnamed property", and
"Duplicate property".
Find: \/\*\*([^@]+)(@copyright)
Replace: /*!$1$2
* Indented blocks are considered code examples.
A few methods had documentation with numbered lists that were
indented, which have now been updated to not be intended.
* The free-form text descriptions are parsed with Markdown,
which requires lists to be separated from paragraphs by an
empty line.
And we should use `backticks` instead of {braces} for inline
code in text paragraphs.
* Doc blocks for classes and their constructor have to be
in the correct order (@constructor, @param, @return must be
before @class, @abstract, @extends etc.)
* `@extends Class` must not have Class {wrapped}
* @throws must start with a {Type}
* @example means something else. It is used for an inline demo
iframe, not code block. For that simply indent with spaces.
* @member means something else.
Non-function properties are marked with @property, not @member.
* To create a link to a class or member, in most cases the name
is enough to create a link. E.g. Foo, Foo.bar, Foo.bar#quux,
where a hash stands for "instance member", so Foo.bar#quux,
links to Foo.bar.prototype.quux (the is not supported, as
"prototype" is considered an implementation detail, it only
indexes class name and method name).
If the magic linker doesn't work for some case, the
verbose syntax is {@link #target label}.
* @property can't have sub-properties (nested @param and @return
values are supported, only @static @property can't be nested).
We only have one case of this, which can be worked around by
moving those in a new virtual class. The code is unaltered
(only moved down so that it isn't with the scope of the main
@class block). ve.dm.TransactionProcessor.processors.
New:
* @mixins: Classes mixed into the current class.
* @event: Events that can be emitted by a class. These are also
inherited by subclasses. (+ @param, @return and @preventable).
So ve.Node#event-attach is inherited to ve.dm.BreakNode,
just like @method is.
* @singleton: Plain objects such as ve, ve.dm, ve.ce were missing
documentation causing a tree error. Documented those as a
JSDuck singleton, which they but just weren't documented yet.
NB: Members of @singleton don't need @static (if present,
triggers a compiler warning).
* @chainable: Shorthand for "@return this". We were using
"@return {classname}" which is ambiguous (returns the same
instance or another instance?), @chainable is specifically
for "@return this". Creates proper labels in the generated
HTML pages.
Removed:
* @mixin: (not to be confused with @mixins). Not supported by
JSDuck. Every class is standalone anyway. Where needed marked
them @class + @abstract instead.
Change-Id: I6a7c9e8ee8f995731bc205d666167874eb2ebe23
2013-01-04 08:54:17 +00:00
|
|
|
* @param {string} method Method to use, either "set" or "clear"
|
2011-11-04 21:06:06 +00:00
|
|
|
* @param {Object} annotation Annotation object to stop setting or clearing from content data
|
|
|
|
*/
|
2012-08-07 01:50:44 +00:00
|
|
|
ve.dm.Transaction.prototype.pushStopAnnotating = function ( method, annotation ) {
|
2011-11-02 21:00:55 +00:00
|
|
|
this.operations.push( {
|
|
|
|
'type': 'annotate',
|
|
|
|
'method': method,
|
|
|
|
'bias': 'stop',
|
|
|
|
'annotation': annotation
|
|
|
|
} );
|
|
|
|
};
|