jenkins-bot has submitted this change and it was merged.
Change subject: First implementation of the support of the <pages> tag in the
VisualEditor
......................................................................
First implementation of the support of the <pages> tag in the VisualEditor
Depends-On: I633c521859b59614835344a4644560ac933c6028
Depends-On: Ia3533d89a94f4451c45deb0d89770d358fb2612a
Change-Id: I876c902c7c8331617ddcdb23e3dc04c7f16224dd
---
M .jshintrc
M ProofreadPage.php
M i18n/en.json
M i18n/qqq.json
A modules/ve/node/ve.ce.MWPagesNode.js
A modules/ve/node/ve.dm.MWPagesNode.js
A modules/ve/node/ve.ui.MWPagesInspector.js
A modules/ve/node/ve.ui.MWPagesInspectorTool.js
8 files changed, 381 insertions(+), 4 deletions(-)
Approvals:
Esanders: Looks good to me, approved
jenkins-bot: Verified
diff --git a/.jshintrc b/.jshintrc
index 27e9c99..1a54bf2 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -2,7 +2,6 @@
// Enforcing
"bitwise": true,
"eqeqeq": true,
- "es3": true,
"freeze": true,
"latedef": true,
"noarg": true,
@@ -15,6 +14,8 @@
"browser": true,
"globals": {
- "mw": false
+ "mw": false,
+ "OO": false,
+ "ve": false
}
}
diff --git a/ProofreadPage.php b/ProofreadPage.php
index e22ff49..cadbc58 100644
--- a/ProofreadPage.php
+++ b/ProofreadPage.php
@@ -202,8 +202,27 @@
'styles' =>
'special/indexpages/ext.proofreadpage.special.indexpages.css',
'dependencies' => array( 'ext.proofreadpage.base' )
),
+ 'ext.proofreadpage.ve.node.pages' => $prpResourceTemplate + array(
+ 'scripts' => array(
+ 've/node/ve.dm.MWPagesNode.js',
+ 've/node/ve.ce.MWPagesNode.js',
+ 've/node/ve.ui.MWPagesInspector.js',
+ 've/node/ve.ui.MWPagesInspectorTool.js'
+ ),
+ 'dependencies' => array( 'ext.visualEditor.mwcore' ),
+ 'messages' => array(
+
'proofreadpage-visualeditor-node-pages-inspector-tooltip',
+ 'proofreadpage-visualeditor-node-pages-inspector-title',
+
'proofreadpage-visualeditor-node-pages-inspector-description',
+
'proofreadpage-visualeditor-node-pages-inspector-indexselector-yes',
+
'proofreadpage-visualeditor-node-pages-inspector-indexselector-no'
+ ),
+ 'targets' => array( 'desktop', 'mobile' )
+ ),
);
+$wgVisualEditorPluginModules[] = 'ext.proofreadpage.ve.node.pages';
+
//Hooks
$wgHooks['SetupAfterCache'][] =
'ProofreadPage\ProofreadPageInit::initNamespaces';
$wgHooks['ParserFirstCallInit'][] = 'ProofreadPage::onParserFirstCallInit';
diff --git a/i18n/en.json b/i18n/en.json
index 0551bc2..0ab3df1 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -84,5 +84,10 @@
"apihelp-query+proofreadinfo-description": "Return information about
configuration of ProofreadPage extension.",
"apihelp-query+proofreadinfo-param-prop": "Which proofread properties
to get:\n;namespaces:Information about \"{{ns:Page}}\" and \"{{ns:Index}}\"
namespaces.\n;qualitylevels:List of proofread quality levels.",
"apihelp-query+proofreadinfo-example-1": "Return default information",
- "apihelp-query+proofreadinfo-example-3": "Return namespace information"
+ "apihelp-query+proofreadinfo-example-3": "Return namespace information",
+ "proofreadpage-visualeditor-node-pages-inspector-title": "Page
selection",
+ "proofreadpage-visualeditor-node-pages-inspector-tooltip": "Pages",
+ "proofreadpage-visualeditor-node-pages-inspector-description":
"Transclusion of $1",
+ "proofreadpage-visualeditor-node-pages-inspector-indexselector-yes":
"Yes",
+ "proofreadpage-visualeditor-node-pages-inspector-indexselector-no": "No"
}
diff --git a/i18n/qqq.json b/i18n/qqq.json
index b455a4c..d31bcd6 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -106,5 +106,10 @@
"apihelp-query+proofreadinfo-description":
"{{doc-apihelp-description|query+proofreadinfo}}",
"apihelp-query+proofreadinfo-param-prop": "Use \"{{ns:Page}}\" and
\"{{ns:Index}}\" with quotes instead of Page and Index
namespaces.\n\n{{doc-apihelp-param|query+proofreadinfo|prop}}",
"apihelp-query+proofreadinfo-example-1":
"{{doc-apihelp-example|query+proofreadinfo}}",
- "apihelp-query+proofreadinfo-example-3":
"{{doc-apihelp-example|query+proofreadinfo}}"
+ "apihelp-query+proofreadinfo-example-3":
"{{doc-apihelp-example|query+proofreadinfo}}",
+ "proofreadpage-visualeditor-node-pages-inspector-tooltip": "Title for
the inspector to edit <nowiki><pages></nowiki> blocks.",
+ "proofreadpage-visualeditor-node-pages-inspector-title": "Title of the
button to open the inspector to edit <nowiki><pages></nowiki> blocks.",
+ "proofreadpage-visualeditor-node-pages-inspector-description":
"Description of the inspector to edit <nowiki><pages></nowiki> blocks.\n$1 is
the title of the transcluded index (like 'My nice book.djvu').",
+ "proofreadpage-visualeditor-node-pages-inspector-indexselector-yes":
"Label of the option that allows to include an header on top of the transluded
pages.",
+ "proofreadpage-visualeditor-node-pages-inspector-indexselector-no":
"Label of the option that disallows to include an header on top of the
transluded pages."
}
diff --git a/modules/ve/node/ve.ce.MWPagesNode.js
b/modules/ve/node/ve.ce.MWPagesNode.js
new file mode 100644
index 0000000..0d1b448
--- /dev/null
+++ b/modules/ve/node/ve.ce.MWPagesNode.js
@@ -0,0 +1,37 @@
+/**
+ * ContentEditable MediaWiki pages node.
+ *
+ * @class
+ * @extends ve.ce.MWBlockExtensionNode
+ *
+ * @constructor
+ */
+ve.ce.MWPagesNode = function VeCeMWPagesNode() {
+ ve.ce.MWPagesNode.super.apply( this, arguments );
+};
+
+/* Inheritance */
+OO.inheritClass( ve.ce.MWPagesNode, ve.ce.MWBlockExtensionNode );
+
+/* Static Properties */
+ve.ce.MWPagesNode.static.name = 'mwPages';
+
+ve.ce.MWPagesNode.static.tagName = 'div';
+
+ve.ce.MWPagesNode.static.primaryCommandName = 'pages';
+
+ve.ce.MWPagesNode.static.iconWhenInvisible = 'article';
+
+ve.ce.MWPagesNode.static.rendersEmpty = true;
+
+/* Methods */
+/**
+ * @inheritdoc
+ */
+ve.ce.MWPagesNode.static.getDescription = function ( model ) {
+ var indexTitle = new mw.Title( model.getIndexName() );
+ return ve.msg(
'proofreadpage-visualeditor-node-pages-inspector-description',
indexTitle.getNameText() );
+};
+
+/* Registration */
+ve.ce.nodeFactory.register( ve.ce.MWPagesNode );
diff --git a/modules/ve/node/ve.dm.MWPagesNode.js
b/modules/ve/node/ve.dm.MWPagesNode.js
new file mode 100644
index 0000000..f8542b0
--- /dev/null
+++ b/modules/ve/node/ve.dm.MWPagesNode.js
@@ -0,0 +1,32 @@
+/**
+ * DataModel MediaWiki pages node.
+ *
+ * @class
+ * @extends ve.dm.MWBlockExtensionNode
+ *
+ * @constructor
+ */
+ve.dm.MWPagesNode = function VeDmMWPagesNode() {
+ ve.dm.MWPagesNode.super.apply( this, arguments );
+};
+
+/* Inheritance */
+OO.inheritClass( ve.dm.MWPagesNode, ve.dm.MWBlockExtensionNode );
+
+/* Static Properties */
+ve.dm.MWPagesNode.static.name = 'mwPages';
+
+ve.dm.MWPagesNode.static.tagName = 'div';
+
+ve.dm.MWPagesNode.static.extensionName = 'pages';
+
+/* Methods */
+/**
+ * @return {string} Index name
+ */
+ve.dm.MWPagesNode.prototype.getIndexName = function () {
+ return this.getAttribute( 'mw' ).attrs.index || '';
+};
+
+/* Registration */
+ve.dm.modelRegistry.register( ve.dm.MWPagesNode );
diff --git a/modules/ve/node/ve.ui.MWPagesInspector.js
b/modules/ve/node/ve.ui.MWPagesInspector.js
new file mode 100644
index 0000000..fc0d44e
--- /dev/null
+++ b/modules/ve/node/ve.ui.MWPagesInspector.js
@@ -0,0 +1,244 @@
+/**
+ * mw pages tag inspector.
+ *
+ * @class
+ * @extends ve.ui.MWExtensionInspector
+ *
+ * @constructor
+ */
+ve.ui.MWPagesInspector = function VeUiMWPagesInspector() {
+ ve.ui.MWPagesInspector.super.apply( this, arguments );
+};
+
+/* Inheritance */
+OO.inheritClass( ve.ui.MWPagesInspector, ve.ui.MWExtensionInspector );
+
+/* Static properties */
+ve.ui.MWPagesInspector.static.name = 'pages';
+
+ve.ui.MWPagesInspector.static.icon = 'article';
+
+ve.ui.MWPagesInspector.static.title = OO.ui.deferMsg(
'proofreadpage-visualeditor-node-pages-inspector-title' );
+
+ve.ui.MWPagesInspector.static.modelClasses = [ ve.dm.MWPagesNode ];
+
+ve.ui.MWPagesInspector.static.allowedEmpty = true;
+
+ve.ui.MWPagesInspector.static.delayForIndexInput = 2000;
+
+/* Methods */
+/**
+ * @inheritdoc
+ */
+ve.ui.MWPagesInspector.prototype.initialize = function () {
+ this.constructor.super.prototype.initialize.apply( this, arguments );
+
+ this.attributeInputs = {};
+ this.$attributes = $( '<div>' );
+ this.form.$element.append( this.$attributes );
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.MWPagesInspector.prototype.getSetupProcess = function ( data ) {
+ return this.constructor.super.prototype.getSetupProcess.call( this,
data )
+ .next( function () {
+ this.mwData = ( this.selectedNode !== null &&
this.selectedNode.getAttribute( 'mw' ) ) || {
+ attrs: {}
+ };
+
+ this.setupForm();
+
+ // Hide the tag content if possible
+ if ( this.input.getValue().trim() === '' ) {
+ this.input.toggle( false );
+ }
+ }, this );
+};
+
+/**
+ * Creates the inspector form using the current data stored in this.mwData
+ */
+ve.ui.MWPagesInspector.prototype.setupForm = function () {
+ var key,
+ attributes = this.mwData.attrs,
+ inspector = this;
+
+ this.pushPending();
+ this.getFileInfo( attributes.index ).done( function ( imageInfo ) {
+ inspector.addAttributeToWidget( inspector.createIndexWidget(),
'index' );
+
+ inspector.addAttributeToWidget( new OO.ui.DropdownInputWidget( {
+ options: inspector.buildHeaderFieldSelectorOptions(
attributes.header )
+ } ), 'header' );
+
+ if ( imageInfo.pagecount !== undefined ) {
+ inspector.addAttributeToWidget( new
OO.ui.NumberInputWidget( {
+ isInteger: true,
+ min: 1,
+ max: imageInfo.pagecount
+ } ), 'from' );
+ inspector.addAttributeToWidget( new
OO.ui.NumberInputWidget( {
+ isInteger: true,
+ min: 1,
+ max: imageInfo.pagecount
+ } ), 'to' );
+ } else {
+ inspector.addAttributeToWidget( new
mw.widgets.TitleInputWidget( {
+ namespace: inspector.getIdForNamespace( 'page' )
+ } ), 'from' );
+ inspector.addAttributeToWidget( new
mw.widgets.TitleInputWidget( {
+ namespace: inspector.getIdForNamespace( 'page' )
+ } ), 'to' );
+ }
+
+ inspector.addAttributeToWidget( new OO.ui.TextInputWidget(),
'fromsection' );
+ inspector.addAttributeToWidget( new OO.ui.TextInputWidget(),
'tosection' );
+
+ for ( key in attributes ) {
+ if ( key in inspector.attributeInputs ) {
+ inspector.attributeInputs[ key ].setValue(
attributes[ key ] );
+ } else {
+ inspector.addAttributeToWidget( new
OO.ui.TextInputWidget( {
+ value: attributes[ key ]
+ } ), key );
+ }
+ }
+
+ inspector.updateSize();
+ inspector.popPending();
+ } );
+};
+
+/**
+ * @return {mw.widgets.TitleInputWidget}
+ */
+ve.ui.MWPagesInspector.prototype.createIndexWidget = function () {
+ return new mw.widgets.TitleInputWidget( {
+ namespace: this.getIdForNamespace( 'index' ),
+ required: true
+ } ).connect( this, {
+ change: OO.ui.debounce( this.onIndexChange.bind( this ),
this.constructor.static.delayForIndexInput )
+ } );
+};
+
+/**
+ * @param {string} namespaceName the name of the namespace like "Index" or
"Page"
+ * @return {int} the namespace id like 252
+ */
+ve.ui.MWPagesInspector.prototype.getIdForNamespace = function ( namespaceName
) {
+ var namespaceIds = mw.config.get( 'wgNamespaceIds' );
+
+ if ( namespaceName in namespaceIds ) {
+ return namespaceIds[ namespaceName ];
+ } else {
+ throw new Error( 'Unknown id for the ' + namespaceName + ':
namespace' );
+ }
+};
+
+/**
+ * Builds the options for the header field dropdown
+ *
+ * @param {string|undefined} headerValue the current value of the header field
+ * @return {Object[]}
+ */
+ve.ui.MWPagesInspector.prototype.buildHeaderFieldSelectorOptions = function (
headerValue ) {
+ var headerInputOptions = [
+ { data: '', label: OO.ui.msg(
'proofreadpage-visualeditor-node-pages-inspector-indexselector-no' ) },
+ { data: '1', label: OO.ui.msg(
'proofreadpage-visualeditor-node-pages-inspector-indexselector-yes' ) }
+ ];
+ if ( [ '', '1' ].indexOf( headerValue ) === -1 ) {
+ headerInputOptions.push( { data: headerValue, label:
headerValue } );
+ }
+ return headerInputOptions;
+};
+
+/**
+ * Get info about the file
+ *
+ * @param {string} fileName like "test.djvu"
+ * @return {jQuery.Promise} information about the file like {size: 222,
pagecount: 1}. Always resolves
+ */
+ve.ui.MWPagesInspector.prototype.getFileInfo = function ( fileName ) {
+ if ( fileName !== '' ) {
+ return ( new mw.Api() ).get( {
+ action: 'query',
+ prop: 'imageinfo',
+ titles: 'File:' + fileName,
+ iiprop: 'size',
+ indexpageids: 1
+ } ).then( function ( data ) {
+ var file = data.query.pages[ data.query.pageids[ 0 ] ];
+ return file.imageinfo && file.imageinfo[ 0 ] || {};
+ }, function () {
+ return $.Deferred().resolve( {} );
+ } );
+ } else {
+ return $.Deferred().resolve( {} );
+ }
+};
+
+/**
+ * Adds to the inspector an input for a <pages> tag parameter
+ *
+ * @param {OO.ui.Widget} attributeInput
+ * @param {string} attributeKey the key of the attribute like "from"
+ */
+ve.ui.MWPagesInspector.prototype.addAttributeToWidget = function (
attributeInput, attributeKey ) {
+ var field = new OO.ui.FieldLayout(
+ attributeInput,
+ {
+ align: 'left',
+ label: attributeKey
+ }
+ );
+ this.$attributes.append( field.$element );
+ this.attributeInputs[ attributeKey ] = attributeInput;
+};
+
+/**
+ * Event callback when the index field changes
+ */
+ve.ui.MWPagesInspector.prototype.onIndexChange = function () {
+ if ( this.attributeInputs.index &&
this.attributeInputs.index.getValue() !== this.mwData.attrs.index ) {
+ this.updateMwData( this.mwData );
+ this.teardownForm();
+ this.setupForm();
+ }
+};
+
+/**
+ * Removes the inspector form
+ */
+ve.ui.MWPagesInspector.prototype.teardownForm = function () {
+ this.$attributes.empty();
+ this.attributeInputs = {};
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.MWPagesInspector.prototype.getTeardownProcess = function ( data ) {
+ return this.constructor.super.prototype.getTeardownProcess.call( this,
data )
+ .next( function () {
+ this.teardownForm();
+ }, this );
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ui.MWPagesInspector.prototype.updateMwData = function ( mwData ) {
+ var key;
+
+ this.constructor.super.prototype.updateMwData.call( this, mwData );
+
+ mwData.attrs = mwData.attrs || {};
+ for ( key in this.attributeInputs ) {
+ mwData.attrs[ key ] = this.attributeInputs[ key ].getValue();
+ }
+};
+
+/* Registration */
+ve.ui.windowFactory.register( ve.ui.MWPagesInspector );
diff --git a/modules/ve/node/ve.ui.MWPagesInspectorTool.js
b/modules/ve/node/ve.ui.MWPagesInspectorTool.js
new file mode 100644
index 0000000..99c5936
--- /dev/null
+++ b/modules/ve/node/ve.ui.MWPagesInspectorTool.js
@@ -0,0 +1,34 @@
+/**
+ * MediaWiki UserInterface pages tool.
+ *
+ * @class
+ * @extends ve.ui.FragmentInspectorTool
+ *
+ * @constructor
+ */
+ve.ui.MWPagesInspectorTool = function VeUiMWPagesInspectorTool() {
+ ve.ui.MWPagesInspectorTool.super.apply( this, arguments );
+};
+
+/* Inheritance */
+OO.inheritClass( ve.ui.MWPagesInspectorTool, ve.ui.FragmentInspectorTool );
+
+/* Static properties */
+ve.ui.MWPagesInspectorTool.static.name = 'pages';
+
+ve.ui.MWPagesInspectorTool.static.group = 'object';
+
+ve.ui.MWPagesInspectorTool.static.icon = 'article';
+
+ve.ui.MWPagesInspectorTool.static.title = OO.ui.deferMsg(
'proofreadpage-visualeditor-node-pages-inspector-tooltip' );
+
+ve.ui.MWPagesInspectorTool.static.modelClasses = [ ve.dm.MWPagesNode ];
+
+ve.ui.MWPagesInspectorTool.static.commandName = 'pages';
+
+/* Registration */
+ve.ui.toolFactory.register( ve.ui.MWPagesInspectorTool );
+
+ve.ui.commandRegistry.register(
+ new ve.ui.Command( 'pages', 'window', 'open', { args: [ 'pages' ] } )
+);
--
To view, visit https://gerrit.wikimedia.org/r/152028
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: I876c902c7c8331617ddcdb23e3dc04c7f16224dd
Gerrit-PatchSet: 14
Gerrit-Project: mediawiki/extensions/ProofreadPage
Gerrit-Branch: master
Gerrit-Owner: Tpt <[email protected]>
Gerrit-Reviewer: Catrope <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: GOIII <[email protected]>
Gerrit-Reviewer: Jforrester <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: Tpt <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits