jenkins-bot has submitted this change and it was merged. (
https://gerrit.wikimedia.org/r/350841 )
Change subject: Refactor the Integration with other extensions (v 4.0.0)
......................................................................
Refactor the Integration with other extensions (v 4.0.0)
This patch makes initialization easier and cheaper.
Since only the PhpTags extension uses the CodeMirrorGetAdditionalResources
hook it was removed. Instead, the CodeMirrorPluginModules and
CodeMirrorTagModes properties are used in extension.json file.
This patch adds ext.CodeMirror.lib.mode.php module for the PhpTags
extension (with dependences). In CodeMirror there are a lot of modes
they will be registered on request (if they will be requered for
extensions).
Examples of integration:
* Cite: I1bf156fa813af4d5f891619f692047bbdb8a1a86
* PhpTags: Ie339f0475e63885e603defaee2cdcccd6a95fafc
Bug: T163238
Change-Id: Idb7a1a5769a1047ef2f7cd25a7152f73a6613225
---
M CodeMirror.hooks.php
M extension.json
M resources/ext.CodeMirror.js
A resources/ext.CodeMirror.loader.js
M resources/mode/mediawiki/mediawiki.js
5 files changed, 144 insertions(+), 129 deletions(-)
Approvals:
Esanders: Looks good to me, approved
jenkins-bot: Verified
Kaldari: Looks good to me, but someone else must approve
diff --git a/CodeMirror.hooks.php b/CodeMirror.hooks.php
index 1f8b369..147148d 100644
--- a/CodeMirror.hooks.php
+++ b/CodeMirror.hooks.php
@@ -2,93 +2,57 @@
class CodeMirrorHooks {
- /** @var null|array Cached version of global variables, if available,
otherwise null */
- private static $globalVariableScript = null;
-
- /** @var null|boolean Saves, if CodeMirror should be loaded on this
page or not */
- private static $isEnabled = null;
-
- /** @var array values passed from other extensions for use in
self::getGlobalVariables() */
- private static $extModes = [];
-
- /**
- * ResourceLoaderRegisterModules hook handler to conditionally register
CodeMirror modules
- *
- * @see
https://www.mediawiki.org/wiki/Manual:Hooks/ResourceLoaderRegisterModules
- *
- * @param ResourceLoader &$rl The ResourceLoader object
- */
- public static function onResourceLoaderRegisterModules( ResourceLoader
$rl ) {
- $codeMirrorResourceTemplate = [
- 'localBasePath' => __DIR__ . '/resources',
- 'remoteExtPath' => 'CodeMirror/resources',
- ];
-
- self::$extModes = [
- 'tag' => [
- 'pre' => 'mw-tag-pre',
- 'nowiki' => 'mw-tag-nowiki',
- ],
- 'func' => [],
- 'data' => [],
- ];
- $extResources = [
- 'scripts' => [],
- 'styles' => [],
- 'messages' => [],
- 'dependencies' => [ 'ext.CodeMirror.lib' => true ],
- ];
-
- // enable other extensions to add additional resources and modes
- Hooks::run( 'CodeMirrorGetAdditionalResources', [
&$extResources, &self::$extModes ] );
-
- // Prepare array of resources for ResourceLoader
- $codeMirror = [
- 'scripts' => array_keys( $extResources['scripts'] ),
- 'styles' => array_keys( $extResources['styles'] ),
- 'messages' => array_keys( $extResources['messages'] ),
- 'dependencies' => array_keys(
$extResources['dependencies'] ),
- 'group' => 'ext.CodeMirror',
- ] + $codeMirrorResourceTemplate;
-
- $rl->register( [ 'ext.CodeMirror.other' => $codeMirror ] );
- }
-
/**
* Checks, if CodeMirror should be loaded on this page or not.
*
* @param IContextSource $context The current ContextSource object
+ * @global bool $wgCodeMirrorEnableFrontend Should CodeMirror be loaded
on this page
+ * @staticvar null|boolean $isEnabled Saves, if CodeMirror should be
loaded on this page or not
* @return bool
*/
private static function isCodeMirrorEnabled( IContextSource $context ) {
global $wgCodeMirrorEnableFrontend;
+ static $isEnabled = null;
// Check, if we already checked, if page action is editing, if
not, do it now
- if ( is_null( self::$isEnabled ) ) {
- // edit can be 'edit' and 'submit'
- self::$isEnabled = $wgCodeMirrorEnableFrontend &&
+ if ( $isEnabled === null ) {
+ $isEnabled = $wgCodeMirrorEnableFrontend &&
in_array(
Action::getActionName( $context ),
[ 'edit', 'submit' ]
);
}
- return self::$isEnabled;
+ return $isEnabled;
+ }
+ /**
+ * This function are used by the MobileFrontend extension only and will
be
+ * removed
+ * @deprecated since version 4.0.0
+ * @todo Remove usage in MobileFrontend and this function some time
later
+ * @param IContextSource $context
+ * @return array
+ */
+ public static function getGlobalVariables() {
+ MWDebug::deprecated( __METHOD__ );
+ return [];
}
/**
* Returns an array of variables for CodeMirror to work (tags and so on)
*
* @param IContextSource $context The current ContextSource object
+ * @global Parser $wgParser
+ * @staticvar array $config Cached version of configuration
* @return array
*/
- public static function getGlobalVariables( IContextSource $context ) {
- /** @var Parser $wgParser */
+ public static function getConfiguraton( IContextSource $context ) {
global $wgParser;
+ static $config = [];
// if we already created these variable array, return it
- if ( !self::$globalVariableScript ) {
+ if ( !$config ) {
$contObj = $context->getLanguage();
if ( !isset( $wgParser->mFunctionSynonyms ) ) {
@@ -96,14 +60,15 @@
$wgParser->firstCallInit();
}
- // initialize global vars
- $globalVariableScript = [
- 'ExtModes' => self::$extModes,
- 'Tags' => array_fill_keys(
$wgParser->getTags(), true ),
- 'DoubleUnderscore' => [ [], [] ],
- 'FunctionSynonyms' =>
$wgParser->mFunctionSynonyms,
- 'UrlProtocols' => $wgParser->mUrlProtocols,
- 'LinkTrailCharacters' => $contObj->linkTrail(),
+ // initialize configuration
+ $config = [
+ 'pluginModules' =>
ExtensionRegistry::getInstance()->getAttribute( 'CodeMirrorPluginModules' ),
+ 'tagModes' =>
ExtensionRegistry::getInstance()->getAttribute( 'CodeMirrorTagModes' ),
+ 'tags' => array_fill_keys(
$wgParser->getTags(), true ),
+ 'doubleUnderscore' => [ [], [] ],
+ 'functionSynonyms' =>
$wgParser->mFunctionSynonyms,
+ 'urlProtocols' => $wgParser->mUrlProtocols,
+ 'linkTrailCharacters' => $contObj->linkTrail(),
];
$mw = $contObj->getMagicWords();
@@ -111,10 +76,10 @@
if ( isset( $mw[$name] ) ) {
$caseSensitive = array_shift(
$mw[$name] ) == 0 ? 0 : 1;
foreach ( $mw[$name] as $n ) {
-
$globalVariableScript['DoubleUnderscore'][$caseSensitive][ $caseSensitive ? $n
: $contObj->lc( $n ) ] = $name;
+
$config['doubleUnderscore'][$caseSensitive][ $caseSensitive ? $n :
$contObj->lc( $n ) ] = $name;
}
} else {
-
$globalVariableScript['DoubleUnderscore'][0][] = $name;
+ $config['doubleUnderscore'][0][] =
$name;
}
}
@@ -122,18 +87,14 @@
if ( isset( $mw[$name] ) ) {
$caseSensitive = array_shift(
$mw[$name] ) == 0 ? 0 : 1;
foreach ( $mw[$name] as $n ) {
-
$globalVariableScript['FunctionSynonyms'][$caseSensitive][ $caseSensitive ? $n
: $contObj->lc( $n ) ] = $name;
+
$config['functionSynonyms'][$caseSensitive][ $caseSensitive ? $n :
$contObj->lc( $n ) ] = $name;
}
}
}
- // prefix all variables and save it into class variable
- foreach ( $globalVariableScript as $key=> $value ) {
-
self::$globalVariableScript["extCodeMirror$key"] = $value;
- }
}
- return self::$globalVariableScript;
+ return $config;
}
/**
@@ -148,7 +109,7 @@
$context = $out->getContext();
// add CodeMirror vars only for edit pages
if ( self::isCodeMirrorEnabled( $context ) ) {
- $vars += self::getGlobalVariables( $context );
+ $vars['extCodeMirrorConfig'] = self::getConfiguraton(
$context );
}
}
@@ -162,7 +123,7 @@
*/
public static function onBeforePageDisplay( OutputPage &$out, Skin
&$skin ) {
if ( self::isCodeMirrorEnabled( $out->getContext() ) ) {
- $out->addModules( 'ext.CodeMirror.init' );
+ $out->addModules( 'ext.CodeMirror' );
}
}
diff --git a/extension.json b/extension.json
index 042c1d6..309e110 100644
--- a/extension.json
+++ b/extension.json
@@ -1,6 +1,6 @@
{
"name": "CodeMirror",
- "version": "3.4.0",
+ "version": "4.0.0",
"author": [
"[https://www.mediawiki.org/wiki/User:Pastakhov Pavel
Astakhov]",
"[https://www.mediawiki.org/wiki/User:Florianschmidtwelzow
Florian Schmidt]"
@@ -18,10 +18,13 @@
"CodeMirrorHooks": "CodeMirror.hooks.php"
},
"ResourceModules": {
- "ext.CodeMirror.init": {
+ "ext.CodeMirror.loader": {
+ "loaderScripts": "ext.CodeMirror.loader.js"
+ },
+ "ext.CodeMirror": {
"dependencies": [
"ext.CodeMirror.lib",
- "ext.CodeMirror.other",
+ "ext.CodeMirror.mode.mediawiki",
"jquery.textSelection",
"mediawiki.api",
"mediawiki.api.options",
@@ -40,18 +43,58 @@
},
"ext.CodeMirror.lib": {
"scripts": [
- "lib/codemirror/lib/codemirror.js",
- "lib/codemirror/addon/selection/active-line.js",
- "mode/mediawiki/mediawiki.js"
+ "lib/codemirror/lib/codemirror.js"
],
"styles": [
- "lib/codemirror/lib/codemirror.css",
- "lib/codemirror/addon/lint/lint.css",
- "mode/mediawiki/mediawiki.css"
- ],
- "targets": [
- "mobile",
- "desktop"
+ "lib/codemirror/lib/codemirror.css"
+ ]
+ },
+ "ext.CodeMirror.mode.mediawiki": {
+ "scripts": "mode/mediawiki/mediawiki.js",
+ "styles": "mode/mediawiki/mediawiki.css",
+ "dependencies": [
+ "ext.CodeMirror.lib"
+ ]
+ },
+ "ext.CodeMirror.lib.mode.css": {
+ "scripts": "lib/codemirror/mode/css/css.js",
+ "dependencies": [
+ "ext.CodeMirror.lib"
+ ]
+ },
+ "ext.CodeMirror.lib.mode.javascript": {
+ "scripts":
"lib/codemirror/mode/javascript/javascript.js",
+ "dependencies": [
+ "ext.CodeMirror.lib"
+ ]
+ },
+ "ext.CodeMirror.lib.mode.xml": {
+ "scripts": "lib/codemirror/mode/xml/xml.js",
+ "dependencies": [
+ "ext.CodeMirror.lib"
+ ]
+ },
+ "ext.CodeMirror.lib.mode.htmlmixed": {
+ "scripts": "lib/codemirror/mode/htmlmixed/htmlmixed.js",
+ "dependencies": [
+ "ext.CodeMirror.lib.mode.xml",
+ "ext.CodeMirror.lib.mode.javascript",
+ "ext.CodeMirror.lib.mode.css",
+ "ext.CodeMirror.lib"
+ ]
+ },
+ "ext.CodeMirror.lib.mode.clike": {
+ "scripts": "lib/codemirror/mode/clike/clike.js",
+ "dependencies": [
+ "ext.CodeMirror.lib"
+ ]
+ },
+ "ext.CodeMirror.lib.mode.php": {
+ "scripts": "lib/codemirror/mode/php/php.js",
+ "dependencies": [
+ "ext.CodeMirror.lib.mode.htmlmixed",
+ "ext.CodeMirror.lib.mode.clike",
+ "ext.CodeMirror.lib"
]
}
},
@@ -68,13 +111,15 @@
],
"GetPreferences": [
"CodeMirrorHooks::onGetPreferences"
- ],
- "ResourceLoaderRegisterModules": [
- "CodeMirrorHooks::onResourceLoaderRegisterModules"
]
},
"config": {
"CodeMirrorEnableFrontend": true
},
+ "CodeMirrorTagModes": {
+ "pre": "mw-tag-pre",
+ "nowiki": "mw-tag-nowiki"
+ },
+ "CodeMirrorPluginModules": [],
"manifest_version": 1
}
diff --git a/resources/ext.CodeMirror.js b/resources/ext.CodeMirror.js
index fc3c5b7..8149619 100644
--- a/resources/ext.CodeMirror.js
+++ b/resources/ext.CodeMirror.js
@@ -359,43 +359,44 @@
* Replaces the default textarea with CodeMirror
*/
function enableCodeMirror() {
- var $codeMirror,
- $textbox1 = $( '#wpTextbox1' );
+ var config = mw.config.get( 'extCodeMirrorConfig' );
if ( codeMirror ) {
return;
}
- codeMirror = CodeMirror.fromTextArea( $textbox1[ 0 ], {
- mwextFunctionSynonyms: mw.config.get(
'extCodeMirrorFunctionSynonyms' ),
- mwextTags: mw.config.get( 'extCodeMirrorTags' ),
- mwextDoubleUnderscore: mw.config.get(
'extCodeMirrorDoubleUnderscore' ),
- mwextUrlProtocols: mw.config.get(
'extCodeMirrorUrlProtocols' ),
- mwextModes: mw.config.get( 'extCodeMirrorExtModes' ),
- // styleActiveLine: true, // disabled since Bug:
T162204, maybe should be optional
- lineWrapping: true,
- readOnly: $textbox1[ 0 ].readOnly,
- // select mediawiki as text input mode
- mode: 'text/mediawiki',
- extraKeys: {
- Tab: false
+
+ mw.loader.using( config.pluginModules, function() {
+ var $codeMirror,
+ $textbox1 = $( '#wpTextbox1' );
+
+ codeMirror = CodeMirror.fromTextArea( $textbox1[ 0 ], {
+ mwConfig: config,
+ // styleActiveLine: true, // disabled since
Bug: T162204, maybe should be optional
+ lineWrapping: true,
+ readOnly: $textbox1[ 0 ].readOnly,
+ // select mediawiki as text input mode
+ mode: 'text/mediawiki',
+ extraKeys: {
+ Tab: false
+ }
+ } );
+ $codeMirror = $( codeMirror.getWrapperElement() );
+
+ // HACK: <textarea> font size varies by browser
(chrome/FF/IE)
+ $codeMirror.css( {
+ 'font-size': $textbox1.css( 'font-size' ),
+ 'line-height': $textbox1.css( 'line-height' )
+ } );
+
+ if ( !wikiEditorToolbarEnabled ) {
+ $codeMirror.addClass(
'mw-codeMirror-classicToolbar' );
}
+
+ // set the height of the textarea
+ codeMirror.setSize( null, $textbox1.height() );
+ // Overwrite default textselection of WikiEditor to
work with CodeMirror, too
+ $.fn.textSelection = cmTextSelection;
} );
- $codeMirror = $( codeMirror.getWrapperElement() );
-
- // HACK: <textarea> font size varies by browser (chrome/FF/IE)
- $codeMirror.css( {
- 'font-size': $textbox1.css( 'font-size' ),
- 'line-height': $textbox1.css( 'line-height' )
- } );
-
- if ( !wikiEditorToolbarEnabled ) {
- $codeMirror.addClass( 'mw-codeMirror-classicToolbar' );
- }
-
- // set the hight of the textarea
- codeMirror.setSize( null, $textbox1.height() );
- // Overwrite default textselection of WikiEditor to work with
CodeMirror, too
- $.fn.textSelection = cmTextSelection;
}
/* Check if view is in edit mode and that the required modules are
available. Then, customize the toolbar … */
diff --git a/resources/ext.CodeMirror.loader.js
b/resources/ext.CodeMirror.loader.js
new file mode 100644
index 0000000..75cd02d
--- /dev/null
+++ b/resources/ext.CodeMirror.loader.js
@@ -0,0 +1,7 @@
+( function ( mw ) {
+ var config = mw.config.get( 'extCodeMirrorConfig' );
+
+ if ( config.pluginModules && config.pluginModules.length > 0 ) {
+ mw.loader.load( config.pluginModules );
+ }
+}( mediaWiki ) );
diff --git a/resources/mode/mediawiki/mediawiki.js
b/resources/mode/mediawiki/mediawiki.js
index 293a497..0115b9f 100644
--- a/resources/mode/mediawiki/mediawiki.js
+++ b/resources/mode/mediawiki/mediawiki.js
@@ -22,7 +22,8 @@
CodeMirror.defineMode( 'mediawiki', function ( config /* , parserConfig
*/ ) {
- var urlProtocols = new RegExp( config.mwextUrlProtocols, 'i' ),
+ var mwConfig = config.mwConfig,
+ urlProtocols = new RegExp( mwConfig.urlProtocols, 'i' ),
permittedHtmlTags = { b: true, bdi: true, del: true, i:
true, ins: true,
u: true, font: true, big: true, small: true,
sub: true, sup: true,
h1: true, h2: true, h3: true, h4: true, h5:
true, h6: true, cite: true,
@@ -443,8 +444,8 @@
}
if ( stream.eat( '>' ) ) {
state.extName = name;
- if ( name in config.mwextModes.tag ) {
- state.extMode =
CodeMirror.getMode( config, config.mwextModes.tag[ name ] );
+ if ( name in mwConfig.tagModes ) {
+ state.extMode =
CodeMirror.getMode( config, mwConfig.tagModes[ name ] );
state.extState =
CodeMirror.startState( state.extMode );
}
state.tokenize = eatExtTagArea( name );
@@ -756,7 +757,7 @@
name = stream.match(
/([^\s\u00a0\}\[\]<\{\'\|\&\:]+)(\:|[\s\u00a0]*)(\}\}?)?(.)?/ );
if ( name ) {
stream.backUp(
name[ 0 ].length );
- if ( ( name[ 2
] === ':' || name[ 4 ] === undefined || name[ 3 ] === '}}' ) && ( name[ 1
].toLowerCase() in config.mwextFunctionSynonyms[ 0 ] || name[ 1 ] in
config.mwextFunctionSynonyms[ 1 ] ) ) {
+ if ( ( name[ 2
] === ':' || name[ 4 ] === undefined || name[ 3 ] === '}}' ) && ( name[ 1
].toLowerCase() in mwConfig.functionSynonyms[ 0 ] || name[ 1 ] in
mwConfig.functionSynonyms[ 1 ] ) ) {
state.nExt++;
state.stack.push( state.tokenize );
state.tokenize = inParserFunctionName;
@@ -778,7 +779,7 @@
}
if ( tagname ) {
tagname = tagname[ 0
].toLowerCase();
- if ( tagname in
config.mwextTags ) { // Parser function
+ if ( tagname in
mwConfig.tags ) { // Parser function
if ( isCloseTag
=== true ) {
//
@todo message
return
'error';
--
To view, visit https://gerrit.wikimedia.org/r/350841
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings
Gerrit-MessageType: merged
Gerrit-Change-Id: Idb7a1a5769a1047ef2f7cd25a7152f73a6613225
Gerrit-PatchSet: 6
Gerrit-Project: mediawiki/extensions/CodeMirror
Gerrit-Branch: master
Gerrit-Owner: Pastakhov <[email protected]>
Gerrit-Reviewer: Esanders <[email protected]>
Gerrit-Reviewer: Jforrester <[email protected]>
Gerrit-Reviewer: Kaldari <[email protected]>
Gerrit-Reviewer: Pastakhov <[email protected]>
Gerrit-Reviewer: TheDJ <[email protected]>
Gerrit-Reviewer: jenkins-bot <>
_______________________________________________
MediaWiki-commits mailing list
[email protected]
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits