summaryrefslogtreecommitdiff
path: root/www/wiki/extensions/Cite/modules/ve-cite/ve.dm.MWReferenceModel.js
diff options
context:
space:
mode:
Diffstat (limited to 'www/wiki/extensions/Cite/modules/ve-cite/ve.dm.MWReferenceModel.js')
-rw-r--r--www/wiki/extensions/Cite/modules/ve-cite/ve.dm.MWReferenceModel.js283
1 files changed, 283 insertions, 0 deletions
diff --git a/www/wiki/extensions/Cite/modules/ve-cite/ve.dm.MWReferenceModel.js b/www/wiki/extensions/Cite/modules/ve-cite/ve.dm.MWReferenceModel.js
new file mode 100644
index 00000000..fcfccfac
--- /dev/null
+++ b/www/wiki/extensions/Cite/modules/ve-cite/ve.dm.MWReferenceModel.js
@@ -0,0 +1,283 @@
+/*!
+ * VisualEditor DataModel MWReferenceModel class.
+ *
+ * @copyright 2011-2018 VisualEditor Team's Cite sub-team and others; see AUTHORS.txt
+ * @license MIT
+ */
+
+/**
+ * MediaWiki reference model.
+ *
+ * @class
+ * @mixins OO.EventEmitter
+ *
+ * @constructor
+ * @param {ve.dm.Document} parentDoc Document that contains or will contain the reference
+ */
+ve.dm.MWReferenceModel = function VeDmMWReferenceModel( parentDoc ) {
+ // Mixin constructors
+ OO.EventEmitter.call( this );
+
+ // Properties
+ this.listKey = '';
+ this.listGroup = '';
+ this.listIndex = null;
+ this.group = '';
+ this.doc = null;
+ this.parentDoc = parentDoc;
+ this.deferDoc = null;
+};
+
+/* Inheritance */
+
+OO.mixinClass( ve.dm.MWReferenceModel, OO.EventEmitter );
+
+/* Static Methods */
+
+/**
+ * Create a reference model from a reference internal item.
+ *
+ * @param {ve.dm.MWReferenceNode} node Reference node
+ * @return {ve.dm.MWReferenceModel} Reference model
+ */
+ve.dm.MWReferenceModel.static.newFromReferenceNode = function ( node ) {
+ var doc = node.getDocument(),
+ internalList = doc.getInternalList(),
+ attr = node.getAttributes(),
+ ref = new ve.dm.MWReferenceModel( doc );
+
+ ref.setListKey( attr.listKey );
+ ref.setListGroup( attr.listGroup );
+ ref.setListIndex( attr.listIndex );
+ ref.setGroup( attr.refGroup );
+ ref.deferDoc = function () {
+ // cloneFromRange is very expensive, so lazy evaluate it
+ return doc.cloneFromRange( internalList.getItemNode( attr.listIndex ).getRange() );
+ };
+
+ return ref;
+};
+
+/* Methods */
+
+/**
+ * Find matching item in a surface.
+ *
+ * @param {ve.dm.Surface} surfaceModel Surface reference is in
+ * @return {ve.dm.InternalItemNode|null} Internal reference item, null if none exists
+ */
+ve.dm.MWReferenceModel.prototype.findInternalItem = function ( surfaceModel ) {
+ if ( this.listIndex !== null ) {
+ return surfaceModel.getDocument().getInternalList().getItemNode( this.listIndex );
+ }
+ return null;
+};
+
+/**
+ * Insert reference internal item into a surface.
+ *
+ * If the internal item for this reference doesn't exist, use this method to create one.
+ * The inserted reference is empty and auto-numbered.
+ *
+ * @param {ve.dm.Surface} surfaceModel Surface model of main document
+ */
+ve.dm.MWReferenceModel.prototype.insertInternalItem = function ( surfaceModel ) {
+ // Create new internal item
+ var item,
+ doc = surfaceModel.getDocument(),
+ internalList = doc.getInternalList();
+
+ // Fill in data
+ this.setListKey( 'auto/' + internalList.getNextUniqueNumber() );
+ this.setListGroup( 'mwReference/' + this.group );
+
+ // Insert internal reference item into document
+ item = internalList.getItemInsertion( this.listGroup, this.listKey, [] );
+ surfaceModel.change( item.transaction );
+ this.setListIndex( item.index );
+
+ // Inject reference document into internal reference item
+ surfaceModel.change(
+ ve.dm.TransactionBuilder.static.newFromDocumentInsertion(
+ doc,
+ internalList.getItemNode( item.index ).getRange().start,
+ this.getDocument()
+ )
+ );
+};
+
+/**
+ * Update an internal reference item.
+ *
+ * An internal item for the reference will be created if no `ref` argument is given.
+ *
+ * @param {ve.dm.Surface} surfaceModel Surface model of main document
+ */
+ve.dm.MWReferenceModel.prototype.updateInternalItem = function ( surfaceModel ) {
+ var i, len, txs, group, refNodes, keyIndex, itemNodeRange,
+ doc = surfaceModel.getDocument(),
+ internalList = doc.getInternalList(),
+ listGroup = 'mwReference/' + this.group;
+
+ // Group/key has changed
+ if ( this.listGroup !== listGroup ) {
+ // Get all reference nodes with the same group and key
+ group = internalList.getNodeGroup( this.listGroup );
+ refNodes = group.keyedNodes[ this.listKey ] ?
+ group.keyedNodes[ this.listKey ].slice() :
+ [ group.firstNodes[ this.listIndex ] ];
+ // Check for name collision when moving items between groups
+ keyIndex = internalList.getKeyIndex( this.listGroup, this.listKey );
+ if ( keyIndex !== undefined ) {
+ // Resolve name collision by generating a new list key
+ this.listKey = 'auto/' + internalList.getNextUniqueNumber();
+ }
+ // Update the group name of all references nodes with the same group and key
+ txs = [];
+ for ( i = 0, len = refNodes.length; i < len; i++ ) {
+ txs.push( ve.dm.TransactionBuilder.static.newFromAttributeChanges(
+ doc,
+ refNodes[ i ].getOuterRange().start,
+ { refGroup: this.group, listGroup: listGroup }
+ ) );
+ }
+ surfaceModel.change( txs );
+ this.listGroup = listGroup;
+ }
+ // Update internal node content
+ itemNodeRange = internalList.getItemNode( this.listIndex ).getRange();
+ surfaceModel.change( ve.dm.TransactionBuilder.static.newFromRemoval( doc, itemNodeRange, true ) );
+ surfaceModel.change(
+ ve.dm.TransactionBuilder.static.newFromDocumentInsertion( doc, itemNodeRange.start, this.getDocument() )
+ );
+};
+
+/**
+ * Insert reference at the end of a surface fragment.
+ *
+ * @param {ve.dm.SurfaceFragment} surfaceFragment Surface fragment to insert at
+ * @param {boolean} [placeholder] Reference is a placeholder for staging purposes
+ */
+ve.dm.MWReferenceModel.prototype.insertReferenceNode = function ( surfaceFragment, placeholder ) {
+ var attributes = {
+ listKey: this.listKey,
+ listGroup: this.listGroup,
+ listIndex: this.listIndex,
+ refGroup: this.group
+ };
+ if ( placeholder ) {
+ attributes.placeholder = true;
+ }
+ surfaceFragment
+ .insertContent( [
+ {
+ type: 'mwReference',
+ attributes: attributes
+ },
+ { type: '/mwReference' }
+ ] );
+};
+
+/**
+ * Get the key of a reference in the references list.
+ *
+ * @return {string} Reference's list key
+ */
+ve.dm.MWReferenceModel.prototype.getListKey = function () {
+ return this.listKey;
+};
+
+/**
+ * Get the name of the group a references list is in.
+ *
+ * @return {string} References list's group
+ */
+ve.dm.MWReferenceModel.prototype.getListGroup = function () {
+ return this.listGroup;
+};
+
+/**
+ * Get the index of reference in the references list.
+ *
+ * @return {string} Reference's index
+ */
+ve.dm.MWReferenceModel.prototype.getListIndex = function () {
+ return this.listIndex;
+};
+
+/**
+ * Get the name of the group a reference is in.
+ *
+ * @return {string} Reference's group
+ */
+ve.dm.MWReferenceModel.prototype.getGroup = function () {
+ return this.group;
+};
+
+/**
+ * Get reference document.
+ *
+ * Auto-generates a blank document if no document exists.
+ *
+ * @return {ve.dm.Document} Reference document
+ */
+ve.dm.MWReferenceModel.prototype.getDocument = function () {
+ if ( !this.doc ) {
+ if ( this.deferDoc ) {
+ this.doc = this.deferDoc();
+ } else {
+ this.doc = this.parentDoc.cloneWithData( [
+ { type: 'paragraph', internal: { generated: 'wrapper' } },
+ { type: '/paragraph' },
+ { type: 'internalList' },
+ { type: '/internalList' }
+ ] );
+ }
+ }
+ return this.doc;
+};
+
+/**
+ * Set key of reference in list.
+ *
+ * @param {string} listKey Reference's list key
+ */
+ve.dm.MWReferenceModel.prototype.setListKey = function ( listKey ) {
+ this.listKey = listKey;
+};
+
+/**
+ * Set name of the group a references list is in.
+ *
+ * @param {string} listGroup References list's group
+ */
+ve.dm.MWReferenceModel.prototype.setListGroup = function ( listGroup ) {
+ this.listGroup = listGroup;
+};
+
+/**
+ * Set the index of reference in list.
+ *
+ * @param {string} listIndex Reference's list index
+ */
+ve.dm.MWReferenceModel.prototype.setListIndex = function ( listIndex ) {
+ this.listIndex = listIndex;
+};
+
+/**
+ * Set the name of the group a reference is in.
+ *
+ * @param {string} group Reference's group
+ */
+ve.dm.MWReferenceModel.prototype.setGroup = function ( group ) {
+ this.group = group;
+};
+
+/**
+ * Set the reference document.
+ *
+ * @param {ve.dm.Document} doc Reference document
+ */
+ve.dm.MWReferenceModel.prototype.setDocument = function ( doc ) {
+ this.doc = doc;
+};