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 example data sets .
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
* /
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
/ * *
* @ class
* @ singleton
* @ ignore
* /
2012-04-27 21:59:52 +00:00
ve . dm . example = { } ;
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
/* Methods */
2012-10-06 00:34:12 +00:00
/ * *
* Convert arrays of shorthand annotations in a data fragment to AnnotationSets with real
2013-03-20 22:35:05 +00:00
* annotation objects , and wraps the result in a ve . dm . ElementLinearData object .
2012-10-06 00:34:12 +00:00
*
* Shorthand notation for annotations is :
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
* [ 'a' , [ { 'type' : 'link' , 'attributes' : { 'href' : '...' } ] ]
2012-10-06 00:34:12 +00:00
*
* The actual storage format has an instance of ve . dm . LinkAnnotation instead of the plain object ,
2013-03-20 22:35:05 +00:00
* and an instance of ve . dm . AnnotationSet instead of the array .
2012-10-06 00:34:12 +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
* @ method
2013-03-20 22:35:05 +00:00
* @ param { Array } data Linear model data
* @ param { ve . dm . IndexValueStore } [ store ] Index - value store to use , creates one if undefined
* @ returns { ve . dm . ElementLinearData } Element linear data store
* @ throws { Error } Example data passed to preprocessAnnotations by reference
2012-10-06 00:34:12 +00:00
* /
2013-03-20 22:35:05 +00:00
ve . dm . example . preprocessAnnotations = function ( data , store ) {
2012-08-24 02:06:36 +00:00
var i , key ;
2013-03-20 22:35:05 +00:00
// Sanity check to make sure ve.dm.example data has not been passed in
// by reference. Always use ve.copyArray.
for ( i in ve . dm . example ) {
if ( data === ve . dm . example [ i ] ) {
throw new Error ( 'Example data passed to preprocessAnnotations by reference' ) ;
}
}
store = store || new ve . dm . IndexValueStore ( ) ;
2012-08-24 02:06:36 +00:00
for ( i = 0 ; i < data . length ; i ++ ) {
key = data [ i ] . annotations ? 'annotations' : 1 ;
2013-03-20 22:35:05 +00:00
// check for shorthand annotation objects in array
if ( ve . isArray ( data [ i ] [ key ] ) && data [ i ] [ key ] [ 0 ] . type ) {
data [ i ] [ key ] = ve . dm . example . createAnnotationSet ( store , data [ i ] [ key ] ) . getIndexes ( ) ;
2012-10-06 00:34:12 +00:00
}
}
2013-03-20 22:35:05 +00:00
return new ve . dm . ElementLinearData ( store , data ) ;
2012-10-06 00:34:12 +00:00
} ;
/ * *
* Create an annotation object from shorthand notation .
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
* @ method
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
* @ param { Object } annotation Plain object with type and attributes properties
2012-10-06 00:34:12 +00:00
* @ return { ve . dm . Annotation } Instance of the right ve . dm . Annotation subclass
* /
ve . dm . example . createAnnotation = function ( annotation ) {
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
return ve . dm . annotationFactory . create ( annotation . type , annotation ) ;
2012-10-06 00:34:12 +00:00
} ;
/ * *
* Create an AnnotationSet from an array of shorthand annotations .
*
* This calls ve . dm . example . createAnnotation ( ) for each element and puts the result in an
* AnnotationSet .
*
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
* @ method
2012-10-06 00:34:12 +00:00
* @ param { Array } annotations Array of annotations in shorthand format
2013-03-20 22:35:05 +00:00
* @ return { ve . dm . AnnotationSet }
2012-10-06 00:34:12 +00:00
* /
2013-03-20 22:35:05 +00:00
ve . dm . example . createAnnotationSet = function ( store , annotations ) {
2012-10-06 00:34:12 +00:00
var i ;
for ( i = 0 ; i < annotations . length ; i ++ ) {
annotations [ i ] = ve . dm . example . createAnnotation ( annotations [ i ] ) ;
}
2013-04-18 17:56:03 +00:00
return new ve . dm . AnnotationSet ( store , store . indexes ( annotations ) ) ;
2012-08-24 02:06:36 +00:00
} ;
2012-10-06 00:34:12 +00:00
/* Some common annotations in shorthand format */
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
ve . dm . example . bold = { 'type' : 'textStyle/bold' } ;
ve . dm . example . italic = { 'type' : 'textStyle/italic' } ;
ve . dm . example . underline = { 'type' : 'textStyle/underline' } ;
ve . dm . example . span = { 'type' : 'textStyle/span' } ;
2012-10-06 00:34:12 +00:00
2013-03-20 22:35:05 +00:00
/ * *
* Creates a document from example data .
*
* Defaults to ve . dm . example . data if no name is supplied .
*
* @ param { string } [ name = 'data' ] Named element of ve . dm . example
* @ param { ve . dm . IndexValueStore } [ store ] A specific index - value store to use , optionally .
* @ returns { ve . dm . Document } Document
* @ throws { Error } Example data not found
* /
ve . dm . example . createExampleDocument = function ( name , store ) {
name = name || 'data' ;
store = store || new ve . dm . IndexValueStore ( ) ;
if ( ve . dm . example [ name ] === undefined ) {
throw new Error ( 'Example data \'' + name + '\' not found' ) ;
}
return new ve . dm . Document (
ve . dm . example . preprocessAnnotations ( ve . copyArray ( ve . dm . example [ name ] ) , store )
) ;
} ;
2013-04-02 21:40:07 +00:00
ve . dm . example . testDir = window . mw ?
( window . mw . config . get ( 'wgExtensionAssetsPath' ) + '/VisualEditor/modules/ve/test' ) :
'.' ;
ve . dm . example . imgSrc = ve . dm . example . testDir + '/example.png' ;
2012-04-27 21:59:52 +00:00
/ * *
* Serialized HTML .
2012-05-14 22:05:09 +00:00
*
2012-04-27 21:59:52 +00:00
* This is what the parser will emit .
2012-08-16 20:06:18 +00:00
* TODO remove some of the < p > s here to test automatic wrapping
2012-04-27 21:59:52 +00:00
* /
ve . dm . example . html =
'<h1>a<b>b</b><i>c</i></h1>' +
'<table>' +
'<tr>' +
'<td>' +
'<p>d</p>' +
'<ul>' +
'<li>' +
2012-08-03 19:12:09 +00:00
'<p>e</p>' +
2012-04-27 21:59:52 +00:00
'<ul>' +
'<li>' +
2012-08-03 19:12:09 +00:00
'<p>f</p>' +
2012-04-27 21:59:52 +00:00
'</li>' +
'</ul>' +
'</li>' +
'</ul>' +
'<ol>' +
'<li>' +
2012-08-03 19:12:09 +00:00
'<p>g</p>' +
2012-04-27 21:59:52 +00:00
'</li>' +
'</ol>' +
'</td>' +
'</tr>' +
'</table>' +
2013-04-02 21:40:07 +00:00
'<pre>h<img src="' + ve . dm . example . imgSrc + '">i</pre>' +
2012-05-04 18:56:32 +00:00
'<dl>' +
'<dt>' +
'<p>j</p>' +
'</dt>' +
'<dd>' +
'<p>k</p>' +
'</dd>' +
2012-05-16 20:33:27 +00:00
'</dl>' +
'<p>l</p>' +
'<p>m</p>' ;
2012-04-27 21:59:52 +00:00
/ *
* Linear data .
2012-05-14 22:05:09 +00:00
*
2012-04-27 21:59:52 +00:00
* This is what we convert serialized HTML from the parser into so we can work with it more easily .
2012-05-14 22:05:09 +00:00
*
2012-04-27 21:59:52 +00:00
* There are three types of components in content data :
2012-05-14 22:05:09 +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
* { string } Plain text character
2012-05-15 00:15:28 +00:00
*
2012-04-27 21:59:52 +00:00
* { Array } Annotated character
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
* 0 : { string } Character
2012-04-27 21:59:52 +00:00
* 1 : { Object } List of references to immutable annotation objects , keyed by JSON
* serializations of their values ( hashes )
2012-05-15 00:15:28 +00:00
*
2012-04-27 21:59:52 +00:00
* { Object } Opening or closing structural 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
* type : { string } Symbolic node type name , if closing element first character will be "/"
2012-04-27 21:59:52 +00:00
* [ attributes ] : { Object } List of symbolic attribute name and literal value pairs
* /
ve . dm . example . data = [
// 0 - Beginning of heading
{ 'type' : 'heading' , 'attributes' : { 'level' : 1 } } ,
// 1 - Plain "a"
'a' ,
// 2 - Bold "b"
2012-10-06 00:34:12 +00:00
[ 'b' , [ ve . dm . example . bold ] ] ,
2012-04-27 21:59:52 +00:00
// 3 - Italic "c"
2012-10-06 00:34:12 +00:00
[ 'c' , [ ve . dm . example . italic ] ] ,
2012-04-27 21:59:52 +00:00
// 4 - End of heading
{ 'type' : '/heading' } ,
// 5 - Beginning of table
{ 'type' : 'table' } ,
2012-06-08 05:08:49 +00:00
// 6 - Beginning of body
{ 'type' : 'tableSection' , 'attributes' : { 'style' : 'body' } } ,
// 7 - Beginning of row
2012-04-27 21:59:52 +00:00
{ 'type' : 'tableRow' } ,
2012-06-08 05:08:49 +00:00
// 8 - Beginning of cell
2012-06-08 05:02:25 +00:00
{ 'type' : 'tableCell' , 'attributes' : { 'style' : 'data' } } ,
2012-06-08 05:08:49 +00:00
// 9 - Beginning of paragraph
2012-04-27 21:59:52 +00:00
{ 'type' : 'paragraph' } ,
2012-06-08 05:08:49 +00:00
// 10 - Plain "d"
2012-04-27 21:59:52 +00:00
'd' ,
2012-06-08 05:08:49 +00:00
// 11 - End of paragraph
2012-04-27 21:59:52 +00:00
{ 'type' : '/paragraph' } ,
2012-06-08 05:08:49 +00:00
// 12 - Beginning of bullet list
2012-05-03 21:54:27 +00:00
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
2012-06-08 05:08:49 +00:00
// 13 - Beginning of list item
2012-05-04 22:50:32 +00:00
{ 'type' : 'listItem' } ,
2012-06-08 05:08:49 +00:00
// 14 - Beginning of paragraph
2012-04-27 21:59:52 +00:00
{ 'type' : 'paragraph' } ,
2012-06-08 05:08:49 +00:00
// 15 - Plain "e"
2012-04-27 21:59:52 +00:00
'e' ,
2012-06-08 05:08:49 +00:00
// 16 - End of paragraph
2012-04-27 21:59:52 +00:00
{ 'type' : '/paragraph' } ,
2012-06-08 05:08:49 +00:00
// 17 - Beginning of nested bullet list
2012-05-03 21:54:27 +00:00
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
2012-06-08 05:08:49 +00:00
// 18 - Beginning of nested bullet list item
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
{ 'type' : 'listItem' } ,
2012-06-08 05:08:49 +00:00
// 19 - Beginning of paragraph
2012-04-27 21:59:52 +00:00
{ 'type' : 'paragraph' } ,
2012-06-08 05:08:49 +00:00
// 20 - Plain "f"
2012-04-27 21:59:52 +00:00
'f' ,
2012-06-08 05:08:49 +00:00
// 21 - End of paragraph
2012-04-27 21:59:52 +00:00
{ 'type' : '/paragraph' } ,
2012-06-08 05:08:49 +00:00
// 22 - End of nested bullet list item
2012-04-27 21:59:52 +00:00
{ 'type' : '/listItem' } ,
2012-06-08 05:08:49 +00:00
// 23 - End of nested bullet list
2012-04-27 21:59:52 +00:00
{ 'type' : '/list' } ,
2012-06-08 05:08:49 +00:00
// 24 - End of bullet list item
2012-04-27 21:59:52 +00:00
{ 'type' : '/listItem' } ,
2012-06-08 05:08:49 +00:00
// 25 - End of bullet list
2012-04-27 21:59:52 +00:00
{ 'type' : '/list' } ,
2012-06-08 05:08:49 +00:00
// 26 - Beginning of numbered list
2012-05-03 21:54:27 +00:00
{ 'type' : 'list' , 'attributes' : { 'style' : 'number' } } ,
2012-06-08 05:08:49 +00:00
// 27 - Beginning of numbered list item
2012-05-04 22:50:32 +00:00
{ 'type' : 'listItem' } ,
2012-06-08 05:08:49 +00:00
// 28 - Beginning of paragraph
2012-04-27 21:59:52 +00:00
{ 'type' : 'paragraph' } ,
2012-06-08 05:08:49 +00:00
// 29 - Plain "g"
2012-04-27 21:59:52 +00:00
'g' ,
2012-06-08 05:08:49 +00:00
// 30 - End of paragraph
2012-04-27 21:59:52 +00:00
{ 'type' : '/paragraph' } ,
2012-06-08 05:08:49 +00:00
// 31 - End of item
2012-04-27 21:59:52 +00:00
{ 'type' : '/listItem' } ,
2013-03-01 01:20:59 +00:00
// 32 - End of lis t
2012-04-27 21:59:52 +00:00
{ 'type' : '/list' } ,
2012-06-08 05:08:49 +00:00
// 33 - End of cell
2012-04-27 21:59:52 +00:00
{ 'type' : '/tableCell' } ,
2012-06-08 05:08:49 +00:00
// 34 - End of row
2012-04-27 21:59:52 +00:00
{ 'type' : '/tableRow' } ,
2012-06-08 05:08:49 +00:00
// 35 - End of body
{ 'type' : '/tableSection' } ,
// 36 - End of table
2012-04-27 21:59:52 +00:00
{ 'type' : '/table' } ,
2012-06-08 05:08:49 +00:00
// 37 - Beginning of preformatted
2012-04-27 21:59:52 +00:00
{ 'type' : 'preformatted' } ,
2012-06-08 05:08:49 +00:00
// 38 - Plain "h"
2012-04-27 21:59:52 +00:00
'h' ,
2012-06-08 05:08:49 +00:00
// 39 - Beginning of inline image
2013-04-10 19:56:20 +00:00
{ 'type' : 'image' , 'attributes' : {
'html/0/src' : ve . dm . example . imgSrc ,
'src' : ve . dm . example . imgSrc ,
'width' : null ,
'height' : null
} } ,
2012-06-08 05:08:49 +00:00
// 40 - End of inline image
2012-04-27 21:59:52 +00:00
{ 'type' : '/image' } ,
2012-06-08 05:08:49 +00:00
// 41 - Plain "i"
2012-04-27 21:59:52 +00:00
'i' ,
2012-06-08 05:08:49 +00:00
// 42 - End of preformatted
2012-05-04 18:56:32 +00:00
{ 'type' : '/preformatted' } ,
2012-06-08 05:08:49 +00:00
// 43 - Beginning of definition list
2012-05-04 18:56:32 +00:00
{ 'type' : 'definitionList' } ,
2012-06-08 05:08:49 +00:00
// 44 - Beginning of definition list term item
2012-05-04 18:56:32 +00:00
{ 'type' : 'definitionListItem' , 'attributes' : { 'style' : 'term' } } ,
2012-06-08 05:08:49 +00:00
// 45 - Beginning of paragraph
2012-05-04 18:56:32 +00:00
{ 'type' : 'paragraph' } ,
2012-06-08 05:08:49 +00:00
// 46 - Plain "j"
2012-05-04 18:56:32 +00:00
'j' ,
2012-06-08 05:08:49 +00:00
// 47 - End of paragraph
2012-05-04 18:56:32 +00:00
{ 'type' : '/paragraph' } ,
2012-06-08 05:08:49 +00:00
// 48 - End of definition list term item
2012-05-04 18:56:32 +00:00
{ 'type' : '/definitionListItem' } ,
2012-06-08 05:08:49 +00:00
// 49 - Beginning of definition list definition item
2012-05-04 18:56:32 +00:00
{ 'type' : 'definitionListItem' , 'attributes' : { 'style' : 'definition' } } ,
2012-06-08 05:08:49 +00:00
// 50 - Beginning of paragraph
2012-05-04 18:56:32 +00:00
{ 'type' : 'paragraph' } ,
2012-06-08 05:08:49 +00:00
// 51 - Plain "k"
2012-05-11 17:29:09 +00:00
'k' ,
2012-06-08 05:08:49 +00:00
// 52 - End of paragraph
2012-05-04 18:56:32 +00:00
{ 'type' : '/paragraph' } ,
2012-06-08 05:08:49 +00:00
// 53 - End of definition list definition item
2012-05-04 18:56:32 +00:00
{ 'type' : '/definitionListItem' } ,
2012-06-08 05:08:49 +00:00
// 54 - End of definition list
2012-05-16 20:33:27 +00:00
{ 'type' : '/definitionList' } ,
2012-06-08 05:08:49 +00:00
// 55 - Beginning of paragraph
2012-05-16 20:33:27 +00:00
{ 'type' : 'paragraph' } ,
2012-06-08 05:08:49 +00:00
// 56 - Plain "l"
2012-05-16 20:33:27 +00:00
'l' ,
2012-06-08 05:08:49 +00:00
// 57 - End of paragraph
2012-05-16 20:33:27 +00:00
{ 'type' : '/paragraph' } ,
2012-06-08 05:08:49 +00:00
// 58 - Beginning of paragraph
2012-05-16 20:33:27 +00:00
{ 'type' : 'paragraph' } ,
2012-06-08 05:08:49 +00:00
// 59 - Plain "m"
2012-05-16 20:33:27 +00:00
'm' ,
2012-06-08 05:08:49 +00:00
// 60 - End of paragraph
2012-05-16 20:33:27 +00:00
{ 'type' : '/paragraph' }
2012-06-08 05:08:49 +00:00
// 61 - End of document
2012-06-04 22:59:04 +00:00
] ;
ve . dm . example . alienData = [
// 0 - Open alienBlock
{ 'type' : 'alienBlock' } ,
// 1 - Close alienBlock
{ 'type' : '/alienBlock' } ,
// 2 - Open paragraph
{ 'type' : 'paragraph' } ,
// 3 - Plain character 'a'
'a' ,
// 4 - Open alienInline
{ 'type' : 'alienBlock' } ,
// 5 - Close alienInline
{ 'type' : '/alienBlock' } ,
// 6 - Plain character 'b'
'b' ,
// 7 - Close paragraph
{ 'type' : '/paragraph' } ,
// 8 - Open alienBlock
{ 'type' : 'alienBlock' } ,
// 9 - Close alienBlock
{ 'type' : '/alienBlock' }
// 10 - End of document
2012-04-27 21:59:52 +00:00
] ;
2012-10-30 01:42:12 +00:00
ve . dm . example . withMeta = [
2012-11-20 04:01:09 +00:00
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-11-20 04:01:09 +00:00
'attributes' : {
'style' : 'comment' ,
'text' : ' No content conversion '
}
} ,
2013-02-21 23:01:04 +00:00
{ 'type' : '/alienMeta' } ,
2012-10-30 01:42:12 +00:00
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
'style' : 'meta' ,
2013-02-16 02:37:50 +00:00
'key' : 'mw:PageProp/nocc' ,
'html/0/property' : 'mw:PageProp/nocc'
2012-10-30 01:42:12 +00:00
}
} ,
2013-02-21 23:01:04 +00:00
{ 'type' : '/alienMeta' } ,
2012-10-30 01:42:12 +00:00
{ 'type' : 'paragraph' } ,
'F' ,
'o' ,
'o' ,
{
2013-03-21 19:18:52 +00:00
'type' : 'MWcategory' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
2013-03-21 19:18:52 +00:00
'hrefPrefix' : './' ,
'category' : 'Category:Bar' ,
'origCategory' : 'Category:Bar' ,
'sortkey' : '' ,
'origSortkey' : '' ,
'html/0/rel' : 'mw:WikiLink/Category' ,
'html/0/href' : './Category:Bar'
2012-10-30 01:42:12 +00:00
}
} ,
2013-03-21 19:18:52 +00:00
{ 'type' : '/MWcategory' } ,
2012-10-30 01:42:12 +00:00
'B' ,
'a' ,
'r' ,
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
'style' : 'meta' ,
'key' : 'mw:foo' ,
2013-02-16 02:37:50 +00:00
'value' : 'bar' ,
'html/0/content' : 'bar' ,
'html/0/property' : 'mw:foo'
2012-10-30 01:42:12 +00:00
}
} ,
2013-02-21 23:01:04 +00:00
{ 'type' : '/alienMeta' } ,
2012-10-30 01:42:12 +00:00
'B' ,
'a' ,
2012-11-20 04:01:09 +00:00
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-11-20 04:01:09 +00:00
'attributes' : {
'style' : 'comment' ,
'text' : ' inline '
}
} ,
2013-02-21 23:01:04 +00:00
{ 'type' : '/alienMeta' } ,
2012-10-30 01:42:12 +00:00
'z' ,
{ 'type' : '/paragraph' } ,
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
'style' : 'meta' ,
'key' : 'mw:bar' ,
2013-02-16 02:37:50 +00:00
'value' : 'baz' ,
'html/0/content' : 'baz' ,
'html/0/property' : 'mw:bar'
2012-10-30 01:42:12 +00:00
}
} ,
2013-02-21 23:01:04 +00:00
{ 'type' : '/alienMeta' } ,
2012-11-20 04:01:09 +00:00
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-11-20 04:01:09 +00:00
'attributes' : {
'style' : 'comment' ,
'text' : 'barbaz'
}
} ,
2013-02-21 23:01:04 +00:00
{ 'type' : '/alienMeta' } ,
2012-10-30 01:42:12 +00:00
{
2013-03-21 19:18:52 +00:00
'type' : 'MWcategory' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
2013-03-21 19:18:52 +00:00
'hrefPrefix' : './' ,
'category' : 'Category:Foo foo' ,
'origCategory' : 'Category:Foo_foo' ,
'sortkey' : 'Bar baz#quux' ,
'origSortkey' : 'Bar baz%23quux' ,
'html/0/href' : './Category:Foo_foo#Bar baz%23quux' ,
2013-02-16 02:37:50 +00:00
'html/0/rel' : 'mw:WikiLink/Category'
2012-10-30 01:42:12 +00:00
}
} ,
2013-03-21 19:18:52 +00:00
{ 'type' : '/MWcategory' } ,
2012-10-30 01:42:12 +00:00
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
'style' : 'meta' ,
'key' : null ,
2013-02-06 19:47:52 +00:00
'html/0/typeof' : 'mw:Placeholder' ,
'html/0/data-parsoid' : 'foobar'
2012-10-30 01:42:12 +00:00
}
} ,
2013-02-21 23:01:04 +00:00
{ 'type' : '/alienMeta' }
2012-10-30 01:42:12 +00:00
] ;
ve . dm . example . withMetaPlainData = [
{ 'type' : 'paragraph' } ,
'F' ,
'o' ,
'o' ,
'B' ,
'a' ,
'r' ,
'B' ,
'a' ,
'z' ,
{ 'type' : '/paragraph' }
] ;
ve . dm . example . withMetaMetaData = [
[
2012-11-20 04:01:09 +00:00
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-11-20 04:01:09 +00:00
'attributes' : {
'style' : 'comment' ,
'text' : ' No content conversion '
}
} ,
2012-10-30 01:42:12 +00:00
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
'style' : 'meta' ,
2013-02-16 02:37:50 +00:00
'key' : 'mw:PageProp/nocc' ,
'html/0/property' : 'mw:PageProp/nocc'
2012-10-30 01:42:12 +00:00
}
}
] ,
undefined ,
undefined ,
undefined ,
[
{
2013-03-21 19:18:52 +00:00
'type' : 'MWcategory' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
2013-03-21 19:18:52 +00:00
'hrefPrefix' : './' ,
'category' : 'Category:Bar' ,
'origCategory' : 'Category:Bar' ,
'sortkey' : '' ,
'origSortkey' : '' ,
'html/0/rel' : 'mw:WikiLink/Category' ,
'html/0/href' : './Category:Bar'
2012-10-30 01:42:12 +00:00
}
}
] ,
undefined ,
undefined ,
[
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
'style' : 'meta' ,
'key' : 'mw:foo' ,
2013-02-16 02:37:50 +00:00
'value' : 'bar' ,
'html/0/content' : 'bar' ,
'html/0/property' : 'mw:foo'
2012-10-30 01:42:12 +00:00
}
}
] ,
undefined ,
2012-11-20 04:01:09 +00:00
[
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-11-20 04:01:09 +00:00
'attributes' : {
'style' : 'comment' ,
'text' : ' inline '
}
}
] ,
2012-10-30 01:42:12 +00:00
undefined ,
[
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
'style' : 'meta' ,
'key' : 'mw:bar' ,
2013-02-16 02:37:50 +00:00
'value' : 'baz' ,
'html/0/content' : 'baz' ,
'html/0/property' : 'mw:bar'
2012-10-30 01:42:12 +00:00
}
} ,
2012-11-20 04:01:09 +00:00
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-11-20 04:01:09 +00:00
'attributes' : {
'style' : 'comment' ,
'text' : 'barbaz'
}
} ,
2012-10-30 01:42:12 +00:00
{
2013-03-21 19:18:52 +00:00
'type' : 'MWcategory' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
2013-03-21 19:18:52 +00:00
'hrefPrefix' : './' ,
'category' : 'Category:Foo foo' ,
'origCategory' : 'Category:Foo_foo' ,
'sortkey' : 'Bar baz#quux' ,
'origSortkey' : 'Bar baz%23quux' ,
'html/0/href' : './Category:Foo_foo#Bar baz%23quux' ,
2013-02-16 02:37:50 +00:00
'html/0/rel' : 'mw:WikiLink/Category'
2012-10-30 01:42:12 +00:00
}
} ,
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2012-10-30 01:42:12 +00:00
'attributes' : {
'style' : 'meta' ,
'key' : null ,
2013-02-06 19:47:52 +00:00
'html/0/typeof' : 'mw:Placeholder' ,
2013-02-16 02:37:50 +00:00
'html/0/data-parsoid' : 'foobar'
2012-10-30 01:42:12 +00:00
}
}
]
] ;
2012-04-27 21:59:52 +00:00
/ * *
* Sample content data index .
2012-05-14 22:05:09 +00:00
*
2012-04-27 21:59:52 +00:00
* This is part of what a ve . dm . DocumentFragment generates when given linear data .
2012-05-14 22:05:09 +00:00
*
2012-05-04 18:56:32 +00:00
* ( 21 ) branch nodes
2012-04-30 20:23:46 +00:00
* ( 01 ) document node
* ( 01 ) heading node
* ( 01 ) table node
* ( 01 ) tableRow node
* ( 01 ) tableCell node
2012-05-04 18:56:32 +00:00
* ( 06 ) paragraph nodes
2012-04-30 20:23:46 +00:00
* ( 03 ) list nodes
* ( 03 ) listItem nodes
* ( 01 ) preformatted node
2012-05-04 18:56:32 +00:00
* ( 01 ) definitionList node
* ( 02 ) definitionListItem nodes
* ( 10 ) leaf nodes
* ( 09 ) text nodes
2012-04-30 20:23:46 +00:00
* ( 01 ) image node
2012-04-27 21:59:52 +00:00
* /
2012-04-30 19:37:08 +00:00
ve . dm . example . tree = new ve . dm . DocumentNode ( [
2012-04-27 21:59:52 +00:00
// Heading with "abc"
2012-11-23 23:16:08 +00:00
new ve . dm . HeadingNode ( [ new ve . dm . TextNode ( 3 ) ] , ve . dm . example . data [ 0 ] ) ,
2012-04-27 21:59:52 +00:00
new ve . dm . TableNode ( [
2012-06-08 05:08:49 +00:00
new ve . dm . TableSectionNode ( [
new ve . dm . TableRowNode ( [
new ve . dm . TableCellNode ( [
// Paragraph with "d"
2012-11-23 23:16:08 +00:00
new ve . dm . ParagraphNode ( [ new ve . dm . TextNode ( 1 ) ] ,
ve . dm . example . data [ 9 ] ) ,
2012-06-08 05:08:49 +00:00
new ve . dm . ListNode ( [
// 1st level bullet list item with "e"
new ve . dm . ListItemNode ( [
2012-11-23 23:16:08 +00:00
new ve . dm . ParagraphNode (
[ new ve . dm . TextNode ( 1 ) ] ,
ve . dm . example . data [ 14 ]
) ,
2012-06-08 05:08:49 +00:00
new ve . dm . ListNode ( [
// 2nd level bullet list item with "f"
new ve . dm . ListItemNode ( [
2012-11-23 23:16:08 +00:00
new ve . dm . ParagraphNode (
[ new ve . dm . TextNode ( 1 ) ] ,
ve . dm . example . data [ 19 ]
)
] , ve . dm . example . data [ 18 ] )
] , ve . dm . example . data [ 17 ] )
] , ve . dm . example . data [ 13 ] )
] , ve . dm . example . data [ 12 ] ) ,
2012-06-08 05:08:49 +00:00
new ve . dm . ListNode ( [
// Numbered list item with "g"
new ve . dm . ListItemNode ( [
2012-11-23 23:16:08 +00:00
new ve . dm . ParagraphNode (
[ new ve . dm . TextNode ( 1 ) ] ,
ve . dm . example . data [ 28 ]
)
] , ve . dm . example . data [ 27 ] )
] , ve . dm . example . data [ 26 ] )
] , ve . dm . example . data [ 8 ] )
] , ve . dm . example . data [ 7 ] )
] , ve . dm . example . data [ 6 ] )
] , ve . dm . example . data [ 5 ] ) ,
2013-04-02 21:40:07 +00:00
// Preformatted with "h[example.png]i"
2012-04-27 21:59:52 +00:00
new ve . dm . PreformattedNode ( [
new ve . dm . TextNode ( 1 ) ,
2012-11-23 23:16:08 +00:00
new ve . dm . ImageNode ( [ ] , ve . dm . example . data [ 39 ] ) ,
2012-04-27 21:59:52 +00:00
new ve . dm . TextNode ( 1 )
2012-11-23 23:16:08 +00:00
] , ve . dm . example . data [ 37 ] ) ,
2012-05-04 18:56:32 +00:00
new ve . dm . DefinitionListNode ( [
// Definition list term item with "j"
new ve . dm . DefinitionListItemNode ( [
2012-11-23 23:16:08 +00:00
new ve . dm . ParagraphNode ( [ new ve . dm . TextNode ( 1 ) ] , ve . dm . example . data [ 45 ] )
] , ve . dm . example . data [ 44 ] ) ,
2012-05-04 18:56:32 +00:00
// Definition list definition item with "k"
new ve . dm . DefinitionListItemNode ( [
2012-11-23 23:16:08 +00:00
new ve . dm . ParagraphNode ( [ new ve . dm . TextNode ( 1 ) ] , ve . dm . example . data [ 50 ] )
] , ve . dm . example . data [ 49 ] )
] , ve . dm . example . data [ 43 ] ) ,
new ve . dm . ParagraphNode ( [ new ve . dm . TextNode ( 1 ) ] , ve . dm . example . data [ 55 ] ) ,
new ve . dm . ParagraphNode ( [ new ve . dm . TextNode ( 1 ) ] , ve . dm . example . data [ 58 ] )
2012-04-30 19:37:08 +00:00
] ) ;
2012-04-27 21:59:52 +00:00
2012-06-06 17:17:30 +00:00
ve . dm . example . conversions = {
'definitionListItem term' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'dt' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'definitionListItem' , 'attributes' : { 'style' : 'term' } }
} ,
'definitionListItem definition' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'dd' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'definitionListItem' , 'attributes' : { 'style' : 'definition' } }
} ,
'definitionList definition' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'dl' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'definitionList' }
} ,
'heading level 1' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'h1' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'heading' , 'attributes' : { 'level' : 1 } }
} ,
'heading level 2' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'h2' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'heading' , 'attributes' : { 'level' : 2 } }
} ,
'heading level 3' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'h3' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'heading' , 'attributes' : { 'level' : 3 } }
} ,
'heading level 4' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'h4' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'heading' , 'attributes' : { 'level' : 4 } }
} ,
'heading level 5' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'h5' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'heading' , 'attributes' : { 'level' : 5 } }
} ,
'heading level 6' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'h6' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'heading' , 'attributes' : { 'level' : 6 } }
} ,
'image' : {
2012-06-08 22:16:55 +00:00
'domElement' : ve . example . createDomElement ( 'img' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'image' }
} ,
'listItem' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'li' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'listItem' }
} ,
'list bullet' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'ul' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } }
} ,
'list number' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'ol' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'list' , 'attributes' : { 'style' : 'number' } }
} ,
'paragraph' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'p' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'paragraph' }
} ,
'preformatted' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'pre' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'preformatted' }
} ,
'tableCell' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'td' ) ,
2012-06-08 05:02:25 +00:00
'dataElement' : { 'type' : 'tableCell' , 'attributes' : { 'style' : 'data' } }
2012-06-06 17:17:30 +00:00
} ,
'table' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'table' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'table' }
} ,
'tableRow' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'tr' ) ,
2012-06-06 17:17:30 +00:00
'dataElement' : { 'type' : 'tableRow' }
} ,
2013-02-06 19:47:52 +00:00
'paragraph with data-mw attribute' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'p' , { 'data-mw' : '{"test":1234}' } ) ,
2013-02-06 19:47:52 +00:00
'dataElement' : { 'type' : 'paragraph' , 'attributes' : { 'html/0/data-mw' : '{"test":1234}' } }
2012-06-06 17:17:30 +00:00
} ,
2012-06-07 00:47:27 +00:00
'paragraph with style attribute' : {
2012-06-07 22:02:25 +00:00
'domElement' : ve . example . createDomElement ( 'p' , { 'style' : 'color:blue' } ) ,
2013-02-06 19:47:52 +00:00
'dataElement' : { 'type' : 'paragraph' , 'attributes' : { 'html/0/style' : 'color:blue' } }
2012-06-06 17:17:30 +00:00
}
} ;
2012-06-08 05:00:25 +00:00
2013-04-02 21:40:07 +00:00
ve . dm . example . MWImageHtml = '<a rel="mw:Image" href="./File:Wiki.png" data-parsoid="{"tsr":[158,216],"src":"[[Image:Wiki.png|500px|thumb|center|Example wiki file]]","optNames":{"width":"$1px"},"dsr":[158,216,null,null]}"><img height="" width="500" src="/index.php?title=Special:FilePath/Wiki.png&width=500" alt="Wiki.png"></a>' ;
2013-04-13 21:22:26 +00:00
ve . dm . example . MWBlockTemplateSpan = '<span about="#mwt1" typeof="mw:Object/Template" data-mw="{"id":"mwt1","target":{"wt":"Test"},"params":{"1":{"wt":"Hello, world!"}}}" data-parsoid="{"tsr":[18,40],"src":"{{Test|Hello, world!}}","dsr":[18,40,null,null]}"></span>' ;
ve . dm . example . MWBlockTemplateContent = '<p about="#mwt1" data-parsoid="{}">Hello, world!</p>' ;
ve . dm . example . MWInlineTemplateOpen = '<span about="#mwt1" typeof="mw:Object/Template" data-mw="{"id":"mwt1","target":{"wt":"Inline"},"params":{"1":{"wt":"1,234"}}}" data-parsoid="{"tsr":[18,34],"src":"{{Inline|1,234}}","dsr":[18,34,null,null]}">' ;
ve . dm . example . MWInlineTemplateContent = '$1,234.00' ;
ve . dm . example . MWInlineTemplateClose = '</span>' ;
2013-03-29 11:57:42 +00:00
2012-06-08 05:00:25 +00:00
ve . dm . example . domToDataCases = {
'paragraph with plain text' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p>abc</p></body>' ,
2012-08-10 23:49:14 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
'a' ,
'b' ,
'c' ,
{ 'type' : '/paragraph' }
]
} ,
'annotated text with bold, italic, underline formatting' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p><b>a</b><i>b</i><u>c</u></p></body>' ,
2012-08-10 23:49:14 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
2012-10-06 00:34:12 +00:00
[ 'a' , [ ve . dm . example . bold ] ] ,
[ 'b' , [ ve . dm . example . italic ] ] ,
[ 'c' , [ ve . dm . example . underline ] ] ,
2012-08-10 23:49:14 +00:00
{ 'type' : '/paragraph' }
]
} ,
'image' : {
2013-04-02 21:40:07 +00:00
'html' : '<body><img src="' + ve . dm . example . imgSrc + '"></body>' ,
2012-08-10 23:49:14 +00:00
'data' : [
2013-02-02 00:06:17 +00:00
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
2013-04-10 19:56:20 +00:00
{ 'type' : 'image' , 'attributes' : {
'html/0/src' : ve . dm . example . imgSrc ,
'width' : null ,
'height' : null ,
'src' : ve . dm . example . imgSrc
} } ,
2013-02-02 00:06:17 +00:00
{ 'type' : '/image' } ,
{ 'type' : '/paragraph' }
2012-08-10 23:49:14 +00:00
]
} ,
2013-03-29 11:57:42 +00:00
'mw:Image' : {
'html' : '<body><p>' + ve . dm . example . MWImageHtml + '</p></body>' ,
'data' : [
{ 'type' : 'paragraph' } ,
{
'type' : 'MWimage' ,
'attributes' : {
2013-04-10 19:56:20 +00:00
'html/0-0/alt' : 'Wiki.png' ,
'html/0-0/height' : '' ,
'html/0-0/src' : '/index.php?title=Special:FilePath/Wiki.png&width=500' ,
'html/0-0/width' : '500' ,
'html/0/data-parsoid' : '{"tsr":[158,216],"src":"[[Image:Wiki.png|500px|thumb|center|Example wiki file]]","optNames":{"width":"$1px"},"dsr":[158,216,null,null]}' ,
'html/0/href' : './File:Wiki.png' ,
'html/0/rel' : 'mw:Image' ,
2013-04-02 21:40:07 +00:00
'src' : '/index.php?title=Special:FilePath/Wiki.png&width=500' ,
2013-03-29 11:57:42 +00:00
'width' : 500 ,
'height' : null ,
2013-04-10 19:56:20 +00:00
'isLinked' : true
2013-03-29 11:57:42 +00:00
}
} ,
{ 'type' : '/MWimage' } ,
{ 'type' : '/paragraph' }
]
} ,
2013-04-13 21:22:26 +00:00
'mw:Template (block level)' : {
'html' : '<body>' + ve . dm . example . MWBlockTemplateSpan + ve . dm . example . MWBlockTemplateContent + '</body>' ,
2013-04-10 18:15:15 +00:00
'data' : [
{
2013-04-13 21:22:26 +00:00
'type' : 'MWtemplateBlock' ,
2013-04-10 18:15:15 +00:00
'mw' : {
'id' : 'mwt1' ,
'target' : { 'wt' : 'Test' } ,
'params' : {
'1' : { 'wt' : 'Hello, world!' }
}
} ,
'about' : '#mwt1' ,
'attributes' : {
'html/0/about' : '#mwt1' ,
'html/0/data-mw' : '{\"id\":\"mwt1\",\"target\":{\"wt\":\"Test\"},\"params\":{\"1\":{\"wt\":\"Hello, world!\"}}}' ,
'html/0/data-parsoid' : '{\"tsr\":[18,40],\"src\":\"{{Test|Hello, world!}}\",\"dsr\":[18,40,null,null]}' ,
'html/0/typeof' : 'mw:Object/Template' ,
'html/1/about' : '#mwt1' ,
'html/1/data-parsoid' : '{}'
} ,
} ,
2013-04-13 21:22:26 +00:00
{ 'type' : '/MWtemplateBlock' } ,
2013-04-10 18:15:15 +00:00
] ,
2013-04-13 21:22:26 +00:00
'normalizedHtml' : ve . dm . example . MWBlockTemplateSpan
} ,
'mw:Template (inline)' : {
'html' : '<body>' + ve . dm . example . MWInlineTemplateOpen + ve . dm . example . MWInlineTemplateContent + ve . dm . example . MWInlineTemplateClose + '</body>' ,
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
{
'type' : 'MWtemplateInline' ,
'mw' : {
'id' : 'mwt1' ,
'target' : { 'wt' : 'Inline' } ,
'params' : {
'1' : { 'wt' : '1,234' }
}
} ,
'about' : '#mwt1' ,
'attributes' : {
'html/0/about' : '#mwt1' ,
'html/0/data-mw' : '{\"id\":\"mwt1\",\"target\":{\"wt\":\"Inline\"},\"params\":{\"1\":{\"wt\":\"1,234\"}}}' ,
'html/0/data-parsoid' : '{\"tsr\":[18,34],\"src\":\"{{Inline|1,234}}\",\"dsr\":[18,34,null,null]}' ,
'html/0/typeof' : 'mw:Object/Template'
} ,
} ,
{ 'type' : '/MWtemplateInline' } ,
{ 'type' : '/paragraph' }
] ,
'normalizedHtml' : ve . dm . example . MWInlineTemplateOpen + ve . dm . example . MWInlineTemplateClose
2013-04-10 18:15:15 +00:00
} ,
2012-08-10 23:49:14 +00:00
'paragraph with alienInline inside' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p>a<tt class="foo">b</tt>c</p></body>' ,
2012-08-10 23:49:14 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
'a' ,
{
'type' : 'alienInline' ,
2012-08-21 00:44:55 +00:00
'attributes' : { 'html' : '<tt class="foo">b</tt>' }
2012-08-10 23:49:14 +00:00
} ,
{ 'type' : '/alienInline' } ,
'c' ,
{ 'type' : '/paragraph' }
]
} ,
'paragraphs with an alienBlock between them' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p>abc</p><figure>abc</figure><p>def</p></body>' ,
2012-08-10 23:49:14 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
'a' ,
'b' ,
'c' ,
{ 'type' : '/paragraph' } ,
2012-08-21 00:44:55 +00:00
{ 'type' : 'alienBlock' , 'attributes' : { 'html' : '<figure>abc</figure>' } } ,
2012-08-10 23:49:14 +00:00
{ 'type' : '/alienBlock' } ,
{ 'type' : 'paragraph' } ,
'd' ,
'e' ,
'f' ,
{ 'type' : '/paragraph' }
]
} ,
2012-11-24 02:44:54 +00:00
'annotated inline nodes' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p>a<b><tt class="foo">b</tt><i><span typeof="mw:Entity">c</span></i></b>' +
'<i><br/>d</i>e</p></body>' ,
2012-11-24 02:44:54 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
'a' ,
{
'type' : 'alienInline' ,
'attributes' : { 'html' : '<tt class="foo">b</tt>' } ,
'annotations' : [ ve . dm . example . bold ]
} ,
{ 'type' : '/alienInline' } ,
{
'type' : 'MWentity' ,
2013-02-06 19:47:52 +00:00
'attributes' : { 'character' : 'c' , 'html/0/typeof' : 'mw:Entity' } ,
2012-11-24 02:44:54 +00:00
'annotations' : [ ve . dm . example . bold , ve . dm . example . italic ]
} ,
{ 'type' : '/MWentity' } ,
{
'type' : 'break' ,
'annotations' : [ ve . dm . example . italic ]
} ,
{ 'type' : '/break' } ,
[ 'd' , [ ve . dm . example . italic ] ] ,
'e' ,
{ 'type' : '/paragraph' }
]
} ,
2012-10-16 06:05:29 +00:00
'wrapping of bare content' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>abc</body>' ,
2012-10-16 06:05:29 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'a' ,
'b' ,
'c' ,
{ 'type' : '/paragraph' }
]
} ,
'wrapping of bare content with inline node' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>1<br/>2</body>' ,
2012-10-16 06:05:29 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'1' ,
{ 'type' : 'break' } ,
{ 'type' : '/break' } ,
'2' ,
{ 'type' : '/paragraph' }
]
} ,
2013-02-02 00:06:17 +00:00
'wrapping of bare content starting with inline node' : {
2013-04-02 21:40:07 +00:00
'html' : '<body><img src="' + ve . dm . example . imgSrc + '">12</body>' ,
2013-02-02 00:06:17 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
2013-04-10 19:56:20 +00:00
{ 'type' : 'image' , 'attributes' : {
'html/0/src' : ve . dm . example . imgSrc ,
'src' : ve . dm . example . imgSrc ,
'width' : null ,
'height' : null
} } ,
2013-02-02 00:06:17 +00:00
{ 'type' : '/image' } ,
'1' ,
'2' ,
{ 'type' : '/paragraph' }
]
} ,
2012-10-16 06:05:29 +00:00
'wrapping of bare content with inline alien' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>1<tt class="bar">baz</tt>2</body>' ,
2012-10-16 06:05:29 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'1' ,
{
'type' : 'alienInline' ,
'attributes' : { 'html' : '<tt class="bar">baz</tt>' }
} ,
{ 'type' : '/alienInline' } ,
'2' ,
{ 'type' : '/paragraph' }
]
} ,
'wrapping of bare content with block alien' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>1<figure class="bar">baz</figure>2</body>' ,
2012-10-16 06:05:29 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'1' ,
{ 'type' : '/paragraph' } ,
{
'type' : 'alienBlock' ,
'attributes' : { 'html' : '<figure class="bar">baz</figure>' }
} ,
{ 'type' : '/alienBlock' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'2' ,
{ 'type' : '/paragraph' }
]
} ,
2012-11-20 04:26:54 +00:00
'wrapping of bare content with mw:unrecognized inline alien' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>1<span typeof="mw:Placeholder">baz</span>2</body>' ,
2012-11-20 04:26:54 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'1' ,
{
'type' : 'alienInline' ,
'attributes' : { 'html' : '<span typeof="mw:Placeholder">baz</span>' }
} ,
{ 'type' : '/alienInline' } ,
'2' ,
{ 'type' : '/paragraph' }
]
} ,
'wrapping of bare content with mw:unrecognized block alien' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>1<div typeof="mw:Placeholder">baz</div>2</body>' ,
2012-11-20 04:26:54 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'1' ,
{ 'type' : '/paragraph' } ,
{
'type' : 'alienBlock' ,
'attributes' : { 'html' : '<div typeof="mw:Placeholder">baz</div>' }
} ,
{ 'type' : '/alienBlock' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'2' ,
{ 'type' : '/paragraph' }
]
} ,
(bug 43056) Inline tags like <span> are block-alienated sometimes
This happens when the <span> is the start of unwrapped content. The
converter logic to look at the tag name in wrapping mode doesn't kick in
because we're not yet in wrapping mode at that point.
The core issue was that previously, we relied on the document
structure/state to choose between alienBlock and alienInline, and only
used the tag name where the document structure was ambiguous (wrapping).
Changed this to be the other way around: we now rely primarily on the
tag name, and if that doesn't match what we expect based on the document
structure, we work around that if possible. Specifically:
* inline tag in our wrapper --> inline alien
* block tag in our wrapper --> close wrapper, block alien
* inline tag in wrapper that's not ours --> inline alien
* block tag in wrapper that's not ours --> *inline* alien
* inline tag in structural location --> open wrapper, inline alien
* block tag in structural location --> block alien
* inline tag in content location --> inline alien
* block tag in content location --> *inline* alien
only in the fourth and the last case do we need to use the "wrong" alien type to
preserve document validity, and it will always be inline where block was
expected, which should reduce UI issues.
The condensed version of the above, which is used in the code, is:
* If in a non-wrapper content location, use inline
* If in a wrapper that's not ours, use inline
* Otherwise, decide based on tag name
* Open or close wrapper if needed
ve.dm.Converter:
* Replace isInline logic in createAlien() with the above
* Factor out code to start wrapping (was duplicated) into startWrapping()
* Call startWrapping() if createAlien() returns an alienInline and we're
in a structural location
Tests:
* Add test cases with aliens at the start and end of unwrapped content
** The first one failed prior to these changes and now passes, the
second one was already passing
* Fix about group test case, was exhibiting the bug that this commit fixes
Change-Id: I657aa0ff5bc2b57cd48ef8a99c8ca930936c03b8
2012-12-20 00:59:58 +00:00
'wrapping of bare content starting with mw:unrecognized inline alien' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><span typeof="mw:Placeholder">Foo</span>Bar</body>' ,
(bug 43056) Inline tags like <span> are block-alienated sometimes
This happens when the <span> is the start of unwrapped content. The
converter logic to look at the tag name in wrapping mode doesn't kick in
because we're not yet in wrapping mode at that point.
The core issue was that previously, we relied on the document
structure/state to choose between alienBlock and alienInline, and only
used the tag name where the document structure was ambiguous (wrapping).
Changed this to be the other way around: we now rely primarily on the
tag name, and if that doesn't match what we expect based on the document
structure, we work around that if possible. Specifically:
* inline tag in our wrapper --> inline alien
* block tag in our wrapper --> close wrapper, block alien
* inline tag in wrapper that's not ours --> inline alien
* block tag in wrapper that's not ours --> *inline* alien
* inline tag in structural location --> open wrapper, inline alien
* block tag in structural location --> block alien
* inline tag in content location --> inline alien
* block tag in content location --> *inline* alien
only in the fourth and the last case do we need to use the "wrong" alien type to
preserve document validity, and it will always be inline where block was
expected, which should reduce UI issues.
The condensed version of the above, which is used in the code, is:
* If in a non-wrapper content location, use inline
* If in a wrapper that's not ours, use inline
* Otherwise, decide based on tag name
* Open or close wrapper if needed
ve.dm.Converter:
* Replace isInline logic in createAlien() with the above
* Factor out code to start wrapping (was duplicated) into startWrapping()
* Call startWrapping() if createAlien() returns an alienInline and we're
in a structural location
Tests:
* Add test cases with aliens at the start and end of unwrapped content
** The first one failed prior to these changes and now passes, the
second one was already passing
* Fix about group test case, was exhibiting the bug that this commit fixes
Change-Id: I657aa0ff5bc2b57cd48ef8a99c8ca930936c03b8
2012-12-20 00:59:58 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
{
'type' : 'alienInline' ,
'attributes' : { 'html' : '<span typeof="mw:Placeholder">Foo</span>' }
} ,
{ 'type' : '/alienInline' } ,
'B' ,
'a' ,
'r' ,
{ 'type' : '/paragraph' }
]
} ,
'wrapping of bare content ending with mw:unrecognized inline alien' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>Foo<span typeof="mw:Placeholder">Bar</span></body>' ,
(bug 43056) Inline tags like <span> are block-alienated sometimes
This happens when the <span> is the start of unwrapped content. The
converter logic to look at the tag name in wrapping mode doesn't kick in
because we're not yet in wrapping mode at that point.
The core issue was that previously, we relied on the document
structure/state to choose between alienBlock and alienInline, and only
used the tag name where the document structure was ambiguous (wrapping).
Changed this to be the other way around: we now rely primarily on the
tag name, and if that doesn't match what we expect based on the document
structure, we work around that if possible. Specifically:
* inline tag in our wrapper --> inline alien
* block tag in our wrapper --> close wrapper, block alien
* inline tag in wrapper that's not ours --> inline alien
* block tag in wrapper that's not ours --> *inline* alien
* inline tag in structural location --> open wrapper, inline alien
* block tag in structural location --> block alien
* inline tag in content location --> inline alien
* block tag in content location --> *inline* alien
only in the fourth and the last case do we need to use the "wrong" alien type to
preserve document validity, and it will always be inline where block was
expected, which should reduce UI issues.
The condensed version of the above, which is used in the code, is:
* If in a non-wrapper content location, use inline
* If in a wrapper that's not ours, use inline
* Otherwise, decide based on tag name
* Open or close wrapper if needed
ve.dm.Converter:
* Replace isInline logic in createAlien() with the above
* Factor out code to start wrapping (was duplicated) into startWrapping()
* Call startWrapping() if createAlien() returns an alienInline and we're
in a structural location
Tests:
* Add test cases with aliens at the start and end of unwrapped content
** The first one failed prior to these changes and now passes, the
second one was already passing
* Fix about group test case, was exhibiting the bug that this commit fixes
Change-Id: I657aa0ff5bc2b57cd48ef8a99c8ca930936c03b8
2012-12-20 00:59:58 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'F' ,
'o' ,
'o' ,
{
'type' : 'alienInline' ,
'attributes' : { 'html' : '<span typeof="mw:Placeholder">Bar</span>' }
} ,
{ 'type' : '/alienInline' } ,
{ 'type' : '/paragraph' }
]
} ,
2012-11-20 04:26:54 +00:00
'wrapping of bare content with about group' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>1<tt about="#mwt1">foo</tt><tt about="#mwt1">bar</tt>2</body>' ,
2012-11-20 04:26:54 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'1' ,
{
2013-02-16 02:37:50 +00:00
'type' : 'alienInline' ,
2012-11-20 04:26:54 +00:00
'attributes' : { 'html' : '<tt about="#mwt1">foo</tt><tt about="#mwt1">bar</tt>' }
} ,
2013-02-16 02:37:50 +00:00
{ 'type' : '/alienInline' } ,
2012-11-20 04:26:54 +00:00
'2' ,
{ 'type' : '/paragraph' }
]
} ,
2012-10-16 06:05:29 +00:00
'wrapping of bare content between structural nodes' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><table></table>abc<table></table></body>' ,
2012-10-16 06:05:29 +00:00
'data' : [
{ 'type' : 'table' } ,
{ 'type' : '/table' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'a' ,
'b' ,
'c' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'table' } ,
{ 'type' : '/table' }
]
} ,
'wrapping of bare content between paragraphs' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p>abc</p>def<p></p></body>' ,
2012-10-16 06:05:29 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
'a' ,
'b' ,
'c' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'd' ,
'e' ,
'f' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'paragraph' } ,
{ 'type' : '/paragraph' }
]
} ,
2012-11-17 03:37:38 +00:00
'wrapping prevents empty list items' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><ul><li></li></ul></body>' ,
2012-11-17 03:37:38 +00:00
'data' : [
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'empty' } } ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' }
]
} ,
'empty document' : {
'html' : '' ,
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'empty' } } ,
{ 'type' : '/paragraph' }
]
} ,
'empty document with content added by the editor' : {
'html' : null ,
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'empty' } } ,
'F' ,
'o' ,
'o' ,
{ 'type' : '/paragraph' }
] ,
2013-02-11 19:46:58 +00:00
'normalizedHtml' : '<body><p>Foo</p></body>'
2012-11-17 03:37:38 +00:00
} ,
'empty list item with content added by the editor' : {
'html' : null ,
'data' : [
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'empty' } } ,
'F' ,
'o' ,
'o' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' }
] ,
2013-02-11 19:46:58 +00:00
'normalizedHtml' : '<body><ul><li><p>Foo</p></li></ul></body>'
2012-11-17 03:37:38 +00:00
} ,
2012-08-10 23:49:14 +00:00
'example document' : {
'html' : ve . dm . example . html ,
'data' : ve . dm . example . data
} ,
'list item with space followed by link' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><ul><li><p> <a rel="mw:WikiLink" href="Foo_bar" data-rt="{"sHref":"foo bar"}">bar</a></p></li></ul></body>' ,
2012-08-10 23:49:14 +00:00
'data' : [
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
{ 'type' : 'listItem' } ,
2012-08-16 17:53:33 +00:00
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ undefined , ' ' ] } } ,
2012-08-10 23:49:14 +00:00
[
2012-06-08 05:00:25 +00:00
'b' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-08-24 02:06:36 +00:00
'title' : 'Foo bar' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo_bar' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'hrefPrefix' : '' ,
'html/0/data-rt' : '{"sHref":"foo bar"}' ,
'html/0/href' : 'Foo_bar' ,
'html/0/rel' : 'mw:WikiLink'
2012-06-08 22:16:55 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-10 23:49:14 +00:00
] ,
[
'a' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-08-24 02:06:36 +00:00
'title' : 'Foo bar' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo_bar' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'hrefPrefix' : '' ,
'html/0/data-rt' : '{"sHref":"foo bar"}' ,
'html/0/href' : 'Foo_bar' ,
'html/0/rel' : 'mw:WikiLink'
2012-06-08 22:16:55 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-10 23:49:14 +00:00
] ,
[
'r' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-08-24 02:06:36 +00:00
'title' : 'Foo bar' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo_bar' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'hrefPrefix' : '' ,
'html/0/data-rt' : '{"sHref":"foo bar"}' ,
'html/0/href' : 'Foo_bar' ,
'html/0/rel' : 'mw:WikiLink'
2012-06-08 22:16:55 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-10 23:49:14 +00:00
] ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' }
]
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
} ,
2012-08-23 21:29:43 +00:00
'internal link with ./ and ../' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p><a rel="mw:WikiLink" href="./../../../Foo/Bar">Foo</a></p></body>' ,
2012-08-14 00:59:16 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
[
'F' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-08-24 02:06:36 +00:00
'title' : 'Foo/Bar' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo/Bar' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'hrefPrefix' : './../../../' ,
'html/0/href' : './../../../Foo/Bar' ,
'html/0/rel' : 'mw:WikiLink'
2012-08-14 00:59:16 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-14 00:59:16 +00:00
] ,
[
'o' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-08-24 02:06:36 +00:00
'title' : 'Foo/Bar' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo/Bar' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'hrefPrefix' : './../../../' ,
'html/0/href' : './../../../Foo/Bar' ,
'html/0/rel' : 'mw:WikiLink'
2012-08-14 00:59:16 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-14 00:59:16 +00:00
] ,
[
'o' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-08-24 02:06:36 +00:00
'title' : 'Foo/Bar' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo/Bar' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'hrefPrefix' : './../../../' ,
'html/0/href' : './../../../Foo/Bar' ,
'html/0/rel' : 'mw:WikiLink'
2012-08-14 00:59:16 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-14 00:59:16 +00:00
] ,
{ 'type' : '/paragraph' }
]
} ,
2012-08-14 00:50:43 +00:00
'numbered external link' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p><a rel="mw:ExtLink/Numbered" href="http://www.mediawiki.org/">[1]</a></p></body>' ,
2012-08-14 00:50:43 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
[
'[' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWexternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-10-06 00:34:12 +00:00
'href' : 'http://www.mediawiki.org/' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'rel' : 'mw:ExtLink/Numbered' ,
'html/0/href' : 'http://www.mediawiki.org/' ,
'html/0/rel' : 'mw:ExtLink/Numbered'
2012-08-14 00:50:43 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-14 00:50:43 +00:00
] ,
[
'1' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWexternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-10-06 00:34:12 +00:00
'href' : 'http://www.mediawiki.org/' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'rel' : 'mw:ExtLink/Numbered' ,
'html/0/href' : 'http://www.mediawiki.org/' ,
'html/0/rel' : 'mw:ExtLink/Numbered'
2012-08-14 00:50:43 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-14 00:50:43 +00:00
] ,
[
']' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWexternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-10-06 00:34:12 +00:00
'href' : 'http://www.mediawiki.org/' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'rel' : 'mw:ExtLink/Numbered' ,
'html/0/href' : 'http://www.mediawiki.org/' ,
'html/0/rel' : 'mw:ExtLink/Numbered'
2012-08-14 00:50:43 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-14 00:50:43 +00:00
] ,
{ 'type' : '/paragraph' }
]
} ,
'URL link' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p><a rel="mw:ExtLink/URL" href="http://www.mediawiki.org/">mw</a></p></body>' ,
2012-08-14 00:50:43 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
[
'm' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWexternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-10-06 00:34:12 +00:00
'href' : 'http://www.mediawiki.org/' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'rel' : 'mw:ExtLink/URL' ,
'html/0/href' : 'http://www.mediawiki.org/' ,
'html/0/rel' : 'mw:ExtLink/URL'
2012-08-14 00:50:43 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-14 00:50:43 +00:00
] ,
[
'w' ,
2012-08-24 02:06:36 +00:00
[ {
2012-10-06 00:34:12 +00:00
'type' : 'link/MWexternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-10-06 00:34:12 +00:00
'href' : 'http://www.mediawiki.org/' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'rel' : 'mw:ExtLink/URL' ,
'html/0/href' : 'http://www.mediawiki.org/' ,
'html/0/rel' : 'mw:ExtLink/URL'
2012-08-14 00:50:43 +00:00
}
2012-08-24 02:06:36 +00:00
} ]
2012-08-14 00:50:43 +00:00
] ,
{ 'type' : '/paragraph' }
]
} ,
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
'whitespace preservation in headings' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><h2>Foo</h2><h2> Bar</h2><h2>Baz </h2><h2> Quux </h2></body>' ,
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
'data' : [
{ 'type' : 'heading' , 'attributes' : { 'level' : 2 } } ,
'F' ,
'o' ,
'o' ,
{ 'type' : '/heading' } ,
{
'type' : 'heading' ,
'attributes' : { 'level' : 2 } ,
2012-08-16 17:53:33 +00:00
'internal' : { 'whitespace' : [ undefined , ' ' ] }
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
} ,
'B' ,
'a' ,
'r' ,
{ 'type' : '/heading' } ,
{
'type' : 'heading' ,
'attributes' : { 'level' : 2 } ,
2012-08-16 17:53:33 +00:00
'internal' : { 'whitespace' : [ undefined , undefined , ' ' ] }
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
} ,
'B' ,
'a' ,
'z' ,
{ 'type' : '/heading' } ,
{
'type' : 'heading' ,
'attributes' : { 'level' : 2 } ,
2012-08-16 17:53:33 +00:00
'internal' : { 'whitespace' : [ undefined , ' ' , ' ' ] }
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
} ,
'Q' ,
'u' ,
'u' ,
'x' ,
{ 'type' : '/heading' }
]
} ,
'whitespace preservation in list items' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><ul><li>Foo</li><li> Bar</li><li>Baz </li><li> Quux </li></ul></body>' ,
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
'data' : [
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
{ 'type' : 'listItem' } ,
2012-08-16 20:06:18 +00:00
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
'F' ,
'o' ,
'o' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
{ 'type' : 'listItem' , 'internal' : { 'whitespace' : [ undefined , ' ' ] } } ,
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ ' ' ] , 'generated' : 'wrapper' } } ,
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
'B' ,
'a' ,
'r' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
{ 'type' : 'listItem' , 'internal' : { 'whitespace' : [ undefined , undefined , ' ' ] } } ,
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ undefined , undefined , undefined , ' ' ] , 'generated' : 'wrapper' } } ,
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
'B' ,
'a' ,
'z' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
{ 'type' : 'listItem' , 'internal' : { 'whitespace' : [ undefined , ' ' , ' ' ] } } ,
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
{
'type' : 'paragraph' ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'internal' : { 'whitespace' : [ ' ' , undefined , undefined , ' ' ] , 'generated' : 'wrapper' }
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
} ,
'Q' ,
'u' ,
'u' ,
'x' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' }
]
} ,
'whitespace preservation with annotations' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p> <i> Foo </i> </p></body>' ,
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
'data' : [
{
'type' : 'paragraph' ,
2012-08-16 17:53:33 +00:00
'internal' : { 'whitespace' : [ undefined , ' ' , ' ' ] }
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
} ,
2012-10-06 00:34:12 +00:00
[ ' ' , [ ve . dm . example . italic ] ] ,
[ ' ' , [ ve . dm . example . italic ] ] ,
[ 'F' , [ ve . dm . example . italic ] ] ,
[ 'o' , [ ve . dm . example . italic ] ] ,
[ 'o' , [ ve . dm . example . italic ] ] ,
[ ' ' , [ ve . dm . example . italic ] ] ,
[ ' ' , [ ve . dm . example . italic ] ] ,
[ ' ' , [ ve . dm . example . italic ] ] ,
Strip and preserve inner leading&trailing whitespace in the linear model
This makes things like
== Foo ==
* Bar
render without the leading and trailing spaces, while still
round-tripping those spaces.
* Added a .fringeWhitespace property to the linear model and ve.dm.Node
** Object containing innerPre, innerPost, outerPre, outerPost
** Only inner* are used right now, outer* are planned for future use
** Like .attributes , it's suppressed if it's an empty object
* In getDataFromDom():
** Store the stripped whitespace in .fringeWhitespace
** Move emptiness check up: empty elements with .fringeWhitespace have
to be preserved
** Move paragraph wrapping up: .fringeWhitespace has to be applied to
the generated paragraph, not its parent
** Add wrapperElement to keep track of the element .fringeWhitespace has
to be added to; this is either dataElement or the generated paragraph
or nothing, but we can't modify dataElement because it's used later
* In getDomFromData():
** When processing an opening, store the fringeWhitespace data in the
generated DOM node
** When processing a closing, add the stored whitespace back in
* In the ve.dm.Document constructor, pass through .fringeWhitespace from
the linear model data to the generated nodes
Tests:
* Change one existing test case to account for this change
* Add three new test cases for this behavior
* Add normalizedHtml field so I can test behavior with bare content
Change-Id: I0411544652dd72b923c831c495d69ee4322a2c14
2012-08-10 21:09:04 +00:00
{ 'type' : '/paragraph' }
]
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
} ,
'outer whitespace preservation in a list with bare text and a wrapper paragraph' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>\n<ul>\n\n<li>\n\n\nBa re\n\n\n\n</li>\n\n\n\n\n<li>\t<p>\t\tP\t\t\t</p>\t\t\t\t</li>\t\n</ul>\t\n\t\n</body>' ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'data' : [
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } , 'internal' : { 'whitespace' : [ '\n' , '\n\n' , '\t\n' , '\t\n\t\n' ] } } ,
{ 'type' : 'listItem' , 'internal' : { 'whitespace' : [ '\n\n' , '\n\n\n' , '\n\n\n\n' , '\n\n\n\n\n' ] } } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' , 'whitespace' : [ '\n\n\n' , undefined , undefined , '\n\n\n\n' ] } } ,
'B' ,
'a' ,
' ' ,
'r' ,
'e' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' , 'internal' : { 'whitespace' : [ '\n\n\n\n\n' , '\t' , '\t\t\t\t' , '\t\n' ] } } ,
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ '\t' , '\t\t' , '\t\t\t' , '\t\t\t\t' ] } } ,
'P' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' }
]
} ,
'outer whitespace preservation in a list with bare text and a sublist' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><ul>\n<li>\n\nBa re\n\n\n<ul>\n\n\n\n<li> <p> P </p> </li>\t</ul>\t\t</li>\t\t\t</ul></body>' ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'data' : [
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } , 'internal' : { 'whitespace' : [ undefined , '\n' , '\t\t\t' ] } } ,
{ 'type' : 'listItem' , 'internal' : { 'whitespace' : [ '\n' , '\n\n' , '\t\t' , '\t\t\t' ] } } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' , 'whitespace' : [ '\n\n' , undefined , undefined , '\n\n\n' ] } } ,
'B' ,
'a' ,
' ' ,
'r' ,
'e' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } , 'internal' : { 'whitespace' : [ '\n\n\n' , '\n\n\n\n' , '\t' , '\t\t' ] } } ,
{ 'type' : 'listItem' , 'internal' : { 'whitespace' : [ '\n\n\n\n' , ' ' , ' ' , '\t' ] } } ,
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ ' ' , ' ' , ' ' , ' ' ] } } ,
'P' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' }
]
} ,
'whitespace preservation leaves non-edge content whitespace alone' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p> A B <b> C\t</b>\t\tD\t\t\t</p>\nE\n\nF\n\n\n<b>\n\n\n\nG </b> H </body>' ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ undefined , ' ' , '\t\t\t' , '\n' ] } } ,
'A' ,
' ' ,
' ' ,
'B' ,
' ' ,
' ' ,
' ' ,
2012-10-06 00:34:12 +00:00
[ ' ' , [ ve . dm . example . bold ] ] ,
[ ' ' , [ ve . dm . example . bold ] ] ,
[ ' ' , [ ve . dm . example . bold ] ] ,
[ ' ' , [ ve . dm . example . bold ] ] ,
[ 'C' , [ ve . dm . example . bold ] ] ,
[ '\t' , [ ve . dm . example . bold ] ] ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'\t' ,
'\t' ,
'D' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' , 'whitespace' : [ '\n' , undefined , undefined , ' ' ] } } ,
'E' ,
'\n' ,
'\n' ,
'F' ,
'\n' ,
'\n' ,
'\n' ,
2012-10-06 00:34:12 +00:00
[ '\n' , [ ve . dm . example . bold ] ] ,
[ '\n' , [ ve . dm . example . bold ] ] ,
[ '\n' , [ ve . dm . example . bold ] ] ,
[ '\n' , [ ve . dm . example . bold ] ] ,
[ 'G' , [ ve . dm . example . bold ] ] ,
[ ' ' , [ ve . dm . example . bold ] ] ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
' ' ,
' ' ,
'H' ,
{ 'type' : '/paragraph' }
]
} ,
'whitespace preservation with non-edge content whitespace with nested annotations' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p> A B <b> C\t<i>\t\tD\t\t\t</i>\t\t\t\tE\n</b>\n\nF\n\n\n</p></body>' ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ undefined , ' ' , '\n\n\n' ] } } ,
'A' ,
' ' ,
' ' ,
'B' ,
' ' ,
' ' ,
' ' ,
2012-10-06 00:34:12 +00:00
[ ' ' , [ ve . dm . example . bold ] ] ,
[ ' ' , [ ve . dm . example . bold ] ] ,
[ ' ' , [ ve . dm . example . bold ] ] ,
[ ' ' , [ ve . dm . example . bold ] ] ,
[ 'C' , [ ve . dm . example . bold ] ] ,
[ '\t' , [ ve . dm . example . bold ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ 'D' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold ] ] ,
[ '\t' , [ ve . dm . example . bold ] ] ,
[ '\t' , [ ve . dm . example . bold ] ] ,
[ '\t' , [ ve . dm . example . bold ] ] ,
[ 'E' , [ ve . dm . example . bold ] ] ,
[ '\n' , [ ve . dm . example . bold ] ] ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'\n' ,
'\n' ,
'F' ,
{ 'type' : '/paragraph' }
]
} ,
'whitespace preservation with tightly nested annotations' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p> A B <b><i>\t\tC\t\t\t</i></b>\n\nD\n\n\n</p></body>' ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ undefined , ' ' , '\n\n\n' ] } } ,
'A' ,
' ' ,
' ' ,
'B' ,
' ' ,
' ' ,
' ' ,
2012-10-06 00:34:12 +00:00
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ 'C' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'\n' ,
'\n' ,
'D' ,
{ 'type' : '/paragraph' }
]
} ,
'whitespace preservation with nested annotations with whitespace on the left side' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p> A B <b>\n\t<i>\t\tC\t\t\t</i></b>\n\nD\n\n\n</p></body>' ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ undefined , ' ' , '\n\n\n' ] } } ,
'A' ,
' ' ,
' ' ,
'B' ,
' ' ,
' ' ,
' ' ,
2012-10-06 00:34:12 +00:00
[ '\n' , [ ve . dm . example . bold ] ] ,
[ '\t' , [ ve . dm . example . bold ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ 'C' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'\n' ,
'\n' ,
'D' ,
{ 'type' : '/paragraph' }
]
} ,
'whitespace preservation with nested annotations with whitespace on the right side' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p> A B <b><i>\t\tC\t\t\t</i>\n\t</b>\n\nD\n\n\n</p></body>' ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ undefined , ' ' , '\n\n\n' ] } } ,
'A' ,
' ' ,
' ' ,
'B' ,
' ' ,
' ' ,
' ' ,
2012-10-06 00:34:12 +00:00
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ 'C' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\t' , [ ve . dm . example . bold , ve . dm . example . italic ] ] ,
[ '\n' , [ ve . dm . example . bold ] ] ,
[ '\t' , [ ve . dm . example . bold ] ] ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'\n' ,
'\n' ,
'D' ,
{ 'type' : '/paragraph' }
]
} ,
2012-09-07 21:58:27 +00:00
'whitespace preservation with aliens' : {
2013-02-11 19:46:58 +00:00
'html' : '<body> <p typeof="mw:Placeholder"> <br> </p> <p>\tFoo\t\t<tt>\t\t\tBar\t\t\t\t</tt>\nBaz\n\n<span typeof="mw:Placeholder">\n\n\nQuux\n\n\n\n</span> \tWhee \n</p>\t\n<figure>\n\tYay \t </figure> \n </body>' ,
2012-09-07 21:58:27 +00:00
'data' : [
{
'type' : 'alienBlock' ,
'attributes' : {
'html' : '<p typeof="mw:Placeholder"> <br> </p>'
} ,
'internal' : {
'whitespace' : [ ' ' , undefined , undefined , ' ' ]
}
} ,
{ 'type' : '/alienBlock' } ,
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ ' ' , '\t' , ' \n' , '\t\n' ] } } ,
'F' ,
'o' ,
'o' ,
'\t' ,
'\t' ,
{ 'type' : 'alienInline' , 'attributes' : { 'html' : '<tt>\t\t\tBar\t\t\t\t</tt>' } } ,
{ 'type' : '/alienInline' } ,
'\n' ,
'B' ,
'a' ,
'z' ,
'\n' ,
'\n' ,
{
'type' : 'alienInline' ,
'attributes' : {
'html' : '<span typeof="mw:Placeholder">\n\n\nQuux\n\n\n\n</span>'
}
} ,
{ 'type' : '/alienInline' } ,
' ' ,
'\t' ,
'W' ,
'h' ,
'e' ,
'e' ,
{ 'type' : '/paragraph' } ,
{
'type' : 'alienBlock' ,
'attributes' : {
'html' : '<figure>\n\tYay \t </figure>'
} ,
'internal' : {
'whitespace' : [ '\t\n' , undefined , undefined , ' \n ' ]
}
} ,
{ 'type' : '/alienBlock' }
]
} ,
2012-11-07 20:03:58 +00:00
'whitespace preservation not triggered inside <pre>' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>\n<pre>\n\n\nFoo\n\n\nBar\n\n\n\n</pre>\n\n\n\n\n</body>' ,
2012-11-07 20:03:58 +00:00
'data' : [
{ 'type' : 'preformatted' , 'internal' : { 'whitespace' : [ '\n' , undefined , undefined , '\n\n\n\n\n' ] } } ,
'\n' ,
'\n' ,
'F' ,
'o' ,
'o' ,
'\n' ,
'\n' ,
'\n' ,
'B' ,
'a' ,
'r' ,
'\n' ,
'\n' ,
'\n' ,
'\n' ,
{ 'type' : '/preformatted' }
2012-12-04 00:43:47 +00:00
] ,
// pre newline hack
// TODO we should test this using a better, more .innerHTML-based mechanism for
// comparing DOM trees
2013-02-11 19:46:58 +00:00
'normalizedHtml' : '<body>\n<pre>\n\n\n\nFoo\n\n\nBar\n\n\n\n</pre>\n\n\n\n\n</body>'
2012-11-07 20:03:58 +00:00
} ,
2013-04-18 00:08:47 +00:00
'whitespace preservation in table cell starting with text and ending with annotation' : {
'html' : '<body><table><tbody><tr><td>Foo <b>Bar</b></td></tr></tbody></table></body>' ,
'data' : [
{ 'type' : 'table' } ,
{ 'type' : 'tableSection' , 'attributes' : { 'style' : 'body' } } ,
{ 'type' : 'tableRow' } ,
{ 'type' : 'tableCell' , 'attributes' : { 'style' : 'data' } } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'F' ,
'o' ,
'o' ,
' ' ,
[ 'B' , [ ve . dm . example . bold ] ] ,
[ 'a' , [ ve . dm . example . bold ] ] ,
[ 'r' , [ ve . dm . example . bold ] ] ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/tableCell' } ,
{ 'type' : '/tableRow' } ,
{ 'type' : '/tableSection' } ,
{ 'type' : '/table' }
]
} ,
2013-04-18 23:06:58 +00:00
'whitespace preservation with wrapped text, comments and language links' : {
'html' : '<body><!-- Foo --> <!-- Bar -->\nFoo\n' +
'<link rel="mw:WikiLink/Language" href="http://de.wikipedia.org/wiki/Foo">\n' +
'<link rel="mw:WikiLink/Language" href="http://fr.wikipedia.org/wiki/Foo"></body>' ,
'data' : [
{
'type' : 'alienMeta' ,
'internal' : { 'whitespace' : [ undefined , undefined , undefined , ' ' ] } ,
'attributes' : {
'style' : 'comment' ,
'text' : ' Foo '
}
} ,
{ 'type' : '/alienMeta' } ,
{
'type' : 'alienMeta' ,
'internal' : { 'whitespace' : [ ' ' , undefined , undefined , '\n' ] } ,
'attributes' : {
'style' : 'comment' ,
'text' : ' Bar '
}
} ,
{ 'type' : '/alienMeta' } ,
{
'type' : 'paragraph' ,
'internal' : {
'generated' : 'wrapper' ,
'whitespace' : [ '\n' , undefined , undefined , '\n' ]
}
} ,
'F' ,
'o' ,
'o' ,
{ 'type' : '/paragraph' } ,
{
'type' : 'MWlanguage' ,
'attributes' : {
'href' : 'http://de.wikipedia.org/wiki/Foo' ,
'html/0/href' : 'http://de.wikipedia.org/wiki/Foo' ,
'html/0/rel' : 'mw:WikiLink/Language'
} ,
'internal' : { 'whitespace' : [ '\n' , undefined , undefined , '\n' ] }
} ,
{ 'type' : '/MWlanguage' } ,
{
'type' : 'MWlanguage' ,
'attributes' : {
'href' : 'http://fr.wikipedia.org/wiki/Foo' ,
'html/0/href' : 'http://fr.wikipedia.org/wiki/Foo' ,
'html/0/rel' : 'mw:WikiLink/Language'
} ,
'internal' : { 'whitespace' : [ '\n' ] }
} ,
{ 'type' : '/MWlanguage' }
]
} ,
Preserve whitespace between elements
This commit fully utilizes all four positions in the internal.whitespace
array. Outer whitespace is now preserved as well, and is duplicated
either in the adjacent sibling (one node's outerPost is the next
sibling's outerPre) or in the parent (a branch node's innerPre is its
first child's outerPre, and its innerPost is its last child's
outerPost). Before restoring saved whitespace, we check that these two
agree with each other, and if they disagree we assume the user has been
moving stuff around and don't restore any whitespace in that spot. The
whitespace at the very beginning and the very end of the document (i.e.
the first node's outerPre and the last node's outerPost) isn't
duplicated anywhere, nor is inner whitespace in content nodes.
The basic outline of the implementation is:
* When we encounter whitespace, strip it and store it in the previous
node's outerPost. Also store it in nextWhitespace so we can put it in
the next node's outerPre once we encounter that node.
* When we encounter whitespace in wrapped bare text, we don't know in
advance if it's gonna be succeeded by more non-whitespace (in which
case it needs to be output verbatim), or not (in which case it's
leading whitespace and needs to be stripped and stored). The fact that
annotations are nodes in HTML makes this trickier. So we write the
whitespace to the temporary linmod and store it in wrappedWhitespace,
then if it turns out to be trailing whitespace we take it back out of
the data array and record it the usual way.
* Because text nodes can contain any combination of leading whitespace
actual text and trailing whitespace, and because we may or may not
already have opened a wrapping paragraph, there are a lot of different
combinations to handle. We handle all of them but the resulting code
is pretty dense and verbose.
More low-level list of changes:
In getDataFromDom():
* Added helper function addWhitespace() for storing whitespace for an
element
* Added helper function processNextWhitespace() for processing any
whitespace passed on from the previous node via the nextWhitespace var
* Rename paragraph to wrappingParagraph. Make wrapping default to
alreadyWrapped so we can simplify wrapping||alreadyWrapped and
!wrapping&&!alreadyWrapped. Add wrappingIsOurs to track whether the
wrapping originated in this recursion level (needed for deciding when
to close the wrapper).
* Add prevElement to track the previous element so we can propagate
whitespace to it, and nextWhitespace so we can propagate whitespace to
the next element.
* Remove previous newline stripping hacks
* Integrate the logic for wrapping bare content with the outer
whitespace preservation code
* Remove wrapperElement, no longer needed because we have a dedicated
variable for the wrapping paragraph now and what was previously inner
whitespace preservation for wrapper paragraphs is now covered by the
outer whitespace preservation code.
In getDomFromData():
* Reinsert whitespace where appropriate
** outerPre is inserted when opening the element
** This covers outerPost as well except for the last child's outerPost,
which is handled as the parent's innerPost when closing the parent.
** innerPre and innerPost are inserted when closing the element. Care is
taken not to insert these if they're duplicates of something else.
* Propagate each node's outerPost to the next node (either the next
sibling or the parent) using parentDomElement.lastOuterPost. We can't
get this using .lastChild because we will have destroyed that child's
.veInternal by then, and we can't tell whether a node will be its
parent's last child when we process it (all other processing,
including first child handling is done when processing the node itself,
but this cannot be).
* Special handling is needed for the last node's outerPost, which ends
up in the container's .lastOuterPost property.
Tests:
* Allow .html to be null in data<->DOM converter tests. This indicates
that the test is a one-way data->DOM test, not a DOM->data->DOM
round-trip test. The data will be converted to HTML and checked
against .normalizedHtml
* Update existing tests as needed
* Add tests for outer whitespace preservation and storage
* Add test for squashing of whitespace in case of disagreement (this
requires .html=null)
Change-Id: I4db4fe372a421182e80a2535657af7784ff15f95
2012-08-21 00:37:42 +00:00
'mismatching whitespace data is ignored' : {
'html' : null ,
'data' : [
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } , 'internal' : { 'whitespace' : [ ' ' , ' ' , ' ' , ' ' ] } } ,
{ 'type' : 'listItem' , 'internal' : { 'whitespace' : [ ' ' , ' ' , ' ' , ' ' ] } } ,
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ ' ' , '\t' , '\n' , ' ' ] } } ,
'A' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ ' ' ] } } ,
'B' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' }
] ,
2013-02-11 19:46:58 +00:00
'normalizedHtml' : '<body> <ul><li><p>\tA\n</p> <p>B</p></li></ul> </body>'
2012-08-31 19:22:40 +00:00
} ,
'order of nested annotations is preserved' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p><b><a rel="mw:WikiLink" href="Foo"><i>Foo</i></a></b></p></body>' ,
2012-08-31 19:22:40 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
[
'F' ,
[
2012-10-06 00:34:12 +00:00
ve . dm . example . bold ,
2012-08-31 19:22:40 +00:00
{
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-09-06 22:40:41 +00:00
'hrefPrefix' : '' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'title' : 'Foo' ,
'html/0/href' : 'Foo' ,
'html/0/rel' : 'mw:WikiLink'
2012-08-31 19:22:40 +00:00
}
} ,
2012-10-06 00:34:12 +00:00
ve . dm . example . italic
2012-08-31 19:22:40 +00:00
]
] ,
[
'o' ,
[
2012-10-06 00:34:12 +00:00
ve . dm . example . bold ,
2012-08-31 19:22:40 +00:00
{
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-09-06 22:40:41 +00:00
'hrefPrefix' : '' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'title' : 'Foo' ,
'html/0/href' : 'Foo' ,
'html/0/rel' : 'mw:WikiLink'
2012-08-31 19:22:40 +00:00
}
} ,
2012-10-06 00:34:12 +00:00
ve . dm . example . italic
2012-08-31 19:22:40 +00:00
]
] ,
[
'o' ,
[
2012-10-06 00:34:12 +00:00
ve . dm . example . bold ,
2012-08-31 19:22:40 +00:00
{
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-09-06 22:40:41 +00:00
'hrefPrefix' : '' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'title' : 'Foo' ,
'html/0/href' : 'Foo' ,
'html/0/rel' : 'mw:WikiLink'
2012-08-31 19:22:40 +00:00
}
} ,
2012-10-06 00:34:12 +00:00
ve . dm . example . italic
2012-08-31 19:22:40 +00:00
]
] ,
{ 'type' : '/paragraph' }
]
} ,
'nested annotations are closed and reopened in the correct order' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p><a rel="mw:WikiLink" href="Foo">F<b>o<i>o</i></b><i>b</i></a><i>a<b>r</b>b<u>a</u>z</i></p></body>' ,
2012-08-31 19:22:40 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
[
'F' ,
[
{
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-09-06 22:40:41 +00:00
'hrefPrefix' : '' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'title' : 'Foo' ,
'html/0/href' : 'Foo' ,
'html/0/rel' : 'mw:WikiLink'
2012-08-31 19:22:40 +00:00
}
}
]
] ,
[
'o' ,
[
{
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-09-06 22:40:41 +00:00
'hrefPrefix' : '' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'title' : 'Foo' ,
'html/0/href' : 'Foo' ,
'html/0/rel' : 'mw:WikiLink'
2012-08-31 19:22:40 +00:00
}
} ,
2012-10-06 00:34:12 +00:00
ve . dm . example . bold
2012-08-31 19:22:40 +00:00
]
] ,
[
'o' ,
[
{
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-09-06 22:40:41 +00:00
'hrefPrefix' : '' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'title' : 'Foo' ,
'html/0/href' : 'Foo' ,
'html/0/rel' : 'mw:WikiLink'
2012-08-31 19:22:40 +00:00
}
} ,
2012-10-06 00:34:12 +00:00
ve . dm . example . bold ,
ve . dm . example . italic
2012-08-31 19:22:40 +00:00
]
] ,
[
'b' ,
[
{
2012-10-06 00:34:12 +00:00
'type' : 'link/MWinternal' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'attributes' : {
2012-09-06 22:40:41 +00:00
'hrefPrefix' : '' ,
2012-11-23 18:56:00 +00:00
'origTitle' : 'Foo' ,
Great Annotation Refactor of 2013
This changes the annotation API to be the same as the node API, sans
a few boolean flags that don't apply. The APIs were different, but
there was really no good reason why, so this makes things simpler for
API users. It also means we'll be able to factor a bunch of things out
because they're now duplicated between nodes, meta items and annotations.
Linear model annotations are now objects with 'type' and 'attributes'
properties (rather than 'name' and 'data'), for consistency with elements.
They now also contain html/0/* attributes for HTML attribute preservation,
which obsoletes the htmlTagName and htmlAttributes properties.
dm.Annotation subclasses take a reference to such an object and implement
conversion using .static.toDataElement and .static.toDomElements just
like nodes do. The custom .getHash() functions are no longer necessary
because of the way HTML attribute preservation was reimplemented.
CE rendering has been moved out of dm.Annotation (it never made sense to
have CE rendering functions in DM classes, this was bothering me) and into
separate ce.Annotation subclasses. These are very similar to CE nodes in
that they have a this.$ generated based on something in the DM; the main
difference is that nodes listen to events and update themselves, whereas
annotations are static and are simply destroyed and rebuilt when they
change. This change also adds whitelisted HTML attribute rendering for
annotations, as well as class="ve-ce-FooAnnotation" attributes.
Now that annotation classes produce real DOM nodes rather than weird
objects describing HTML tags, we can't generate HTML as a string in
ce.ContentBranchNode anymore. getRenderedContents() has been rewritten
to be much more similar to the way the converter renders annotations;
in fact, significant parts of it were copied from the converter, so that
should be factored out in the future. This change actually fixes an
annotation rendering discrepancy between ce.ContentBranchNode and
dm.Converter; see the diff of ve.ce.ContentBranchNode.test.js.
ve.ce.MWEntityNode.js:
* Remove stray property
ve.dm.MWExternalLinkAnnotation.js:
* Store 'rel' attribute
ve.dm.TextStyleAnnotation.js:
* Put all the conversion logic in the abstract base class
ve.dm.Converter.js:
* Also feed annotations through getDomElementsFromDataElement() and
createDataElement()
ve.dm.Node.js:
* Fix undocumented property
ve.ce.ContentBranchNode.test.js:
* Add descriptive messages for each test case
* Compare DOM trees, not HTML strings
* Compare without all the class="ve-ce-WhateverAnnotation" clutter
ve.ui.LinkInspector.js:
* Replace direct .getHash() calls (evil!) with ve.getHash()
Bug: 46464
Bug: 44808
Change-Id: I31991488579b8cce6d98ed8b29b486ba5ec38cdc
2013-04-02 17:23:33 +00:00
'title' : 'Foo' ,
'html/0/href' : 'Foo' ,
'html/0/rel' : 'mw:WikiLink'
2012-08-31 19:22:40 +00:00
}
} ,
2012-10-06 00:34:12 +00:00
ve . dm . example . italic
2012-08-31 19:22:40 +00:00
]
] ,
[
'a' ,
[
2012-10-06 00:34:12 +00:00
ve . dm . example . italic
2012-08-31 19:22:40 +00:00
]
] ,
[
'r' ,
[
2012-10-06 00:34:12 +00:00
ve . dm . example . italic ,
ve . dm . example . bold
2012-08-31 19:22:40 +00:00
]
] ,
[
'b' ,
[
2012-10-06 00:34:12 +00:00
ve . dm . example . italic
2012-08-31 19:22:40 +00:00
]
] ,
[
'a' ,
[
2012-10-06 00:34:12 +00:00
ve . dm . example . italic ,
ve . dm . example . underline
2012-08-31 19:22:40 +00:00
]
] ,
[
'z' ,
[
2012-10-06 00:34:12 +00:00
ve . dm . example . italic
2012-08-31 19:22:40 +00:00
]
] ,
{ 'type' : '/paragraph' }
]
2012-09-06 21:07:39 +00:00
} ,
'document with meta elements' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><!-- No content conversion --><meta property="mw:PageProp/nocc" /><p>Foo' +
2012-09-06 21:07:39 +00:00
'<link rel="mw:WikiLink/Category" href="./Category:Bar" />Bar' +
2012-11-20 04:01:09 +00:00
'<meta property="mw:foo" content="bar" />Ba<!-- inline -->z</p>' +
'<meta property="mw:bar" content="baz" /><!--barbaz-->' +
2013-03-21 19:18:52 +00:00
'<link rel="mw:WikiLink/Category" href="./Category:Foo_foo#Bar baz%23quux" />' +
2013-02-11 19:46:58 +00:00
'<meta typeof="mw:Placeholder" data-parsoid="foobar" /></body>' ,
2012-10-30 01:42:12 +00:00
'data' : ve . dm . example . withMeta
2012-10-23 00:53:58 +00:00
} ,
2013-04-09 00:59:15 +00:00
'RDFa types spread across two attributes' : {
'html' : '<body><link rel="mw:WikiLink/Category" href="./Category:Foo" about="#mwt1" typeof="mw:Object/Template"></body>' ,
'data' : [
{
'type' : 'alienMeta' ,
'attributes' : {
'style' : 'link' ,
'key' : 'mw:WikiLink/Category' ,
'value' : './Category:Foo' ,
'html/0/rel' : 'mw:WikiLink/Category' ,
'html/0/href' : './Category:Foo' ,
'html/0/about' : '#mwt1' ,
'html/0/typeof' : 'mw:Object/Template'
}
} ,
{ 'type' : '/alienMeta' } ,
]
} ,
2012-10-23 00:53:58 +00:00
'change markers' : {
'html' : null ,
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'changed' : { 'content' : 1 } } } ,
'F' ,
'o' ,
'o' ,
{ 'type' : 'image' , 'internal' : { 'changed' : { 'attributes' : 2 } } } ,
{ 'type' : '/image' } ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'paragraph' , 'internal' : { 'changed' : { 'created' : 1 } } } ,
'B' ,
'a' ,
'r' ,
2012-11-16 23:39:35 +00:00
{ 'type' : '/paragraph' } ,
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
{ 'type' : 'listItem' } ,
{
'type' : 'paragraph' ,
'internal' : {
'generated' : 'wrapper' ,
'changed' : { 'content' : 1 }
}
} ,
'B' ,
'a' ,
'z' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' }
2012-10-23 00:53:58 +00:00
] ,
2013-02-11 19:46:58 +00:00
'normalizedHtml' : '<body><p data-ve-changed="{"content":1}">' +
2012-10-23 00:53:58 +00:00
'Foo<img data-ve-changed="{"attributes":2}" />' +
2012-11-16 23:39:35 +00:00
'</p><p data-ve-changed="{"created":1}">Bar</p>' +
2013-02-11 19:46:58 +00:00
'<ul><li data-ve-changed="{"content":1}">Baz</li></ul></body>'
2012-11-08 02:03:05 +00:00
} ,
'about grouping' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><div typeof="mw:Placeholder" about="#mwt1">Foo</div>' +
2012-11-08 02:03:05 +00:00
'<figure typeof="mw:Placeholder" about="#mwt1">Bar</figure>' +
'<figure typeof="mw:Placeholder" about="#mwt2">Baz</figure>' +
'<span typeof="mw:Placeholder" about="#mwt2">Quux</span>' +
'<p>Whee</p><span typeof="mw:Placeholder" about="#mwt2">Yay</span>' +
'<div typeof="mw:Placeholder" about="#mwt2">Blah</div>' +
2013-02-11 19:46:58 +00:00
'<span typeof="mw:Placeholder" about="#mwt3">Meh</span></body>' ,
2012-11-08 02:03:05 +00:00
'data' : [
{
'type' : 'alienBlock' ,
'attributes' : {
'html' : '<div typeof="mw:Placeholder" about="#mwt1">Foo</div>' +
'<figure typeof="mw:Placeholder" about="#mwt1">Bar</figure>'
}
} ,
{ 'type' : '/alienBlock' } ,
{
'type' : 'alienBlock' ,
'attributes' : {
'html' : '<figure typeof="mw:Placeholder" about="#mwt2">Baz</figure>' +
'<span typeof="mw:Placeholder" about="#mwt2">Quux</span>'
}
} ,
{ 'type' : '/alienBlock' } ,
{ 'type' : 'paragraph' } ,
'W' ,
'h' ,
'e' ,
'e' ,
{ 'type' : '/paragraph' } ,
{
'type' : 'alienBlock' ,
'attributes' : {
'html' : '<span typeof="mw:Placeholder" about="#mwt2">Yay</span>' +
'<div typeof="mw:Placeholder" about="#mwt2">Blah</div>'
}
} ,
{ 'type' : '/alienBlock' } ,
(bug 43056) Inline tags like <span> are block-alienated sometimes
This happens when the <span> is the start of unwrapped content. The
converter logic to look at the tag name in wrapping mode doesn't kick in
because we're not yet in wrapping mode at that point.
The core issue was that previously, we relied on the document
structure/state to choose between alienBlock and alienInline, and only
used the tag name where the document structure was ambiguous (wrapping).
Changed this to be the other way around: we now rely primarily on the
tag name, and if that doesn't match what we expect based on the document
structure, we work around that if possible. Specifically:
* inline tag in our wrapper --> inline alien
* block tag in our wrapper --> close wrapper, block alien
* inline tag in wrapper that's not ours --> inline alien
* block tag in wrapper that's not ours --> *inline* alien
* inline tag in structural location --> open wrapper, inline alien
* block tag in structural location --> block alien
* inline tag in content location --> inline alien
* block tag in content location --> *inline* alien
only in the fourth and the last case do we need to use the "wrong" alien type to
preserve document validity, and it will always be inline where block was
expected, which should reduce UI issues.
The condensed version of the above, which is used in the code, is:
* If in a non-wrapper content location, use inline
* If in a wrapper that's not ours, use inline
* Otherwise, decide based on tag name
* Open or close wrapper if needed
ve.dm.Converter:
* Replace isInline logic in createAlien() with the above
* Factor out code to start wrapping (was duplicated) into startWrapping()
* Call startWrapping() if createAlien() returns an alienInline and we're
in a structural location
Tests:
* Add test cases with aliens at the start and end of unwrapped content
** The first one failed prior to these changes and now passes, the
second one was already passing
* Fix about group test case, was exhibiting the bug that this commit fixes
Change-Id: I657aa0ff5bc2b57cd48ef8a99c8ca930936c03b8
2012-12-20 00:59:58 +00:00
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
2012-11-08 02:03:05 +00:00
{
(bug 43056) Inline tags like <span> are block-alienated sometimes
This happens when the <span> is the start of unwrapped content. The
converter logic to look at the tag name in wrapping mode doesn't kick in
because we're not yet in wrapping mode at that point.
The core issue was that previously, we relied on the document
structure/state to choose between alienBlock and alienInline, and only
used the tag name where the document structure was ambiguous (wrapping).
Changed this to be the other way around: we now rely primarily on the
tag name, and if that doesn't match what we expect based on the document
structure, we work around that if possible. Specifically:
* inline tag in our wrapper --> inline alien
* block tag in our wrapper --> close wrapper, block alien
* inline tag in wrapper that's not ours --> inline alien
* block tag in wrapper that's not ours --> *inline* alien
* inline tag in structural location --> open wrapper, inline alien
* block tag in structural location --> block alien
* inline tag in content location --> inline alien
* block tag in content location --> *inline* alien
only in the fourth and the last case do we need to use the "wrong" alien type to
preserve document validity, and it will always be inline where block was
expected, which should reduce UI issues.
The condensed version of the above, which is used in the code, is:
* If in a non-wrapper content location, use inline
* If in a wrapper that's not ours, use inline
* Otherwise, decide based on tag name
* Open or close wrapper if needed
ve.dm.Converter:
* Replace isInline logic in createAlien() with the above
* Factor out code to start wrapping (was duplicated) into startWrapping()
* Call startWrapping() if createAlien() returns an alienInline and we're
in a structural location
Tests:
* Add test cases with aliens at the start and end of unwrapped content
** The first one failed prior to these changes and now passes, the
second one was already passing
* Fix about group test case, was exhibiting the bug that this commit fixes
Change-Id: I657aa0ff5bc2b57cd48ef8a99c8ca930936c03b8
2012-12-20 00:59:58 +00:00
'type' : 'alienInline' ,
2012-11-08 02:03:05 +00:00
'attributes' : {
'html' : '<span typeof="mw:Placeholder" about="#mwt3">Meh</span>'
}
} ,
(bug 43056) Inline tags like <span> are block-alienated sometimes
This happens when the <span> is the start of unwrapped content. The
converter logic to look at the tag name in wrapping mode doesn't kick in
because we're not yet in wrapping mode at that point.
The core issue was that previously, we relied on the document
structure/state to choose between alienBlock and alienInline, and only
used the tag name where the document structure was ambiguous (wrapping).
Changed this to be the other way around: we now rely primarily on the
tag name, and if that doesn't match what we expect based on the document
structure, we work around that if possible. Specifically:
* inline tag in our wrapper --> inline alien
* block tag in our wrapper --> close wrapper, block alien
* inline tag in wrapper that's not ours --> inline alien
* block tag in wrapper that's not ours --> *inline* alien
* inline tag in structural location --> open wrapper, inline alien
* block tag in structural location --> block alien
* inline tag in content location --> inline alien
* block tag in content location --> *inline* alien
only in the fourth and the last case do we need to use the "wrong" alien type to
preserve document validity, and it will always be inline where block was
expected, which should reduce UI issues.
The condensed version of the above, which is used in the code, is:
* If in a non-wrapper content location, use inline
* If in a wrapper that's not ours, use inline
* Otherwise, decide based on tag name
* Open or close wrapper if needed
ve.dm.Converter:
* Replace isInline logic in createAlien() with the above
* Factor out code to start wrapping (was duplicated) into startWrapping()
* Call startWrapping() if createAlien() returns an alienInline and we're
in a structural location
Tests:
* Add test cases with aliens at the start and end of unwrapped content
** The first one failed prior to these changes and now passes, the
second one was already passing
* Fix about group test case, was exhibiting the bug that this commit fixes
Change-Id: I657aa0ff5bc2b57cd48ef8a99c8ca930936c03b8
2012-12-20 00:59:58 +00:00
{ 'type' : '/alienInline' } ,
{ 'type' : '/paragraph' }
2012-11-08 02:03:05 +00:00
]
} ,
'whitespace preservation with an about group' : {
2013-02-11 19:46:58 +00:00
'html' : '<body> <div typeof="mw:Placeholder" about="#mwt1">\tFoo\t\t</div>\t\t\t' +
'<div typeof="mw:Placeholder" about="#mwt1"> Bar </div> </body>' ,
2012-11-08 02:03:05 +00:00
'data' : [
{
'type' : 'alienBlock' ,
'attributes' : {
'html' : '<div typeof="mw:Placeholder" about="#mwt1">\tFoo\t\t</div>\t\t\t' +
'<div typeof="mw:Placeholder" about="#mwt1"> Bar </div>'
} ,
'internal' : {
'whitespace' : [ ' ' , undefined , undefined , ' ' ]
}
} ,
{ 'type' : '/alienBlock' }
]
2012-11-20 23:37:06 +00:00
} ,
'mw:Entity' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p>a<span typeof="mw:Entity">¢</span>b<span typeof="mw:Entity">¥</span><span typeof="mw:Entity">™</span></p></body>' ,
2012-11-20 23:37:06 +00:00
'data' : [
{ 'type' : 'paragraph' } ,
'a' ,
2013-02-06 19:47:52 +00:00
{ 'type' : 'MWentity' , 'attributes' : { 'character' : '¢' , 'html/0/typeof' : 'mw:Entity' } } ,
2012-11-20 23:37:06 +00:00
{ 'type' : '/MWentity' } ,
'b' ,
2013-02-06 19:47:52 +00:00
{ 'type' : 'MWentity' , 'attributes' : { 'character' : '¥' , 'html/0/typeof' : 'mw:Entity' } } ,
2012-11-20 23:37:06 +00:00
{ 'type' : '/MWentity' } ,
2013-02-06 19:47:52 +00:00
{ 'type' : 'MWentity' , 'attributes' : { 'character' : '™' , 'html/0/typeof' : 'mw:Entity' } } ,
2012-11-20 23:37:06 +00:00
{ 'type' : '/MWentity' } ,
{ 'type' : '/paragraph' }
]
} ,
'wrapping with mw:Entity' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>a<span typeof="mw:Entity">¢</span>b<span typeof="mw:Entity">¥</span><span typeof="mw:Entity">™</span></body>' ,
2012-11-20 23:37:06 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'a' ,
2013-02-06 19:47:52 +00:00
{ 'type' : 'MWentity' , 'attributes' : { 'character' : '¢' , 'html/0/typeof' : 'mw:Entity' } } ,
2012-11-20 23:37:06 +00:00
{ 'type' : '/MWentity' } ,
'b' ,
2013-02-06 19:47:52 +00:00
{ 'type' : 'MWentity' , 'attributes' : { 'character' : '¥' , 'html/0/typeof' : 'mw:Entity' } } ,
2012-11-20 23:37:06 +00:00
{ 'type' : '/MWentity' } ,
2013-02-06 19:47:52 +00:00
{ 'type' : 'MWentity' , 'attributes' : { 'character' : '™' , 'html/0/typeof' : 'mw:Entity' } } ,
2012-11-20 23:37:06 +00:00
{ 'type' : '/MWentity' } ,
{ 'type' : '/paragraph' }
]
} ,
'whitespace preservation with mw:Entity' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><p> a <span typeof="mw:Entity"> </span> b <span typeof="mw:Entity">¥</span>\t<span typeof="mw:Entity">™</span></p></body>' ,
2012-11-20 23:37:06 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'whitespace' : [ undefined , ' ' ] } } ,
'a' ,
' ' ,
' ' ,
2013-02-06 19:47:52 +00:00
{ 'type' : 'MWentity' , 'attributes' : { 'character' : ' ' , 'html/0/typeof' : 'mw:Entity' } } ,
2012-11-20 23:37:06 +00:00
{ 'type' : '/MWentity' } ,
' ' ,
' ' ,
' ' ,
'b' ,
' ' ,
' ' ,
' ' ,
' ' ,
2013-02-06 19:47:52 +00:00
{ 'type' : 'MWentity' , 'attributes' : { 'character' : '¥' , 'html/0/typeof' : 'mw:Entity' } } ,
2012-11-20 23:37:06 +00:00
{ 'type' : '/MWentity' } ,
'\t' ,
2013-02-06 19:47:52 +00:00
{ 'type' : 'MWentity' , 'attributes' : { 'character' : '™' , 'html/0/typeof' : 'mw:Entity' } } ,
2012-11-20 23:37:06 +00:00
{ 'type' : '/MWentity' } ,
{ 'type' : '/paragraph' }
]
2012-12-05 22:35:10 +00:00
} ,
'block node inside annotation node is alienated' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><span>\n<p>Bar</p></span></body>' ,
2012-12-05 22:35:10 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
[ '\n' , [ ve . dm . example . span ] ] ,
{
'type' : 'alienInline' ,
'attributes' : {
'html' : '<p>Bar</p>'
} ,
'annotations' : [ ve . dm . example . span ]
} ,
{ 'type' : '/alienInline' } ,
{ 'type' : '/paragraph' }
]
} ,
'block node inside annotation node surrounded by tables' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><table></table><span>\n<p>Bar</p></span><table></table></body>' ,
2012-12-05 22:35:10 +00:00
'data' : [
{ 'type' : 'table' } ,
{ 'type' : '/table' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
[ '\n' , [ ve . dm . example . span ] ] ,
{
'type' : 'alienInline' ,
'attributes' : {
'html' : '<p>Bar</p>'
} ,
'annotations' : [ ve . dm . example . span ]
} ,
{ 'type' : '/alienInline' } ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'table' } ,
{ 'type' : '/table' }
]
} ,
'block node inside annotation node is alienated and continues wrapping' : {
2013-02-11 19:46:58 +00:00
'html' : '<body>Foo<span>\n<p>Bar</p></span>Baz</body>' ,
2012-12-05 22:35:10 +00:00
'data' : [
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'F' ,
'o' ,
'o' ,
[ '\n' , [ ve . dm . example . span ] ] ,
{
'type' : 'alienInline' ,
'attributes' : {
'html' : '<p>Bar</p>'
} ,
'annotations' : [ ve . dm . example . span ]
} ,
{ 'type' : '/alienInline' } ,
'B' ,
'a' ,
'z' ,
{ 'type' : '/paragraph' }
]
2012-12-11 18:23:33 +00:00
} ,
2013-04-18 01:26:54 +00:00
'context-sensitive nodes are alienated correctly' : {
'html' : '<table><caption>Foo</caption><tbody><tr><td>Bar</td></tr></tbody></table>' ,
'data' : [
{ 'type' : 'table' } ,
{ 'type' : 'alienBlock' , 'attributes' : { 'html' : '<caption>Foo</caption>' } } ,
{ 'type' : '/alienBlock' } ,
{ 'type' : 'tableSection' , 'attributes' : { 'style' : 'body' } } ,
{ 'type' : 'tableRow' } ,
{ 'type' : 'tableCell' , 'attributes' : { 'style' : 'data' } } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'B' ,
'a' ,
'r' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/tableCell' } ,
{ 'type' : '/tableRow' } ,
{ 'type' : '/tableSection' } ,
{ 'type' : '/table' }
]
} ,
2012-12-11 18:23:33 +00:00
'whitespace before meta node in wrapping mode' : {
2013-02-11 19:46:58 +00:00
'html' : '<body><table><tbody><tr><td>Foo\n<meta property="mw:foo" content="bar" /></td></tr></tbody></table></body>' ,
2012-12-11 18:23:33 +00:00
'data' : [
{ 'type' : 'table' } ,
{ 'type' : 'tableSection' , 'attributes' : { 'style' : 'body' } } ,
{ 'type' : 'tableRow' } ,
{
'type' : 'tableCell' ,
'attributes' : { 'style' : 'data' } ,
'internal' : { 'whitespace' : [ undefined , undefined , '\n' ] }
} ,
{
'type' : 'paragraph' ,
'internal' : {
'generated' : 'wrapper' ,
'whitespace' : [ undefined , undefined , undefined , '\n' ]
}
} ,
'F' ,
'o' ,
'o' ,
2013-04-18 23:06:58 +00:00
{ 'type' : '/paragraph' } ,
2012-12-11 18:23:33 +00:00
{
2013-02-21 23:01:04 +00:00
'type' : 'alienMeta' ,
2013-04-18 23:06:58 +00:00
'internal' : { 'whitespace' : [ '\n' ] } ,
2012-12-11 18:23:33 +00:00
'attributes' : {
'style' : 'meta' ,
'key' : 'mw:foo' ,
2013-02-16 02:37:50 +00:00
'value' : 'bar' ,
'html/0/content' : 'bar' ,
'html/0/property' : 'mw:foo'
2012-12-11 18:23:33 +00:00
}
} ,
2013-02-21 23:01:04 +00:00
{ 'type' : '/alienMeta' } ,
2012-12-11 18:23:33 +00:00
{ 'type' : '/tableCell' } ,
{ 'type' : '/tableRow' } ,
{ 'type' : '/tableSection' } ,
{ 'type' : '/table' }
]
2012-08-10 23:49:14 +00:00
}
2012-06-08 05:00:25 +00:00
} ;
2013-02-21 01:30:02 +00:00
ve . dm . example . isolationHTML =
'<ul><li>Item 1</li><li>Item 2</li><li>Item 3</li></ul>' +
'Paragraph' +
'<ul><li>Item 4</li><li>Item 5</li><li>Item 6</li></ul>' +
'<table><tbody><tr><td>Cell 1</td><td>Cell 2</td><td>Cell 3</td></tr><tr><td>Cell 4</td></tr></tbody></table>' +
'Not allowed by dm:' +
2013-03-01 01:20:59 +00:00
'<ul><li><h1>Title in list</h1></li><li><pre>Preformatted in list</pre></li></ul>' +
'<ul><li><ol><li>Nested 1</li><li>Nested 2</li><li>Nested 3</li></ol></li></ul>' +
'<ul><li><p>P1</p><p>P2</p><p>P3</p></li></ul>' ;
2013-02-21 01:30:02 +00:00
ve . dm . example . isolationData = [
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'I' , 't' , 'e' , 'm' , ' ' , '1' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'I' , 't' , 'e' , 'm' , ' ' , '2' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'I' , 't' , 'e' , 'm' , ' ' , '3' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'P' , 'a' , 'r' , 'a' , 'g' , 'r' , 'a' , 'p' , 'h' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'I' , 't' , 'e' , 'm' , ' ' , '4' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'I' , 't' , 'e' , 'm' , ' ' , '5' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'I' , 't' , 'e' , 'm' , ' ' , '6' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' } ,
{ 'type' : 'table' } ,
{ 'type' : 'tableSection' , 'attributes' : { 'style' : 'body' } } ,
{ 'type' : 'tableRow' } ,
{ 'type' : 'tableCell' , 'attributes' : { 'style' : 'data' } } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'C' , 'e' , 'l' , 'l' , ' ' , '1' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/tableCell' } ,
{ 'type' : 'tableCell' , 'attributes' : { 'style' : 'data' } } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'C' , 'e' , 'l' , 'l' , ' ' , '2' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/tableCell' } ,
{ 'type' : 'tableCell' , 'attributes' : { 'style' : 'data' } } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'C' , 'e' , 'l' , 'l' , ' ' , '3' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/tableCell' } ,
{ 'type' : '/tableRow' } ,
{ 'type' : 'tableRow' } ,
{ 'type' : 'tableCell' , 'attributes' : { 'style' : 'data' } } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'C' , 'e' , 'l' , 'l' , ' ' , '4' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/tableCell' } ,
{ 'type' : '/tableRow' } ,
{ 'type' : '/tableSection' } ,
{ 'type' : '/table' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'N' , 'o' , 't' , ' ' , 'a' , 'l' , 'l' , 'o' , 'w' , 'e' , 'd' , ' ' , 'b' , 'y' , ' ' , 'd' , 'm' , ': ' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'heading' , 'attributes' : { 'level' : 1 } } ,
'T' , 'i' , 't' , 'l' , 'e' , ' ' , 'i' , 'n' , ' ' , 'l' , 'i' , 's' , 't' ,
{ 'type' : '/heading' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'preformatted' } ,
'P' , 'r' , 'e' , 'f' , 'o' , 'r' , 'm' , 'a' , 't' , 't' , 'e' , 'd' , ' ' , 'i' , 'n' , ' ' , 'l' , 'i' , 's' , 't' ,
{ 'type' : '/preformatted' } ,
{ 'type' : '/listItem' } ,
2013-03-01 01:20:59 +00:00
{ 'type' : '/list' } ,
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'list' , 'attributes' : { 'style' : 'number' } } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'N' , 'e' , 's' , 't' , 'e' , 'd' , ' ' , '1' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'N' , 'e' , 's' , 't' , 'e' , 'd' , ' ' , '2' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' , 'internal' : { 'generated' : 'wrapper' } } ,
'N' , 'e' , 's' , 't' , 'e' , 'd' , ' ' , '3' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' } ,
{ 'type' : 'list' , 'attributes' : { 'style' : 'bullet' } } ,
{ 'type' : 'listItem' } ,
{ 'type' : 'paragraph' } ,
'P' , '1' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'paragraph' } ,
'P' , '2' ,
{ 'type' : '/paragraph' } ,
{ 'type' : 'paragraph' } ,
'P' , '3' ,
{ 'type' : '/paragraph' } ,
{ 'type' : '/listItem' } ,
{ 'type' : '/list' } ,
2013-02-22 23:26:18 +00:00
] ;