jenkins-bot has submitted this change and it was merged.

Change subject: Render Vega specifications inside VisualEditor
......................................................................


Render Vega specifications inside VisualEditor

* Declared a new MWGraphNode, which listens for <graph> tags in wiki pages
* Renders Vega inside based on the JSON contained within the tag

Bug: T99936
Change-Id: I66ff1d3574813daea22274777261b02d8b18b513
---
M .jshintrc
A Graph.hooks.php
M Gruntfile.js
M extension.json
M i18n/en.json
M i18n/qqq.json
A modules/ve-graph/ve.ce.MWGraphNode.js
A modules/ve-graph/ve.dm.MWGraphNode.js
8 files changed, 277 insertions(+), 7 deletions(-)

Approvals:
  Mooeypoo: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/.jshintrc b/.jshintrc
index 10bb722..c198255 100644
--- a/.jshintrc
+++ b/.jshintrc
@@ -2,7 +2,6 @@
        // Enforcing
        "bitwise": true,
        "eqeqeq": true,
-       "es3": true,
        "freeze": true,
        "latedef": true,
        "noarg": true,
@@ -11,12 +10,17 @@
        "unused": true,
        "strict": false,
 
+       // Relaxing
+       "es5": false,
+
        // Environment
        "browser": true,
        "jquery": true,
 
        "globals": {
-               "mediaWiki": true,
-               "vg": true
+               "mediaWiki": false,
+               "OO": false,
+               "ve": false,
+               "vg": false
        }
 }
diff --git a/Graph.hooks.php b/Graph.hooks.php
new file mode 100644
index 0000000..4a37c92
--- /dev/null
+++ b/Graph.hooks.php
@@ -0,0 +1,47 @@
+<?php
+/**
+ * Graph extension Hooks
+ *
+ * @file
+ * @ingroup Extensions
+ */
+
+class GraphHooks {
+       /**
+        * Conditionally register the ext.graph.VisualEditor module if 
VisualEditor
+        * has been loaded
+        *
+        * @param ResourceLoader $resourceLoader
+        * @return boolean true
+        */
+       public static function onResourceLoaderRegisterModules( ResourceLoader 
&$resourceLoader ) {
+               $resourceModules = $resourceLoader->getConfig()->get( 
'ResourceModules' );
+
+               $graphModuleTemplate = array(
+                       'localBasePath' => __DIR__,
+                       'remoteExtPath' => 'Graph'
+               );
+
+               $addModules = array(
+                       'ext.graph.visualEditor' => $graphModuleTemplate + 
array(
+                               'scripts' => array(
+                                       'modules/ve-graph/ve.dm.MWGraphNode.js',
+                                       'modules/ve-graph/ve.ce.MWGraphNode.js'
+                               ),
+                               'dependencies' => array(
+                                       'ext.visualEditor.mwcore',
+                                       'ext.graph'
+                               ),
+                               'messages' => array(
+                                       'graph-ve-no-spec'
+                               )
+                       )
+               );
+
+               if ( isset( $resourceModules[ 'ext.visualEditor.mwcore' ] ) || 
$resourceLoader->isModuleRegistered( 'ext.visualEditor.mwcore' ) ) {
+                       $resourceLoader->register( $addModules );
+               }
+
+               return true;
+       }
+}
diff --git a/Gruntfile.js b/Gruntfile.js
index e692d27..e8e5d84 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -20,7 +20,8 @@
                                jshintrc: true
                        },
                        all: [
-                               'js/*.js'
+                               'js/*.js',
+                               'modules/ve-graph/*.js'
                        ]
                },
                jscs: {
diff --git a/extension.json b/extension.json
index a142778..7ee5283 100644
--- a/extension.json
+++ b/extension.json
@@ -15,7 +15,8 @@
        },
        "AutoloadClasses": {
                "Graph\\Singleton": "Graph.body.php",
-               "Graph\\Content": "Graph.body.php"
+               "Graph\\Content": "Graph.body.php",
+               "GraphHooks": "Graph.hooks.php"
        },
        "ResourceModules": {
                "ext.graph": {
@@ -59,8 +60,14 @@
                ],
                "ParserAfterParse": [
                        "Graph\\Singleton::onParserAfterParse"
+               ],
+               "ResourceLoaderRegisterModules": [
+                       "GraphHooks::onResourceLoaderRegisterModules"
                ]
        },
