Esanders has uploaded a new change for review.

  https://gerrit.wikimedia.org/r/59651


Change subject: DM support for MW references
......................................................................

DM support for MW references

So far just read-only.

Change-Id: I6daff5c5969e5fdc871f8f346cf790b4302ae080
---
M VisualEditor.php
M demos/ve/index.php
M modules/ve/ce/nodes/ve.ce.AlienNode.js
M modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js
A modules/ve/ce/nodes/ve.ce.InternalReferenceListNode.js
A modules/ve/ce/nodes/ve.ce.InternalReferenceNode.js
A modules/ve/ce/nodes/ve.ce.MWReferenceNode.js
M modules/ve/ce/nodes/ve.ce.MWTemplateNode.js
M modules/ve/ce/ve.ce.ContentBranchNode.js
A modules/ve/dm/nodes/ve.dm.InternalReferenceListNode.js
A modules/ve/dm/nodes/ve.dm.InternalReferenceNode.js
M modules/ve/dm/nodes/ve.dm.MWHeadingNode.js
M modules/ve/dm/nodes/ve.dm.MWPreformattedNode.js
A modules/ve/dm/nodes/ve.dm.MWReferenceNode.js
M modules/ve/dm/ve.dm.Converter.js
M modules/ve/dm/ve.dm.Document.js
M modules/ve/dm/ve.dm.Model.js
A modules/ve/dm/ve.dm.ReferenceList.js
M modules/ve/init/mw/ve.init.mw.Target.js
M modules/ve/test/dm/ve.dm.Converter.test.js
M modules/ve/test/index.php
21 files changed, 473 insertions(+), 67 deletions(-)


  git pull ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor 
refs/changes/51/59651/1

diff --git a/VisualEditor.php b/VisualEditor.php
index 2453d51..da3bf46 100644
--- a/VisualEditor.php
+++ b/VisualEditor.php
@@ -236,6 +236,7 @@
                        've/dm/ve.dm.Annotation.js',
                        've/dm/ve.dm.MetaItem.js',
                        've/dm/ve.dm.MetaList.js',
+                       've/dm/ve.dm.ReferenceList.js',
                        've/dm/ve.dm.TransactionProcessor.js',
                        've/dm/ve.dm.Transaction.js',
                        've/dm/ve.dm.Surface.js',
@@ -260,6 +261,8 @@
                        've/dm/nodes/ve.dm.DocumentNode.js',
                        've/dm/nodes/ve.dm.HeadingNode.js',
                        've/dm/nodes/ve.dm.ImageNode.js',
+                       've/dm/nodes/ve.dm.InternalReferenceListNode.js',
+                       've/dm/nodes/ve.dm.InternalReferenceNode.js',
                        've/dm/nodes/ve.dm.ListItemNode.js',
                        've/dm/nodes/ve.dm.ListNode.js',
                        've/dm/nodes/ve.dm.ParagraphNode.js',
@@ -274,6 +277,7 @@
                        've/dm/nodes/ve.dm.MWHeadingNode.js',
                        've/dm/nodes/ve.dm.MWImageNode.js',
                        've/dm/nodes/ve.dm.MWPreformattedNode.js',
+                       've/dm/nodes/ve.dm.MWReferenceNode.js',
                        've/dm/nodes/ve.dm.MWTemplateNode.js',
 
                        've/dm/annotations/ve.dm.LinkAnnotation.js',
@@ -310,6 +314,8 @@
                        've/ce/nodes/ve.ce.DocumentNode.js',
                        've/ce/nodes/ve.ce.HeadingNode.js',
                        've/ce/nodes/ve.ce.ImageNode.js',
+                       've/ce/nodes/ve.ce.InternalReferenceListNode.js',
+                       've/ce/nodes/ve.ce.InternalReferenceNode.js',
                        've/ce/nodes/ve.ce.ListItemNode.js',
                        've/ce/nodes/ve.ce.ListNode.js',
                        've/ce/nodes/ve.ce.ParagraphNode.js',
@@ -324,6 +330,7 @@
                        've/ce/nodes/ve.ce.MWHeadingNode.js',
                        've/ce/nodes/ve.ce.MWImageNode.js',
                        've/ce/nodes/ve.ce.MWPreformattedNode.js',
+                       've/ce/nodes/ve.ce.MWReferenceNode.js',
                        've/ce/nodes/ve.ce.MWTemplateNode.js',
 
                        've/ce/annotations/ve.ce.LinkAnnotation.js',
diff --git a/demos/ve/index.php b/demos/ve/index.php
index 57cd489..d9b48ec 100644
--- a/demos/ve/index.php
+++ b/demos/ve/index.php
@@ -126,6 +126,7 @@
                <script src="../../modules/ve/dm/ve.dm.Annotation.js"></script>
                <script src="../../modules/ve/dm/ve.dm.MetaItem.js"></script>
                <script src="../../modules/ve/dm/ve.dm.MetaList.js"></script>
+               <script 
src="../../modules/ve/dm/ve.dm.ReferenceList.js"></script>
                <script 
src="../../modules/ve/dm/ve.dm.TransactionProcessor.js"></script>
                <script src="../../modules/ve/dm/ve.dm.Transaction.js"></script>
                <script src="../../modules/ve/dm/ve.dm.Surface.js"></script>
