http://www.mediawiki.org/wiki/Special:Code/MediaWiki/97302
Revision: 97302 Author: tparscal Date: 2011-09-16 18:04:03 +0000 (Fri, 16 Sep 2011) Log Message: ----------- Removed dynamic property names from base container and container item classes Modified Paths: -------------- trunk/parsers/wikidom/lib/synth/bases/es.ModelContainer.js trunk/parsers/wikidom/lib/synth/bases/es.ModelContainerItem.js trunk/parsers/wikidom/lib/synth/bases/es.ViewContainer.js trunk/parsers/wikidom/lib/synth/models/es.DocumentModel.js trunk/parsers/wikidom/lib/synth/models/es.ListBlockItemModel.js trunk/parsers/wikidom/lib/synth/models/es.TableBlockCellModel.js trunk/parsers/wikidom/lib/synth/models/es.TableBlockRowModel.js trunk/parsers/wikidom/lib/synth/views/es.DocumentView.js trunk/parsers/wikidom/lib/synth/views/es.ListBlockView.js trunk/parsers/wikidom/lib/synth/views/es.TableBlockRowView.js trunk/parsers/wikidom/lib/synth/views/es.TableBlockView.js Modified: trunk/parsers/wikidom/lib/synth/bases/es.ModelContainer.js =================================================================== --- trunk/parsers/wikidom/lib/synth/bases/es.ModelContainer.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/bases/es.ModelContainer.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -6,16 +6,11 @@ * @class * @constructor * @extends {es.EventEmitter} - * @param listName {String} Property name for list of items - * @property [listName] {Array} list of items + * @property items {Array} list of items */ -es.ModelContainer = function( listName ) { +es.ModelContainer = function() { es.EventEmitter.call( this ); - if ( typeof listName !== 'string' ) { - listName = 'items'; - } - this._listName = listName; - this[this._listName] = new es.AggregateArray(); + this.items = new es.AggregateArray(); var container = this; this.relayUpdate = function() { container.emit( 'update' ); @@ -31,7 +26,7 @@ * @returns {Object} Child object at index */ es.ModelContainer.prototype.get = function( index ) { - return this[this._listName][index] || null; + return this.items[index] || null; }; /** @@ -41,7 +36,7 @@ * @returns {Array} List of all items. */ es.ModelContainer.prototype.all = function() { - return this[this._listName]; + return this.items; }; /** @@ -51,7 +46,7 @@ * @returns {Integer} Number of items in container */ es.ModelContainer.prototype.getLength = function() { - return this[this._listName].length + return this.items.length }; /** @@ -61,7 +56,7 @@ * @returns {Integer} Index of item, -1 if item is not in container */ es.ModelContainer.prototype.indexOf = function( item ) { - return this[this._listName].indexOf( item ); + return this.items.indexOf( item ); }; /** @@ -71,7 +66,7 @@ * @returns {Object} First item */ es.ModelContainer.prototype.first = function() { - return this[this._listName].length ? this[this._listName][0] : null; + return this.items.length ? this.items[0] : null; }; /** @@ -81,8 +76,8 @@ * @returns {Object} Last item */ es.ModelContainer.prototype.last = function() { - return this[this._listName].length - ? this[this._listName][this[this._listName].length - 1] : null; + return this.items.length + ? this.items[this.items.length - 1] : null; }; /** @@ -94,8 +89,8 @@ * @param callback {Function} Function to call on each item which takes item and index arguments */ es.ModelContainer.prototype.each = function( callback ) { - for ( var i = 0; i < this[this._listName].length; i++ ) { - if ( callback( this[this._listName][i], i ) === false ) { + for ( var i = 0; i < this.items.length; i++ ) { + if ( callback( this.items[i], i ) === false ) { break; } } @@ -113,11 +108,11 @@ es.ModelContainer.prototype.append = function( item ) { var parent = item.parent(); if ( parent === this ) { - this[this._listName].splice( this.indexOf( item ), 1 ); + this.items.splice( this.indexOf( item ), 1 ); } else if ( parent ) { parent.remove( item ); } - this[this._listName].push( item ); + this.items.push( item ); item.on( 'update', this.relayUpdate ); item.attach( this ); this.emit( 'append', item ); @@ -136,11 +131,11 @@ es.ModelContainer.prototype.prepend = function( item ) { var parent = item.parent(); if ( parent === this ) { - this[this._listName].splice( this.indexOf( item ), 1 ); + this.items.splice( this.indexOf( item ), 1 ); } else if ( parent ) { parent.remove( item ); } - this[this._listName].unshift( item ); + this.items.unshift( item ); item.on( 'update', this.relayUpdate ); item.attach( this ); this.emit( 'prepend', item ); @@ -160,14 +155,14 @@ es.ModelContainer.prototype.insertBefore = function( item, before ) { var parent = item.parent(); if ( parent === this ) { - this[this._listName].splice( this.indexOf( item ), 1 ); + this.items.splice( this.indexOf( item ), 1 ); } else if ( parent ) { parent.remove( item ); } if ( before ) { - this[this._listName].splice( this[this._listName].indexOf( before ), 0, item ); + this.items.splice( this.items.indexOf( before ), 0, item ); } else { - this[this._listName].unshift( item ); + this.items.unshift( item ); } item.on( 'update', this.relayUpdate ); item.attach( this ); @@ -188,14 +183,14 @@ es.ModelContainer.prototype.insertAfter = function( item, after ) { var parent = item.parent(); if ( parent === this ) { - this[this._listName].splice( this.indexOf( item ), 1 ); + this.items.splice( this.indexOf( item ), 1 ); } else if ( parent ) { parent.remove( item ); } if ( after ) { - this[this._listName].splice( this[this._listName].indexOf( after ) + 1, 0, item ); + this.items.splice( this.items.indexOf( after ) + 1, 0, item ); } else { - this[this._listName].push( item ); + this.items.push( item ); } item.on( 'update', this.relayUpdate ); item.attach( this ); @@ -214,7 +209,7 @@ */ es.ModelContainer.prototype.remove = function( item ) { item.removeListener( 'update', this.relayUpdate ); - this[this._listName].splice( this.indexOf( item ), 1 ); + this.items.splice( this.indexOf( item ), 1 ); item.detach(); this.emit( 'remove', item ); this.emit( 'update' ); Modified: trunk/parsers/wikidom/lib/synth/bases/es.ModelContainerItem.js =================================================================== --- trunk/parsers/wikidom/lib/synth/bases/es.ModelContainerItem.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/bases/es.ModelContainerItem.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -4,22 +4,17 @@ * @class * @constructor * @extends {es.EventEmitter} - * @param containerName {String} Name of container type - * @property [containerName] {Object} Reference to container, if attached + * @property container {Object} Reference to container, if attached */ -es.ModelContainerItem = function( containerName ) { +es.ModelContainerItem = function() { es.EventEmitter.call( this ); - if ( typeof containerName !== 'string' ) { - containerName = 'container'; - } - this._containerName = containerName; - this[this._containerName] = null; + this.container = null; }; /* Methods */ es.ModelContainerItem.prototype.parent = function() { - return this[this._containerName]; + return this.container; }; /** @@ -37,7 +32,7 @@ * @emits "attach" with container argument */ es.ModelContainerItem.prototype.attach = function( container ) { - this[this._containerName] = container; + this.container = container; this.emit( 'attach', container ); }; @@ -48,8 +43,8 @@ * @emits "detach" with container argument */ es.ModelContainerItem.prototype.detach = function() { - var container = this[this._containerName]; - this[this._containerName] = null; + var container = this.container; + this.container = null; this.emit( 'detach', container ); }; @@ -63,7 +58,7 @@ */ es.ModelContainerItem.prototype.getIndex = function() { try { - var index = this[this._containerName].indexOf( this ); + var index = this.container.indexOf( this ); if ( index === -1 ) { throw 'Unknown item error. Can not get index of item that is not in a container. ' + e; } @@ -82,7 +77,7 @@ */ es.ModelContainerItem.prototype.previous = function() { try { - return this[this._containerName].get( this[this._containerName].indexOf( this ) - 1 ); + return this.container.get( this.container.indexOf( this ) - 1 ); } catch ( e ) { throw 'Missing container error. Can not get previous item in missing container. ' + e; } @@ -97,7 +92,7 @@ */ es.ModelContainerItem.prototype.next = function() { try { - return this[this._containerName].get( this[this._containerName].indexOf( this ) + 1 ); + return this.container.get( this.container.indexOf( this ) + 1 ); } catch ( e ) { throw 'Missing container error. Can not get next item in missing container. ' + e; } @@ -112,7 +107,7 @@ */ es.ModelContainerItem.prototype.isFirst = function() { try { - return this[this._containerName].indexOf( this ) === 0; + return this.container.indexOf( this ) === 0; } catch ( e ) { throw 'Missing container error. Can not get index of item in missing container. ' + e; } @@ -127,8 +122,7 @@ */ es.ModelContainerItem.prototype.isLast = function() { try { - return this[this._containerName].indexOf( this ) - === this[this._containerName].getLength() - 1; + return this.container.indexOf( this ) === this.container.getLength() - 1; } catch ( e ) { throw 'Missing container error. Can not get index of item in missing container. ' + e; } Modified: trunk/parsers/wikidom/lib/synth/bases/es.ViewContainer.js =================================================================== --- trunk/parsers/wikidom/lib/synth/bases/es.ViewContainer.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/bases/es.ViewContainer.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -7,19 +7,19 @@ * @class * @constructor * @extends {es.EventEmitter} - * @param containerModel {es.ModelContainer} Property name for list of items + * @param model {es.ModelContainer} Model to follow * @param typeName {String} Name to use in CSS classes and HTML element data * @param tagName {String} HTML element name to use (optional, default: "div") * @property $ {jQuery} Container element - * @property views {Array} List of views, correlating to models in the model container + * @property items {Array} List of views, correlating to models in the model container */ -es.ViewContainer = function( containerModel, typeName, tagName ) { +es.ViewContainer = function( model, typeName, tagName ) { es.EventEmitter.call( this ); - this.containerModel = containerModel; - if ( !this.containerModel ) { + this.model = model; + if ( !this.model ) { return; } - this.views = new es.AggregateArray(); + this.items = new es.AggregateArray(); if ( typeof typeName !== 'string' ) { typeName = 'viewContainer'; } @@ -45,7 +45,7 @@ } return itemView; } - this.containerModel.on( 'prepend', function( itemModel ) { + this.model.on( 'prepend', function( itemModel ) { var itemView = recycleItemView( itemModel, true ); itemView.on( 'update', container.relayUpdate ); container.views.unshift( itemView ); @@ -53,7 +53,7 @@ container.emit( 'prepend', itemView ); container.emit( 'update' ); } ); - this.containerModel.on( 'append', function( itemModel ) { + this.model.on( 'append', function( itemModel ) { var itemView = recycleItemView( itemModel, true ); itemView.on( 'update', container.relayUpdate ); container.views.push( itemView ); @@ -61,7 +61,7 @@ container.emit( 'append', itemView ); container.emit( 'update' ); } ); - this.containerModel.on( 'insertBefore', function( itemModel, beforeModel ) { + this.model.on( 'insertBefore', function( itemModel, beforeModel ) { var beforeView = container.lookupItemView( beforeModel ), itemView = recycleItemView( itemModel, true ); itemView.on( 'update', container.relayUpdate ); @@ -75,7 +75,7 @@ container.emit( 'insertBefore', itemView, beforeView ); container.emit( 'update' ); } ); - this.containerModel.on( 'insertAfter', function( itemModel, afterModel ) { + this.model.on( 'insertAfter', function( itemModel, afterModel ) { var afterView = container.lookupItemView( afterModel ), itemView = recycleItemView( itemModel, true ); itemView.on( 'update', container.relayUpdate ); @@ -89,26 +89,26 @@ container.emit( 'insertAfter', itemView, afterView ); container.emit( 'update' ); } ); - this.containerModel.on( 'remove', function( itemModel ) { + this.model.on( 'remove', function( itemModel ) { var itemView = recycleItemView( itemModel ); itemView.removeListener( 'update', container.relayUpdate ); container.emit( 'remove', itemView ); container.emit( 'update' ); } ); // Auto-add views for existing items - var itemModels = this.containerModel.all(); + var itemModels = this.model.all(); for ( var i = 0; i < itemModels.length; i++ ) { var itemView = itemModels[i].createView(); itemView.on( 'update', container.relayUpdate ); - this.views.push( itemView ); + this.items.push( itemView ); this.$.append( itemView.$ ); } }; es.ViewContainer.prototype.lookupItemView = function( itemModel ) { - for ( var i = 0; i < this.views.length; i++ ) { - if ( this.views[i].getModel() === itemModel ) { - return this.views[i]; + for ( var i = 0; i < this.items.length; i++ ) { + if ( this.items[i].getModel() === itemModel ) { + return this.items[i]; } } return null; Modified: trunk/parsers/wikidom/lib/synth/models/es.DocumentModel.js =================================================================== --- trunk/parsers/wikidom/lib/synth/models/es.DocumentModel.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/models/es.DocumentModel.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -3,14 +3,14 @@ * * @class * @constructor - * @param blocks {Array} + * @param items {Array} * @param attributes {Object} - * @property blocks {Array} + * @property items {Array} * @property attributes {Object} */ es.DocumentModel = function( blocks, attributes ) { - es.ModelContainer.call( this, 'blocks' ); - this.blocks = new es.AggregateArray( blocks || [] ); + es.ModelContainer.call( this ); + this.items = new es.AggregateArray( blocks || [] ); this.attributes = attributes || {}; }; @@ -39,10 +39,10 @@ es.DocumentModel.prototype.getPlainObject = function() { var obj = {}; - if ( this.blocks.length ) { + if ( this.items.length ) { obj.blocks = []; - for ( var i = 0; i < this.blocks.length; i++ ) { - obj.blocks.push( this.blocks[i].getPlainObject() ); + for ( var i = 0; i < this.items.length; i++ ) { + obj.blocks.push( this.items[i].getPlainObject() ); } } if ( !$.isEmptyObject( this.attributes ) ) { @@ -57,7 +57,7 @@ * @returns {Integer} */ es.DocumentModel.prototype.getContentLength = function() { - return this.blocks.getContentLength(); + return this.items.getContentLength(); }; es.extend( es.DocumentModel, es.ModelContainer ); Modified: trunk/parsers/wikidom/lib/synth/models/es.ListBlockItemModel.js =================================================================== --- trunk/parsers/wikidom/lib/synth/models/es.ListBlockItemModel.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/models/es.ListBlockItemModel.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -9,7 +9,7 @@ * @property styles {Array} */ es.ListBlockItemModel = function( content, styles ) { - es.ModelContainerItem.call( this, 'list' ); + es.ModelContainerItem.call( this ); this.content = content || null; this.styles = styles || ['bullet']; }; Modified: trunk/parsers/wikidom/lib/synth/models/es.TableBlockCellModel.js =================================================================== --- trunk/parsers/wikidom/lib/synth/models/es.TableBlockCellModel.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/models/es.TableBlockCellModel.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -9,7 +9,7 @@ * @property attributes {Object} */ es.TableBlockCellModel = function( documentModel, attributes ) { - es.ModelContainerItem.call( this, 'row' ); + es.ModelContainerItem.call( this ); this.documentModel = documentModel || null; this.attributes = attributes || {}; }; Modified: trunk/parsers/wikidom/lib/synth/models/es.TableBlockRowModel.js =================================================================== --- trunk/parsers/wikidom/lib/synth/models/es.TableBlockRowModel.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/models/es.TableBlockRowModel.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -3,18 +3,18 @@ * * @class * @constructor - * @param cells {Array} + * @param items {Array} * @param attributes {Object} - * @property cells {Array} + * @property items {Array} * @property attributes {Object} */ -es.TableBlockRowModel = function( cells, attributes ) { - es.ModelContainerItem.call( this, 'table' ); +es.TableBlockRowModel = function( items, attributes ) { + es.ModelContainerItem.call( this ); es.ModelContainer.call( this ); - if ( $.isArray( cells ) ) { - for ( var i = 0; i < cells.length; i++ ) { - this.append( cells[i] ); + if ( $.isArray( items ) ) { + for ( var i = 0; i < items.length; i++ ) { + this.append( items[i] ); } } @@ -56,7 +56,7 @@ * @returns {Integer} Length of all content */ es.TableBlockRowModel.prototype.getContentLength = function() { - return this.cells.getContentLength(); + return this.items.getContentLength(); }; /** @@ -68,9 +68,9 @@ es.TableBlockRowModel.prototype.getPlainObject = function() { /* var obj = {}; - if ( this.cells.length ) { - obj.cells = $.map( this.cells, function( cell ) { - return cell.getPlainObject(); + if ( this.items.length ) { + obj.cells = $.map( this.items, function( item ) { + return item.getPlainObject(); } ); } if ( !$.isEmptyObject( this.attributes ) ) { @@ -83,4 +83,4 @@ /* Inheritance */ es.extend( es.TableBlockRowModel, es.ModelContainerItem ); -es.extend( es.TableBlockRowModel, es.ModelContainer ); \ No newline at end of file +es.extend( es.TableBlockRowModel, es.ModelContainer ); Modified: trunk/parsers/wikidom/lib/synth/views/es.DocumentView.js =================================================================== --- trunk/parsers/wikidom/lib/synth/views/es.DocumentView.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/views/es.DocumentView.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -12,13 +12,13 @@ * Render content. */ es.DocumentView.prototype.renderContent = function() { - for ( var i = 0; i < this.views.length; i++ ) { - this.views[i].renderContent(); + for ( var i = 0; i < this.items.length; i++ ) { + this.items[i].renderContent(); } }; es.DocumentView.prototype.drawSelection = function( range ) { - var selectedViews = this.views.select( range ); + var selectedViews = this.items.select( range ); for ( var i = 0; i < selectedViews.length; i++ ) { selectedViews[i].item.drawSelection( new es.Range( selectedViews[i].from, selectedViews[i].to ) @@ -27,7 +27,7 @@ }; es.DocumentView.prototype.getLength = function( ) { - return this.views.getLengthOfItems(); + return this.items.getLengthOfItems(); }; /** @@ -37,11 +37,11 @@ * @returns {String} HTML data */ es.DocumentView.prototype.getHtml = function() { - var views = this.views; + var views = this.items; return es.Html.makeTag( 'div', { 'class': this.$.attr( 'class' ) }, - $.map( this.views, function( view, i ) { + $.map( this.items, function( view, i ) { return view.getHtml( { 'singular': i === 0 && views.length == 1 } ); } ).join( '' ) ); Modified: trunk/parsers/wikidom/lib/synth/views/es.ListBlockView.js =================================================================== --- trunk/parsers/wikidom/lib/synth/views/es.ListBlockView.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/views/es.ListBlockView.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -17,8 +17,8 @@ * Render content. */ es.ListBlockView.prototype.renderContent = function() { - for ( var i = 0; i < this.views.length; i++ ) { - this.views[i].renderContent(); + for ( var i = 0; i < this.items.length; i++ ) { + this.items[i].renderContent(); } }; @@ -26,14 +26,14 @@ var itemLevel, levels = []; - for ( var i = 0; i < this.views.length; i++ ) { - itemLevel = this.views[i].model.getLevel(); + for ( var i = 0; i < this.items.length; i++ ) { + itemLevel = this.items[i].model.getLevel(); levels = levels.slice(0, itemLevel + 1); - if ( this.views[i].model.getStyle() === 'number' ) { + if ( this.items[i].model.getStyle() === 'number' ) { if ( !levels[itemLevel] ) { levels[itemLevel] = 0; } - this.views[i].setNumber( ++levels[itemLevel] ); + this.items[i].setNumber( ++levels[itemLevel] ); } } }; @@ -64,7 +64,7 @@ }; es.ListBlockView.prototype.drawSelection = function( range ) { - var selectedViews = this.views.select( range ); + var selectedViews = this.items.select( range ); for ( var i = 0; i < selectedViews.length; i++ ) { selectedViews[i].item.drawSelection( new es.Range( selectedViews[i].from, selectedViews[i].to ) @@ -83,7 +83,7 @@ return es.Html.makeTag( 'div', { 'class': this.$.attr( 'class' ) }, - $.map( this.views, function( view ) { + $.map( this.items, function( view ) { return view.getHtml(); } ).join( '' ) ); Modified: trunk/parsers/wikidom/lib/synth/views/es.TableBlockRowView.js =================================================================== --- trunk/parsers/wikidom/lib/synth/views/es.TableBlockRowView.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/views/es.TableBlockRowView.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -19,17 +19,17 @@ * Render content. */ es.TableBlockRowView.prototype.renderContent = function() { - for ( var i = 0; i < this.views.length; i++ ) { - this.views[i].renderContent(); + for ( var i = 0; i < this.items.length; i++ ) { + this.items[i].renderContent(); } }; es.TableBlockRowView.prototype.getLength = function() { - return this.views.getLengthOfItems(); + return this.items.getLengthOfItems(); }; es.TableBlockRowView.prototype.drawSelection = function( range ) { - var selectedViews = this.views.select( range ); + var selectedViews = this.items.select( range ); for ( var i = 0; i < selectedViews.length; i++ ) { selectedViews[i].item.drawSelection( new es.Range( selectedViews[i].from, selectedViews[i].to ) @@ -45,7 +45,7 @@ * @returns {String} HTML data */ es.TableBlockRowView.prototype.getHtml = function( options ) { - return es.Html.makeTag( 'tr', this.model.attributes, $.map( this.views, function( view ) { + return es.Html.makeTag( 'tr', this.model.attributes, $.map( this.items, function( view ) { return view.getHtml(); } ).join( '' ) ); }; Modified: trunk/parsers/wikidom/lib/synth/views/es.TableBlockView.js =================================================================== --- trunk/parsers/wikidom/lib/synth/views/es.TableBlockView.js 2011-09-16 17:58:50 UTC (rev 97301) +++ trunk/parsers/wikidom/lib/synth/views/es.TableBlockView.js 2011-09-16 18:04:03 UTC (rev 97302) @@ -19,17 +19,17 @@ * Render content. */ es.TableBlockView.prototype.renderContent = function() { - for ( var i = 0; i < this.views.length; i++ ) { - this.views[i].renderContent(); + for ( var i = 0; i < this.items.length; i++ ) { + this.items[i].renderContent(); } }; es.TableBlockView.prototype.getLength = function() { - return this.views.getLengthOfItems(); + return this.items.getLengthOfItems(); }; es.TableBlockView.prototype.drawSelection = function( range ) { - var selectedViews = this.views.select( range ); + var selectedViews = this.items.select( range ); for ( var i = 0; i < selectedViews.length; i++ ) { selectedViews[i].item.drawSelection( new es.Range( selectedViews[i].from, selectedViews[i].to ) @@ -45,7 +45,7 @@ * @returns {String} HTML data */ es.TableBlockView.prototype.getHtml = function( options ) { - return es.Html.makeTag( 'table', this.model.attributes, $.map( this.views, function( view ) { + return es.Html.makeTag( 'table', this.model.attributes, $.map( this.items, function( view ) { return view.getHtml(); } ).join( '' ) ); }; _______________________________________________ MediaWiki-CVS mailing list MediaWiki-CVS@lists.wikimedia.org https://lists.wikimedia.org/mailman/listinfo/mediawiki-cvs