+       "VisualEditorPluginModules": [
+               "ext.graph.visualEditor"
+       ],
        "config": {
                "GraphDataDomains": [],
                "GraphUrlBlacklist": false,
diff --git a/i18n/en.json b/i18n/en.json
index 5401583..2a8a457 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -5,5 +5,6 @@
                        "Yuri Astrakhan"
                ]
        },
-       "graph-desc": "Allows &lt;graph> tags or entire pages to become 
[http://trifacta.github.io/vega/ Vega]-based graphs"
+       "graph-desc": "Allows &lt;graph&gt; tags or entire pages to become 
[http://trifacta.github.io/vega/ Vega]-based graphs",
+       "graph-ve-no-spec": "No graph specification found"
 }
diff --git a/i18n/qqq.json b/i18n/qqq.json
index 5f498bc..8d73ea5 100644
--- a/i18n/qqq.json
+++ b/i18n/qqq.json
@@ -5,5 +5,6 @@
                        "Mormegil"
                ]
        },
-       "graph-desc": 
"{{desc|name=Graph|url=https://www.mediawiki.org/wiki/Extension:Graph}}";
+       "graph-desc": 
"{{desc|name=Graph|url=https://www.mediawiki.org/wiki/Extension:Graph}}";,
+       "graph-ve-no-spec": "Label to display on a graph node when no spec is 
found"
 }