@@ -148,6 +149,8 @@
                <script 
src="../../modules/ve/dm/nodes/ve.dm.DocumentNode.js"></script>
                <script 
src="../../modules/ve/dm/nodes/ve.dm.HeadingNode.js"></script>
                <script 
src="../../modules/ve/dm/nodes/ve.dm.ImageNode.js"></script>
+               <script 
src="../../modules/ve/dm/nodes/ve.dm.InternalReferenceListNode.js"></script>
+               <script 
src="../../modules/ve/dm/nodes/ve.dm.InternalReferenceNode.js"></script>
                <script 
src="../../modules/ve/dm/nodes/ve.dm.ListItemNode.js"></script>
                <script 
src="../../modules/ve/dm/nodes/ve.dm.ListNode.js"></script>
                <script 
src="../../modules/ve/dm/nodes/ve.dm.ParagraphNode.js"></script>
@@ -161,6 +164,7 @@
                <script 
src="../../modules/ve/dm/nodes/ve.dm.MWHeadingNode.js"></script>
                <script 
src="../../modules/ve/dm/nodes/ve.dm.MWImageNode.js"></script>
                <script 
src="../../modules/ve/dm/nodes/ve.dm.MWPreformattedNode.js"></script>
+               <script 
src="../../modules/ve/dm/nodes/ve.dm.MWReferenceNode.js"></script>
                <script 
src="../../modules/ve/dm/nodes/ve.dm.MWTemplateNode.js"></script>
                <script 
src="../../modules/ve/dm/annotations/ve.dm.LinkAnnotation.js"></script>
                <script 
src="../../modules/ve/dm/annotations/ve.dm.MWExternalLinkAnnotation.js"></script>
@@ -192,6 +196,8 @@
                <script 
src="../../modules/ve/ce/nodes/ve.ce.DocumentNode.js"></script>
                <script 
src="../../modules/ve/ce/nodes/ve.ce.HeadingNode.js"></script>
                <script 
src="../../modules/ve/ce/nodes/ve.ce.ImageNode.js"></script>
+               <script 
src="../../modules/ve/ce/nodes/ve.ce.InternalReferenceListNode.js"></script>
+               <script 
src="../../modules/ve/ce/nodes/ve.ce.InternalReferenceNode.js"></script>
                <script 
src="../../modules/ve/ce/nodes/ve.ce.ListItemNode.js"></script>
                <script 
src="../../modules/ve/ce/nodes/ve.ce.ListNode.js"></script>
                <script 
src="../../modules/ve/ce/nodes/ve.ce.ParagraphNode.js"></script>
@@ -205,6 +211,7 @@
                <script 
src="../../modules/ve/ce/nodes/ve.ce.MWHeadingNode.js"></script>
                <script 
src="../../modules/ve/ce/nodes/ve.ce.MWImageNode.js"></script>
                <script 
src="../../modules/ve/ce/nodes/ve.ce.MWPreformattedNode.js"></script>
+               <script 
src="../../modules/ve/ce/nodes/ve.ce.MWReferenceNode.js"></script>
                <script 
src="../../modules/ve/ce/nodes/ve.ce.MWTemplateNode.js"></script>
                <script 
src="../../modules/ve/ce/annotations/ve.ce.LinkAnnotation.js"></script>
                <script 
