diff --git a/.jshintrc b/.jshintrc index 66e3d481..fa96cd85 100644 --- a/.jshintrc +++ b/.jshintrc @@ -19,6 +19,7 @@ "globals": { "mediaWiki": false, + "ve": false, "OO": false } } diff --git a/extension.json b/extension.json index 89313044..533253f0 100644 --- a/extension.json +++ b/extension.json @@ -26,7 +26,7 @@ }, "Hooks": { "LoadExtensionSchemaUpdates": "MediaWiki\\Linter\\Hooks::onLoadExtensionSchemaUpdates", - "EditFormInitialText": "MediaWiki\\Linter\\Hooks::onEditFormInitialText", + "BeforePageDisplay": "MediaWiki\\Linter\\Hooks::onBeforePageDisplay", "APIQuerySiteInfoGeneralInfo": "MediaWiki\\Linter\\Hooks::onAPIQuerySiteInfoGeneralInfo", "InfoAction": "MediaWiki\\Linter\\Hooks::onInfoAction", "WikiPageDeletionUpdates": "MediaWiki\\Linter\\Hooks::onWikiPageDeletionUpdates" diff --git a/includes/Hooks.php b/includes/Hooks.php index 5626e1e7..6498eeb0 100644 --- a/includes/Hooks.php +++ b/includes/Hooks.php @@ -23,9 +23,9 @@ namespace MediaWiki\Linter; use ApiQuerySiteInfo; use Content; use DatabaseUpdater; -use EditPage; use IContextSource; use MWCallableUpdate; +use OutputPage; use WikiPage; class Hooks { @@ -38,21 +38,23 @@ class Hooks { } /** - * Hook: EditFormInitialText + * Hook: BeforePageDisplay * * If there is a lintid parameter, look up that error in the database * and setup and output our client-side helpers * - * @param EditPage $editPage + * @param OutputPage &$out */ - public static function onEditFormInitialText( EditPage $editPage ) { - $context = $editPage->getContext(); - $request = $context->getRequest(); + public static function onBeforePageDisplay( OutputPage &$out ) { + $request = $out->getRequest(); $lintId = $request->getInt( 'lintid' ); if ( !$lintId ) { return; } - $title = $editPage->getTitle(); + $title = $out->getTitle(); + if ( !$title ) { + return; + } $lintError = ( new Database( $title->getArticleID() ) )->getFromId( $lintId ); if ( !$lintError ) { @@ -60,7 +62,6 @@ class Hooks { return; } - $out = $context->getOutput(); $out->addJsConfigVars( [ 'wgLinterErrorCategory' => $lintError->category, 'wgLinterErrorLocation' => $lintError->location, diff --git a/modules/ext.linter.edit.js b/modules/ext.linter.edit.js index 5162219f..fa13f981 100644 --- a/modules/ext.linter.edit.js +++ b/modules/ext.linter.edit.js @@ -1,8 +1,35 @@ ( function ( mw, $ ) { $( function () { - var location = mw.config.get( 'wgLinterErrorLocation' ); + var location = mw.config.get( 'wgLinterErrorLocation' ), + $textbox = $( '#wpTextbox1' ); + + /** + * Convert the normal offset for one that is usable + * by VE's DOM that changes newlines into

+ * + * @param {ve.ui.Surface} surface + * @param {int} offset + * @return {int} + */ + function fixOffset( surface, offset ) { + return ( surface.getDom().slice( 0, offset ).match( /\n/g ) || [] ).length + 1 + offset; + } + if ( location ) { - $( '#wpTextbox1' ).focus().textSelection( 'setSelection', { start: location[ 0 ], end: location[ 1 ] } ); + if ( $textbox.length ) { + $textbox.focus().textSelection( 'setSelection', { start: location[ 0 ], end: location[ 1 ] } ); + } + // Register NWE code should it be loaded + // TODO: We should somehow force source mode if VE is opened + mw.hook( 've.activationComplete' ).add( function () { + var range, + surface = ve.init.target.getSurface(); + + if ( surface.getMode() === 'source' ) { + range = new ve.Range( fixOffset( surface, location[ 0 ] ), fixOffset( surface, location[ 1 ] ) ); + surface.getModel().setLinearSelection( range ); + } + } ); } } ); }( mediaWiki, jQuery ) );