diff --git a/modules/ve-graph/ve.ce.MWGraphNode.js 
b/modules/ve-graph/ve.ce.MWGraphNode.js
new file mode 100644
index 0000000..b188fdc
--- /dev/null
+++ b/modules/ve-graph/ve.ce.MWGraphNode.js
@@ -0,0 +1,91 @@
+/*!
+ * VisualEditor ContentEditable MWGraphNode class.
+ *
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * ContentEditable MediaWiki graph node.
+ *
+ * @class
+ * @extends ve.ce.MWBlockExtensionNode
+ *
+ * @constructor
+ * @param {ve.dm.MWGraphNode} model Model to observe
+ * @param {Object} [config] Configuration options
+ */
+ve.ce.MWGraphNode = function VeCeMWGraphNode() {
+       // Parent constructor
+       ve.ce.MWGraphNode.super.apply( this, arguments );
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.ce.MWGraphNode, ve.ce.MWBlockExtensionNode );
+
+/* Static Properties */
+
+ve.ce.MWGraphNode.static.name = 'mwGraph';
+
+ve.ce.MWGraphNode.static.primaryCommandName = 'graph';
+
+/* Methods */
+
+/**
+ * @inheritdoc
+ */
+ve.ce.MWGraphNode.prototype.onSetup = function () {
+       // Parent method
+       ve.ce.MWGraphNode.super.prototype.onSetup.call( this );
+
+       // Events
+       this.getModel().connect( this, {
+               specChange: 'onSpecChange'
+       } );
+
+       // Initial rendering
+       this.renderGraph();
+};
+
+/**
+ * @inheritdoc
+ */
+ve.ce.MWGraphNode.prototype.onTeardown = function () {
+       // Parent method
+       ve.ce.MWGraphNode.super.prototype.onTeardown.call( this );
+
+       // Events
+       this.getModel().disconnect( this );
+};
+
+/**
+ * Render a Vega graph inside the node
+ *
+ * @private
+ */
+ve.ce.MWGraphNode.prototype.renderGraph = function () {
+       var element = this.$element[0],
+               spec = this.getModel().getSpec();
+
+       // Check if the spec is currently valid
+       if ( spec !== null ) {
+               vg.parse.spec( spec, function ( chart ) {
+                       chart( { el: element } ).update();
+               } );
+       } else {
+               $( element ).text( ve.msg( 'graph-ve-no-spec' ) );
+       }
+};
+
+/**
+ * React to specification model update
+ *
+ * @private
+ */
+ve.ce.MWGraphNode.prototype.onSpecChange = function () {
+       this.renderGraph();
+};
+
+/* Registration */
+
+ve.ce.nodeFactory.register( ve.ce.MWGraphNode );
diff --git a/modules/ve-graph/ve.dm.MWGraphNode.js 
b/modules/ve-graph/ve.dm.MWGraphNode.js
new file mode 100644
index 0000000..2202a85
--- /dev/null
+++ b/modules/ve-graph/ve.dm.MWGraphNode.js
@@ -0,0 +1,118 @@
+/*!
+ * VisualEditor DataModel MWGraphNode class.
+ *
+ * @license The MIT License (MIT); see LICENSE.txt
+ */
+
+/**
+ * DataModel MediaWiki graph node.
+ *
+ * @class
+ * @extends ve.dm.MWBlockExtensionNode
+ *
+ * @constructor
+ * @param {Object} [element]
+ */
+ve.dm.MWGraphNode = function VeDmMWGraphNode() {
+       var mw, extsrc;
+
+       // Parent constructor
+       ve.dm.MWGraphNode.super.apply( this, arguments );
+
+       // Properties
+       this.spec = null;
+
+       // Initialize specificiation
+       mw = this.getAttribute( 'mw' );
+       extsrc = ve.getProp( mw, 'body', 'extsrc' );
+
+       if ( extsrc !== undefined ) {
+               this.setSpecFromString( extsrc );
+       }
+};
+
+/* Inheritance */
+
+OO.inheritClass( ve.dm.MWGraphNode, ve.dm.MWBlockExtensionNode );
+
+/* Static Members */
+
+ve.dm.MWGraphNode.static.name = 'mwGraph';
+
+ve.dm.MWGraphNode.static.tagName = 'graph';
+
+ve.dm.MWGraphNode.static.extensionName = 'graph';
+
+/* Events */
+
+/**
+ * @event specChange
+ *
+ * Change when the specification object is updated
+ *
+ * @param {Object} The new specification object
+ */
+
+/* Static Methods */
+
+/**
+ * Parses a spec string and returns its object representation.
+ *
+ * @param {string} str The spec string to validate
+ * @return {Object|null} The object specification if the parsing was 
successful, null otherwise
+ */
+ve.dm.MWGraphNode.static.parseSpecString = function ( str ) {
+       try {
+               return JSON.parse( str );
+       } catch ( err ) {
+               return null;
+       }
+};
+
+/* Methods */
+
+/**
+ * Get the specification string
+ *
+ * @return {string} The specification JSON string
+ */
+ve.dm.MWGraphNode.prototype.getSpecString = function () {
+       return JSON.stringify( this.spec, null, '\t' );
+};
+
+/**
+ * Get the parsed JSON specification
+ *
+ * @return {Object} The specification object
+ */
+ve.dm.MWGraphNode.prototype.getSpec = function () {
+       return this.spec;
+};
+
+/**
+ * Update the spec with new parameters
+ *
+ * @param {Object} params The new parameters to be updated in the spec
+ * @fires specChange
+ */
+ve.dm.MWGraphNode.prototype.updateSpec = function ( params ) {
+       this.spec = $.extend( {}, this.spec, params );
+
+       this.emit( 'specChange', this.spec );
+};
+
+/**
+ * Set the specification from a stringified version
+ *
+ * @param {string} str The new specification JSON string
+ * @fires specChange
+ */
+ve.dm.MWGraphNode.prototype.setSpecFromString = function ( str ) {
+       this.spec = ve.dm.MWGraphNode.static.parseSpecString( str );
+
+       this.emit( 'specChange', this.spec );
+};
+
+/* Registration */
+
+ve.dm.modelRegistry.register( ve.dm.MWGraphNode );

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

Gerrit-MessageType: merged
Gerrit-Change-Id: I66ff1d3574813daea22274777261b02d8b18b513
Gerrit-PatchSet: 7
Gerrit-Project: mediawiki/extensions/Graph
Gerrit-Branch: master
Gerrit-Owner: Ferdbold <[email protected]>
Gerrit-Reviewer: Ferdbold <[email protected]>
Gerrit-Reviewer: Jforrester <[email protected]>
Gerrit-Reviewer: Krinkle <[email protected]>
Gerrit-Reviewer: Legoktm <[email protected]>
Gerrit-Reviewer: Mooeypoo <[email protected]>
Gerrit-Reviewer: Mvolz <[email protected]>
Gerrit-Reviewer: Siebrand <[email protected]>
Gerrit-Reviewer: jenkins-bot <>

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

Reply via email to