src="../../modules/ve/ce/annotations/ve.ce.MWExternalLinkAnnotation.js"></script>
diff --git a/modules/ve/ce/nodes/ve.ce.AlienNode.js 
b/modules/ve/ce/nodes/ve.ce.AlienNode.js
index b0705ea..9ccccca 100644
--- a/modules/ve/ce/nodes/ve.ce.AlienNode.js
+++ b/modules/ve/ce/nodes/ve.ce.AlienNode.js
@@ -1,5 +1,5 @@
 /*!
- * VisualEditor ContentEditable AlienNode class.
+ * VisualEditor ContentEditable AlienNode, AlienBlockNode and AlienInlineNode 
classes.
  *
  * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
  * @license The MIT License (MIT); see LICENSE.txt
@@ -119,7 +119,7 @@
  * @param {jQuery.Event} e
  */
 ve.ce.AlienNode.prototype.onSurfaceMouseOut = function ( e ) {
-       if ( e.toElement === null) {
+       if ( e.toElement === null ) {
                this.clearPhantoms();
        }
 };
diff --git a/modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js 
b/modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js
index 7d54b08..63bb61b 100644
--- a/modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js
+++ b/modules/ve/ce/nodes/ve.ce.GeneratedContentNode.js
@@ -1,5 +1,5 @@
 /*!
- * VisualEditor ContentEditable GeneratedContent class.
+ * VisualEditor ContentEditable GeneratedContentNode class.
  *
  * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
  * @license The MIT License (MIT); see LICENSE.txt
diff --git a/modules/ve/ce/nodes/ve.ce.InternalReferenceListNode.js 
b/modules/ve/ce/nodes/ve.ce.InternalReferenceListNode.js
new file mode 100644
index 0000000..86e79e4
--- /dev/null
+++ b/modules/ve/ce/nodes/ve.ce.InternalReferenceListNode.js
@@ -0,0 +1,36 @@
+/*!
+ * VisualEditor InternalReferenceListNode class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * ContentEditable internal reference list node.
+ *
+ * @class
+ * @extends ve.ce.BranchNode
+ * @constructor
+ * @param {ve.dm.InternalReferenceListNode} model Model to observe
+ */
+ve.ce.InternalReferenceListNode = function VeCeInternalReferenceListNode( 
model ) {
+       // Parent constructor
+       ve.ce.BranchNode.call(
+               this, model, $( '<span>' )
+       );
+
+       // TODO: render nothing
+       this.$.hide();
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.ce.InternalReferenceListNode, ve.ce.BranchNode );
+
+/* Static Properties */
+
+ve.ce.InternalReferenceListNode.static.name = 'internalReferenceList';
+
+/* Registration */
+
+ve.ce.nodeFactory.register( ve.ce.InternalReferenceListNode );
diff --git a/modules/ve/ce/nodes/ve.ce.InternalReferenceNode.js 
b/modules/ve/ce/nodes/ve.ce.InternalReferenceNode.js
new file mode 100644
index 0000000..932b201
--- /dev/null
+++ b/modules/ve/ce/nodes/ve.ce.InternalReferenceNode.js
@@ -0,0 +1,34 @@
+/*!
+ * VisualEditor InternalReferenceNode class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * ContentEditable internal reference node.
+ *
+ * @class
+ * @extends ve.ce.BranchNode
+ * @constructor
+ * @param {ve.dm.InternalReferenceNode} model Model to observe
+ */
+ve.ce.InternalReferenceNode = function VeCeInternalReferenceNode( model ) {
+       // Parent constructor
+       ve.ce.BranchNode.call(
+               // TODO: render nothing
+               this, model, $( '<span>' )
+       );
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.ce.InternalReferenceNode, ve.ce.BranchNode );
+
+/* Static Properties */
+
+ve.ce.InternalReferenceNode.static.name = 'internalReference';
+
+/* Registration */
+
+ve.ce.nodeFactory.register( ve.ce.InternalReferenceNode );
diff --git a/modules/ve/ce/nodes/ve.ce.MWReferenceNode.js 
b/modules/ve/ce/nodes/ve.ce.MWReferenceNode.js
new file mode 100644
index 0000000..7b9139e
--- /dev/null
+++ b/modules/ve/ce/nodes/ve.ce.MWReferenceNode.js
@@ -0,0 +1,55 @@
+/*!
+ * VisualEditor ContentEditable MWReferenceNode class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * ContentEditable MediaWiki template node.
+ *
+ * @class
+ * @extends ve.ce.LeafNode
+ * @constructor
+ * @param {ve.dm.MWReferenceNode} model Model to observe
+ */
+ve.ce.MWReferenceNode = function VeCeMWReferenceNode( model ) {
+       // Parent constructor
+       ve.ce.LeafNode.call( this, model, $( '<sup>' ) );
+
+       // DOM Changes
+       this.$link = $( '<a>' ).attr( 'href', '#' );
+       this.$.addClass( 've-ce-MWreferenceNode', 'reference' )
+               .attr( 'contenteditable', false )
+               .append( this.$link );
+
+       // Events
+       this.model.addListenerMethod( this, 'update', 'onUpdate' );
+       this.$link.click( ve.bind( this.onClick, this ) );
+
+       // Initialization
+       this.onUpdate();
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.ce.MWReferenceNode, ve.ce.LeafNode );
+
+/* Static Properties */
+
+ve.ce.MWReferenceNode.static.name = 'MWreference';
+
+/* Methods */
+
+ve.ce.MWReferenceNode.prototype.onUpdate = function () {
+       this.$link.text( this.model.element.text );
+};
+
+ve.ce.MWReferenceNode.prototype.onClick = function ( e ) {
+       e.preventDefault();
+       // edit reference...
+};
+
+/* Registration */
+
+ve.ce.nodeFactory.register( ve.ce.MWReferenceNode );
diff --git a/modules/ve/ce/nodes/ve.ce.MWTemplateNode.js 
b/modules/ve/ce/nodes/ve.ce.MWTemplateNode.js
index 59c560c..48e66d4 100644
--- a/modules/ve/ce/nodes/ve.ce.MWTemplateNode.js
+++ b/modules/ve/ce/nodes/ve.ce.MWTemplateNode.js
@@ -1,5 +1,5 @@
 /*!
- * VisualEditor ContentEditable MWTemplate class.
+ * VisualEditor ContentEditable MWTemplateNode class.
  *
  * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
  * @license The MIT License (MIT); see LICENSE.txt
diff --git a/modules/ve/ce/ve.ce.ContentBranchNode.js 
b/modules/ve/ce/ve.ce.ContentBranchNode.js
index 8c589a7..bc55438 100644
--- a/modules/ve/ce/ve.ce.ContentBranchNode.js
+++ b/modules/ve/ce/ve.ce.ContentBranchNode.js
@@ -114,7 +114,7 @@
        // Detach all child nodes from this.$
        // We can't use this.$.empty() because that destroys .data() and event 
handlers
        this.$.contents().each( function () {
-               $(this).detach();
+               $( this ).detach();
        } );
 
        // Reattach child nodes with the right annotations
diff --git a/modules/ve/dm/nodes/ve.dm.InternalReferenceListNode.js 
b/modules/ve/dm/nodes/ve.dm.InternalReferenceListNode.js
new file mode 100644
index 0000000..8d2c740
--- /dev/null
+++ b/modules/ve/dm/nodes/ve.dm.InternalReferenceListNode.js
@@ -0,0 +1,38 @@
+/*!
+ * VisualEditor DataModel InternalReferenceListNode class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * DataModel internal reference node.
+ *
+ * @class
+ * @extends ve.dm.BranchNode
+ * @constructor
+ * @param {ve.dm.BranchNode[]} [children] Child nodes to attach
+ * @param {Object} [element] Reference to element in linear model
+ */
+ve.dm.InternalReferenceListNode = function VeDmInternalReferenceListNode( 
children, element ) {
+       // Parent constructor
+       ve.dm.BranchNode.call( this, children, element );
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.dm.InternalReferenceListNode, ve.dm.BranchNode );
+
+/* Static members */
+
+ve.dm.InternalReferenceListNode.static.name = 'internalReferenceList';
+
+ve.dm.InternalReferenceListNode.static.childNodeTypes = [ 'internalReference' 
];
+
+ve.dm.InternalReferenceListNode.static.matchTagNames = [];
+
+ve.dm.InternalReferenceListNode.static.isInternal = true;
+
+/* Registration */
+
+ve.dm.modelRegistry.register( ve.dm.InternalReferenceListNode );
\ No newline at end of file
diff --git a/modules/ve/dm/nodes/ve.dm.InternalReferenceNode.js 
b/modules/ve/dm/nodes/ve.dm.InternalReferenceNode.js
new file mode 100644
index 0000000..7d0cf5c
--- /dev/null
+++ b/modules/ve/dm/nodes/ve.dm.InternalReferenceNode.js
@@ -0,0 +1,38 @@
+/*!
+ * VisualEditor DataModel InternalReferenceNode class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * DataModel internal reference node.
+ *
+ * @class
+ * @extends ve.dm.BranchNode
+ * @constructor
+ * @param {ve.dm.BranchNode[]} [children] Child nodes to attach
+ * @param {Object} [element] Reference to element in linear model
+ */
+ve.dm.InternalReferenceNode = function VeDmInternalReferenceNode( children, 
element ) {
+       // Parent constructor
+       ve.dm.BranchNode.call( this, children, element );
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.dm.InternalReferenceNode, ve.dm.BranchNode );
+
+/* Static members */
+
+ve.dm.InternalReferenceNode.static.name = 'internalReference';
+
+ve.dm.InternalReferenceNode.static.matchTagNames = [];
+
+ve.dm.InternalReferenceNode.static.handlesOwnChildren = true;
+
+ve.dm.InternalReferenceNode.static.isInternal = true;
+
+/* Registration */
+
+ve.dm.modelRegistry.register( ve.dm.InternalReferenceNode );
\ No newline at end of file
diff --git a/modules/ve/dm/nodes/ve.dm.MWHeadingNode.js 
b/modules/ve/dm/nodes/ve.dm.MWHeadingNode.js
index 5fba677..320e331 100644
--- a/modules/ve/dm/nodes/ve.dm.MWHeadingNode.js
+++ b/modules/ve/dm/nodes/ve.dm.MWHeadingNode.js
@@ -6,7 +6,7 @@
  */
 
 /**
- * DataModel MW heading node.
+ * DataModel MediaWiki heading node.
  *
  * @class
  * @extends ve.dm.HeadingNode
diff --git a/modules/ve/dm/nodes/ve.dm.MWPreformattedNode.js 
b/modules/ve/dm/nodes/ve.dm.MWPreformattedNode.js
index 210d18f..2585b45 100644
--- a/modules/ve/dm/nodes/ve.dm.MWPreformattedNode.js
+++ b/modules/ve/dm/nodes/ve.dm.MWPreformattedNode.js
@@ -6,7 +6,7 @@
  */
 
 /**
- * DataModel MW preformatted node.
+ * DataModel MediaWiki preformatted node.
  *
  * @class
  * @extends ve.dm.PreformattedNode
diff --git a/modules/ve/dm/nodes/ve.dm.MWReferenceNode.js 
b/modules/ve/dm/nodes/ve.dm.MWReferenceNode.js
new file mode 100644
index 0000000..55dc681
--- /dev/null
+++ b/modules/ve/dm/nodes/ve.dm.MWReferenceNode.js
@@ -0,0 +1,69 @@
+/*!
+ * VisualEditor DataModel MWReferenceNode class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * DataModel MediaWiki reference node.
+ *
+ * @class
+ * @extends ve.dm.GeneratedContentNode
+ * @constructor
+ * @param {number} [length] Length of content data in document; ignored and 
overridden to 0
+ * @param {Object} [element] Reference to element in linear model
+ */
+ve.dm.MWReferenceNode = function VeDmMWReferenceNode( length, element ) {
+       // Parent constructor
+       ve.dm.GeneratedContentNode.call( this, 0, element );
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.dm.MWReferenceNode, ve.dm.GeneratedContentNode );
+
+/* Static members */
+
+ve.dm.MWReferenceNode.static.name = 'MWreference';
+
+ve.dm.MWReferenceNode.static.matchTagNames = null;
+
+// TODO: latest spec has this as mw:Object/Extension/Ref
+ve.dm.MWReferenceNode.static.matchRdfaTypes = [ 'mw:Object/Ext/Ref' ];
+
+ve.dm.MWReferenceNode.static.isContent = true;
+
+ve.dm.MWReferenceNode.static.toDataElement = function ( domElements, converter 
) {
+       var dataElement,
+               about = domElements[0].getAttribute( 'about' ),
+               text = $( '<div>', domElements[0].ownerDocument ).append( $( 
domElements ).clone() ).text(),
+               // TODO: this is always-present in the new spec, so "|| '{}'" 
can be removed later
+               mw = JSON.parse( domElements[0].getAttribute( 'data-mw' ) || 
'{}' ),
+               // TODO: this will be stored in mw.body.html in the new spec
+               body = JSON.parse( domElements[0].getAttribute( 'data-parsoid' 
) ).src,
+               // TODO: this will be stored in mw.name in the new spec
+               name = $( body ).attr( 'name' );
+
+       converter.referenceList.addReference( name, body );
+
+       dataElement = {
+               'type': this.name,
+               'mw': mw,
+               'about': about,
+               'text': text
+       };
+       return dataElement;
+};
+
+ve.dm.MWReferenceNode.static.toDomElements = function ( dataElement, doc ) {
+       var span = doc.createElement( 'span' );
+       span.setAttribute( 'about', dataElement.about );
+       // TODO: latest spec has this as mw:Object/Extension/Ref
+       span.setAttribute( 'typeof', 'mw:Object/Ext/Ref' );
+       span.setAttribute( 'data-mw', JSON.stringify( dataElement.mw ) );
+       return [ span ];
+};
+/* Registration */
+
+ve.dm.modelRegistry.register( ve.dm.MWReferenceNode );
\ No newline at end of file
diff --git a/modules/ve/dm/ve.dm.Converter.js b/modules/ve/dm/ve.dm.Converter.js
index eae715b..da6fe96 100644
--- a/modules/ve/dm/ve.dm.Converter.js
+++ b/modules/ve/dm/ve.dm.Converter.js
@@ -205,6 +205,9 @@
        if ( !nodeClass ) {
                throw new Error( 'Attempting to convert unknown data element 
type ' + dataElement.type );
        }
+       if ( nodeClass.static.isInternal ) {
+               return false;
+       }
        domElements = nodeClass.static.toDomElements( dataElements, doc, this );
        if ( !domElements || !domElements.length ) {
                throw new Error( 'toDomElements() failed to return an array 
when converting element of type ' + dataElement.type );
@@ -285,26 +288,33 @@
 
 /**
  * Convert an HTML document to a linear model.
- * @param {ve.dm.IndexValueStore} store Index-value store
  * @param {HTMLDocument} doc HTML document to convert
+ * @param {ve.dm.IndexValueStore} store Index-value store
+ * @param {ve.dm.ReferenceList} referenceList Reference list
  * @returns {ve.dm.ElementLinearData} Linear model data
  */
-ve.dm.Converter.prototype.getDataFromDom = function ( store, doc ) {
-       var result;
+ve.dm.Converter.prototype.getDataFromDom = function ( doc, store, 
referenceList ) {
+       var linearData, refData;
        // Set up the converter state
        this.doc = doc;
        this.store = store;
+       this.referenceList = referenceList;
        this.contextStack = [];
        // Possibly do things with doc and the head in the future
-       result = new ve.dm.ElementLinearData(
+
+       linearData = new ve.dm.ElementLinearData(
                store,
                this.getDataFromDomRecursion( doc.body )
        );
+       refData = this.referenceList.getDataFromDom( this );
+       linearData.batchSplice( linearData.getLength(), 0, refData );
+
        // Clear the state
        this.doc = null;
        this.store = null;
+       this.referenceList = null;
        this.contextStack = null;
-       return result;
+       return linearData;
 };
 
 /**
@@ -1025,59 +1035,61 @@
                                // Create node from data
                                dataElementOrSlice = getDataElementOrSlice();
                                childDomElements = 
this.getDomElementsFromDataElement( dataElementOrSlice, doc );
-                               // Add reference to internal data
-                               childDomElements[0].veInternal = 
ve.extendObject(
-                                       { 'childDomElements': childDomElements 
},
-                                       dataElement.internal || {}
-                               );
-                               // Add elements
-                               for ( j = 0; j < childDomElements.length; j++ ) 
{
-                                       domElement.appendChild( 
childDomElements[j] );
-                               }
-                               // Descend into the first child node
-                               parentDomElement = domElement;
-                               domElement = childDomElements[0];
-
-                               // Process outer whitespace
-                               // Every piece of outer whitespace is 
duplicated somewhere:
-                               // each node's outerPost is duplicated as the 
next node's
-                               // outerPre, the first node's outerPre is the 
parent's
-                               // innerPre, and the last node's outerPost is 
the parent's
-                               // innerPost. For each piece of whitespace, we 
verify that
-                               // the duplicate matches. If it doesn't, we 
take that to
-                               // mean the user has messed with it and don't 
output any
-                               // whitespace.
-                               if ( domElement.veInternal && 
domElement.veInternal.whitespace ) {
-                                       // Process this node's outerPre
-                                       ours = 
domElement.veInternal.whitespace[0];
-                                       theirs = undefined;
-                                       if ( domElement.previousSibling ) {
-                                               // Get previous sibling's 
outerPost
-                                               theirs = 
parentDomElement.lastOuterPost;
-                                       } else if ( parentDomElement === 
container ) {
-                                               // outerPre of the very first 
node in the document, this one
-                                               // has no duplicate
-                                               theirs = ours;
-                                       } else {
-                                               // First child, get parent's 
innerPre
-                                               if (
-                                                       
parentDomElement.veInternal &&
-                                                       
parentDomElement.veInternal.whitespace
-                                               ) {
-                                                       theirs = 
parentDomElement.veInternal.whitespace[1];
-                                                       // Clear after use so 
it's not used twice
-                                                       
parentDomElement.veInternal.whitespace[1] = undefined;
-                                               }
-                                               // else theirs=undefined
+                               if ( childDomElements ) {
+                                       // Add reference to internal data
+                                       childDomElements[0].veInternal = 
ve.extendObject(
+                                               { 'childDomElements': 
childDomElements },
+                                               dataElement.internal || {}
+                                       );
+                                       // Add elements
+                                       for ( j = 0; j < 
childDomElements.length; j++ ) {
+                                               domElement.appendChild( 
childDomElements[j] );
                                        }
-                                       if ( ours && ours === theirs ) {
-                                               // Matches the duplicate, 
insert a TextNode
-                                               textNode = doc.createTextNode( 
ours );
-                                               textNode.veIsWhitespace = true;
-                                               parentDomElement.insertBefore(
-                                                       textNode,
-                                                       domElement
-                                               );
+                                       // Descend into the first child node
+                                       parentDomElement = domElement;
+                                       domElement = childDomElements[0];
+
+                                       // Process outer whitespace
+                                       // Every piece of outer whitespace is 
duplicated somewhere:
+                                       // each node's outerPost is duplicated 
as the next node's
+                                       // outerPre, the first node's outerPre 
is the parent's
+                                       // innerPre, and the last node's 
outerPost is the parent's
+                                       // innerPost. For each piece of 
whitespace, we verify that
+                                       // the duplicate matches. If it 
doesn't, we take that to
+                                       // mean the user has messed with it and 
don't output any
+                                       // whitespace.
+                                       if ( domElement.veInternal && 
domElement.veInternal.whitespace ) {
+                                               // Process this node's outerPre
+                                               ours = 
domElement.veInternal.whitespace[0];
+                                               theirs = undefined;
+                                               if ( domElement.previousSibling 
) {
+                                                       // Get previous 
sibling's outerPost
+                                                       theirs = 
parentDomElement.lastOuterPost;
+                                               } else if ( parentDomElement 
=== container ) {
+                                                       // outerPre of the very 
first node in the document, this one
+                                                       // has no duplicate
+                                                       theirs = ours;
+                                               } else {
+                                                       // First child, get 
parent's innerPre
+                                                       if (
+                                                               
parentDomElement.veInternal &&
+                                                               
parentDomElement.veInternal.whitespace
+                                                       ) {
+                                                               theirs = 
parentDomElement.veInternal.whitespace[1];
+                                                               // Clear after 
use so it's not used twice
+                                                               
parentDomElement.veInternal.whitespace[1] = undefined;
+                                                       }
+                                                       // else theirs=undefined
+                                               }
+                                               if ( ours && ours === theirs ) {
+                                                       // Matches the 
duplicate, insert a TextNode
+                                                       textNode = 
doc.createTextNode( ours );
+                                                       textNode.veIsWhitespace 
= true;
+                                                       
parentDomElement.insertBefore(
+                                                               textNode,
+                                                               domElement
+                                                       );
+                                               }
                                        }
                                }
 
diff --git a/modules/ve/dm/ve.dm.Document.js b/modules/ve/dm/ve.dm.Document.js
index d353473..8b0120a 100644
--- a/modules/ve/dm/ve.dm.Document.js
+++ b/modules/ve/dm/ve.dm.Document.js
@@ -41,6 +41,7 @@
                currentNode = this.documentNode;
        this.documentNode.setDocument( doc );
        this.documentNode.setRoot( root );
+       this.referenceList = new ve.dm.ReferenceList( this );
 
        // Properties
        this.parentDocument = parentDocument;
@@ -48,7 +49,7 @@
        if ( documentOrData instanceof ve.dm.LinearData ) {
                this.data = documentOrData;
        } else if ( !ve.isArray( documentOrData ) && typeof documentOrData === 
'object' ) {
-               this.data = ve.dm.converter.getDataFromDom( new 
ve.dm.IndexValueStore(), documentOrData );
+               this.data = ve.dm.converter.getDataFromDom( documentOrData, new 
ve.dm.IndexValueStore(), this.getReferenceList() );
        } else {
                this.data = new ve.dm.ElementLinearData(
                        new ve.dm.IndexValueStore(),
@@ -267,6 +268,14 @@
 };
 
 /**
+ * Get the document's reference list
+ * @returns {ve.dm.ReferenceList} The document's reference list
+ */
+ve.dm.Document.prototype.getReferenceList = function () {
+       return this.referenceList;
+};
+
+/**
  * Splice data into and/or out of the linear model.
  *
  * `this.metadata` will be updated accordingly.
diff --git a/modules/ve/dm/ve.dm.Model.js b/modules/ve/dm/ve.dm.Model.js
index 550fc83..71eac79 100644
--- a/modules/ve/dm/ve.dm.Model.js
+++ b/modules/ve/dm/ve.dm.Model.js
@@ -65,6 +65,11 @@
 ve.dm.Model.static.matchFunction = null;
 
 /**
+ * Set the model to be internal. Internal model items are ignored by the 
converter.
+ */
+ve.dm.Model.static.isInternal = false;
+
+/**
  * Static function to convert a DOM element or set of sibling DOM elements to 
a linear model element
  * for this model type.
  *
diff --git a/modules/ve/dm/ve.dm.ReferenceList.js 
b/modules/ve/dm/ve.dm.ReferenceList.js
new file mode 100644
index 0000000..ec089be
--- /dev/null
+++ b/modules/ve/dm/ve.dm.ReferenceList.js
@@ -0,0 +1,88 @@
+/*!
+ * VisualEditor DataModel ReferenceList class.
+ *
+ * @copyright 2011-2013 VisualEditor Team and others; see AUTHORS.txt
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * DataModel meta item.
+ *
+ * @class
+ * @extends ve.EventEmitter
+ * @constructor
+ * @param {ve.dm.Document} doc Document model
+ */
+ve.dm.ReferenceList = function VeDmReferenceList(/* doc */) {
+       // Parent constructor
+       ve.EventEmitter.call( this );
+
+       // Properties
+       //this.document = doc;
+       this.store = new ve.dm.IndexValueStore();
+       this.domElements = [];
+       this.dataRanges = [];
+
+       // Event handlers
+       //this.document.on( 'transact', ve.bind( this.onTransact, this ) );
+};
+
+/* Inheritance */
+
+ve.inheritClass( ve.dm.ReferenceList, ve.EventEmitter );
+
+/* Methods */
+
+/**
+ * Add a reference to the list.
+ *
+ * If a reference by this name already exists it will be ignored.
+ *
+ * @param {string|null} name Reference name
+ * @param {string} body Reference contents
+ */
+ve.dm.ReferenceList.prototype.addReference = function ( name, body ) {
+       if ( name === null || this.store.indexOfHash( name ) === null ) {
+               this.domElements.push( this.store.index( body, name ) );
+       }
+};
+
+/**
+ * Gets all the reference DOM elements
+ * @returns {Object} Name-indexed object containing HTMLElements
+ */
+ve.dm.ReferenceList.prototype.getDomElements = function () {
+       return this.store.values( this.domElements );
+};
+
+/**
+ * Gets linear model data for all the stored reference DOM elements.
+ *
+ * Each reference is an internalReference item, and they are wrapped in an 
internalReferenceList.
+ * If there are no references an empty array is returned.
+ * 
+ * @param {ve.dm.Converter} converter Converter object
+ * @returns {Array} Linear model data
+ */
+ve.dm.ReferenceList.prototype.getDataFromDom = function ( converter ) {
+       var i, length, domElements, refData, endOffset,
+               refList = [], startOffset = 0, refElements = 
this.getDomElements();
+
+       if ( !ve.isEmptyObject( refElements ) ) {
+               refList.push( { 'type': 'internalReferenceList' } );
+               domElements = this.getDomElements();
+               for ( i = 0, length = domElements.length; i < length; i++ ) {
+                       refData = converter.getDataFromDomRecursion( $( 
domElements[i] )[0] );
+                       refList = refList.concat(
+                               [{ 'type': 'internalReference' }],
+                               refData,
+                               [{ 'type': '/internalReference' }]
+                       );
+                       endOffset = startOffset + refData.length + 2;
+                       this.dataRanges[i] = new ve.Range( startOffset, 
endOffset );
+                       startOffset = endOffset;
+               }
+               refList.push( { 'type': '/internalReferenceList' } );
+       }
+       return refList;
+};
\ No newline at end of file
diff --git a/modules/ve/init/mw/ve.init.mw.Target.js 
b/modules/ve/init/mw/ve.init.mw.Target.js
index 05abd6f..76820cc 100644
--- a/modules/ve/init/mw/ve.init.mw.Target.js
+++ b/modules/ve/init/mw/ve.init.mw.Target.js
@@ -577,6 +577,7 @@
        var now = new Date(),
                editedData = this.surface.getDocumentModel().getFullData(),
                store = this.surface.getDocumentModel().getStore(),
+               referenceList = 
this.surface.getDocumentModel().getReferenceList(),
                report = {
                        'title': this.pageName,
                        'oldid': this.oldid,
@@ -586,7 +587,7 @@
                        'originalHtml': this.originalHtml,
                        'originalData':
                                // originalHTML only has the body's HTML for 
now, see TODO comment in ve.init.mw.ViewPageTarget.prototype.setUpSurface
-                               ve.dm.converter.getDataFromDom( 
ve.createDocumentFromHTML( '<body>' + this.originalHtml  + '</body>') ),
+                               ve.dm.converter.getDataFromDom( 
ve.createDocumentFromHTML( '<body>' + this.originalHtml  + '</body>'), store, 
referenceList ),
                        'editedData': editedData,
                        'editedHtml': ve.dm.converter.getDomFromData( store, 
editedData ).body.innerHTML,
                        'wiki': mw.config.get( 'wgDBname' )
diff --git a/modules/ve/test/dm/ve.dm.Converter.test.js 
b/modules/ve/test/dm/ve.dm.Converter.test.js
index 9f63029..a09e9a7 100644
--- a/modules/ve/test/dm/ve.dm.Converter.test.js
+++ b/modules/ve/test/dm/ve.dm.Converter.test.js
@@ -60,7 +60,7 @@
                if ( cases[msg].html !== null ) {
                        ve.dm.example.preprocessAnnotations( cases[msg].data, 
store );
                        assert.deepEqual(
-                               ve.dm.converter.getDataFromDom( store, 
ve.createDocumentFromHTML( cases[msg].html ) ).getData(),
+                               ve.dm.converter.getDataFromDom( 
ve.createDocumentFromHTML( cases[msg].html ), store, new ve.dm.ReferenceList() 
).getData(),
                                cases[msg].data,
                                msg
                        );
diff --git a/modules/ve/test/index.php b/modules/ve/test/index.php
index fe9ccda..0a0596d 100644
--- a/modules/ve/test/index.php
+++ b/modules/ve/test/index.php
@@ -69,6 +69,7 @@
                <script src="../../ve/dm/ve.dm.Annotation.js"></script>
                <script src="../../ve/dm/ve.dm.MetaItem.js"></script>
                <script src="../../ve/dm/ve.dm.MetaList.js"></script>
+               <script src="../../ve/dm/ve.dm.ReferenceList.js"></script>
                <script 
src="../../ve/dm/ve.dm.TransactionProcessor.js"></script>
                <script src="../../ve/dm/ve.dm.Transaction.js"></script>
                <script src="../../ve/dm/ve.dm.Surface.js"></script>
@@ -91,6 +92,8 @@
                <script src="../../ve/dm/nodes/ve.dm.DocumentNode.js"></script>
                <script src="../../ve/dm/nodes/ve.dm.HeadingNode.js"></script>
                <script src="../../ve/dm/nodes/ve.dm.ImageNode.js"></script>
+               <script 
src="../../ve/dm/nodes/ve.dm.InternalReferenceListNode.js"></script>
+               <script 
src="../../ve/dm/nodes/ve.dm.InternalReferenceNode.js"></script>
                <script src="../../ve/dm/nodes/ve.dm.ListItemNode.js"></script>
                <script src="../../ve/dm/nodes/ve.dm.ListNode.js"></script>
                <script src="../../ve/dm/nodes/ve.dm.ParagraphNode.js"></script>
@@ -104,6 +107,7 @@
                <script src="../../ve/dm/nodes/ve.dm.MWHeadingNode.js"></script>
                <script src="../../ve/dm/nodes/ve.dm.MWImageNode.js"></script>
                <script 
src="../../ve/dm/nodes/ve.dm.MWPreformattedNode.js"></script>
+               <script 
src="../../ve/dm/nodes/ve.dm.MWReferenceNode.js"></script>
                <script 
src="../../ve/dm/nodes/ve.dm.MWTemplateNode.js"></script>
                <script 
src="../../ve/dm/annotations/ve.dm.LinkAnnotation.js"></script>
                <script 
src="../../ve/dm/annotations/ve.dm.MWExternalLinkAnnotation.js"></script>
@@ -135,6 +139,8 @@
                <script src="../../ve/ce/nodes/ve.ce.DocumentNode.js"></script>
                <script src="../../ve/ce/nodes/ve.ce.HeadingNode.js"></script>
                <script src="../../ve/ce/nodes/ve.ce.ImageNode.js"></script>
+               <script 
src="../../ve/ce/nodes/ve.ce.InternalReferenceListNode.js"></script>
+               <script 
src="../../ve/ce/nodes/ve.ce.InternalReferenceNode.js"></script>
                <script src="../../ve/ce/nodes/ve.ce.ListItemNode.js"></script>
                <script src="../../ve/ce/nodes/ve.ce.ListNode.js"></script>
                <script src="../../ve/ce/nodes/ve.ce.ParagraphNode.js"></script>
@@ -148,6 +154,7 @@
                <script src="../../ve/ce/nodes/ve.ce.MWHeadingNode.js"></script>
                <script src="../../ve/ce/nodes/ve.ce.MWImageNode.js"></script>
                <script 
src="../../ve/ce/nodes/ve.ce.MWPreformattedNode.js"></script>
+               <script 
src="../../ve/ce/nodes/ve.ce.MWReferenceNode.js"></script>
                <script 
src="../../ve/ce/nodes/ve.ce.MWTemplateNode.js"></script>
                <script 
src="../../ve/ce/annotations/ve.ce.LinkAnnotation.js"></script>
                <script 
src="../../ve/ce/annotations/ve.ce.MWExternalLinkAnnotation.js"></script>

-- 
To view, visit https://gerrit.wikimedia.org/r/59651
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: I6daff5c5969e5fdc871f8f346cf790b4302ae080
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/extensions/VisualEditor
Gerrit-Branch: master
Gerrit-Owner: Esanders <[email protected]>

_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to