mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-11-23 14:06:52 +00:00
Provide VE-rebaser in MediaWiki as Special:CollabPad
Change-Id: I3ffe0e2b6af43d4018dcd79877f4f27ed7d6a7e7
This commit is contained in:
parent
1ffb299f18
commit
574baf2e8e
|
@ -188,6 +188,10 @@ class ApiVisualEditor extends ApiBase {
|
|||
$params = $this->extractRequestParams();
|
||||
|
||||
$title = Title::newFromText( $params['page'] );
|
||||
if ( $title && $title->isSpecial( 'CollabPad' ) ) {
|
||||
// Convert Special:CollabPad/MyPage to MyPage so we can parsefragment properly
|
||||
$title = Title::newFromText( preg_replace( '`^([^/]+/)`', '', $params['page'] ) );
|
||||
}
|
||||
if ( !$title ) {
|
||||
$this->dieWithError( [ 'apierror-invalidtitle', wfEscapeWikiText( $params['page'] ) ] );
|
||||
}
|
||||
|
|
|
@ -792,6 +792,7 @@ class VisualEditorHooks {
|
|||
'svgMaxSize' => $coreConfig->get( 'SVGMaxSize' ),
|
||||
'namespacesWithSubpages' => $coreConfig->get( 'NamespacesWithSubpages' ),
|
||||
'specialBooksources' => urldecode( SpecialPage::getTitleFor( 'Booksources' )->getPrefixedURL() ),
|
||||
'rebaserUrl' => $coreConfig->get( 'VisualEditorRebaserURL' ),
|
||||
'restbaseUrl' => $coreConfig->get( 'VisualEditorRestbaseURL' ),
|
||||
'fullRestbaseUrl' => $coreConfig->get( 'VisualEditorFullRestbaseURL' ),
|
||||
'feedbackApiUrl' => $veConfig->get( 'VisualEditorFeedbackAPIURL' ),
|
||||
|
|
23
VisualEditor.i18n.alias.php
Normal file
23
VisualEditor.i18n.alias.php
Normal file
|
@ -0,0 +1,23 @@
|
|||
<?php
|
||||
/**
|
||||
* Aliases for Special:CollabPad
|
||||
*
|
||||
* @file
|
||||
* @ingroup Extensions
|
||||
*/
|
||||
|
||||
$specialPageAliases = [];
|
||||
|
||||
/** English
|
||||
* @author "James D. Forrester"
|
||||
*/
|
||||
$specialPageAliases['en'] = [
|
||||
'CollabPad' => [ 'CollabPad', 'Collab Pad' ],
|
||||
];
|
||||
|
||||
/** Cyrmu
|
||||
* @author "James D. Forrester"
|
||||
*/
|
||||
$specialPageAliases['cy'] = [
|
||||
'CollabPad' => [ 'PadCydweithredu', 'Pad Cydweithredu' ],
|
||||
];
|
|
@ -31,6 +31,7 @@
|
|||
"site",
|
||||
"user"
|
||||
],
|
||||
"VisualEditorRebaserURL": false,
|
||||
"VisualEditorRestbaseURL": false,
|
||||
"VisualEditorFullRestbaseURL": false,
|
||||
"VisualEditorFeedbackAPIURL": false,
|
||||
|
@ -127,6 +128,9 @@
|
|||
"modules/ve-wmf/i18n"
|
||||
]
|
||||
},
|
||||
"ExtensionMessagesFiles": {
|
||||
"VisualEditorAlias": "VisualEditor.i18n.alias.php"
|
||||
},
|
||||
"Hooks": {
|
||||
"BeforePageDisplay": [
|
||||
"VisualEditorHooks::onBeforePageDisplay"
|
||||
|
@ -224,6 +228,16 @@
|
|||
"mobile"
|
||||
]
|
||||
},
|
||||
"socket.io": {
|
||||
"scripts": [
|
||||
"lib/ve/lib/socket.io-client/socket.io.min.js"
|
||||
]
|
||||
},
|
||||
"dompurify": {
|
||||
"scripts": [
|
||||
"lib/ve/lib/dompurify/purify.js"
|
||||
]
|
||||
},
|
||||
"unicodejs": {
|
||||
"scripts": [
|
||||
"lib/ve/lib/unicodejs/unicodejs.js"
|
||||
|
@ -421,6 +435,32 @@
|
|||
"mobile"
|
||||
]
|
||||
},
|
||||
"ext.visualEditor.collabTarget": {
|
||||
"scripts": [
|
||||
"modules/ve-mw-collab/ve.init.mw.CollabTarget.js"
|
||||
],
|
||||
"dependencies": [
|
||||
"ext.visualEditor.base",
|
||||
"ext.visualEditor.mediawiki",
|
||||
"ext.visualEditor.core.desktop",
|
||||
"ext.visualEditor.mwextensions.desktop",
|
||||
"ext.visualEditor.desktopArticleTarget"
|
||||
],
|
||||
"messages" : []
|
||||
},
|
||||
"ext.visualEditor.collabTarget.init": {
|
||||
"scripts": [
|
||||
"modules/ve-mw-collab/ve.init.mw.CollabTarget.init.js"
|
||||
],
|
||||
"dependencies": [
|
||||
"oojs-ui"
|
||||
]
|
||||
},
|
||||
"ext.visualEditor.collabTarget.init.styles": {
|
||||
"styles": [
|
||||
"modules/ve-mw-collab/ve.init.mw.CollabTarget.css"
|
||||
]
|
||||
},
|
||||
"ext.visualEditor.ve": {
|
||||
"scripts": "lib/ve/src/ve.js",
|
||||
"targets": [
|
||||
|
@ -1049,6 +1089,26 @@
|
|||
"mobile"
|
||||
]
|
||||
},
|
||||
"ext.visualEditor.rebase": {
|
||||
"scripts": [
|
||||
"lib/ve/src/dm/ve.dm.Change.js",
|
||||
"lib/ve/src/dm/ve.dm.RebaseClient.js",
|
||||
"lib/ve/src/dm/ve.dm.SurfaceSynchronizer.js",
|
||||
"lib/ve/src/ui/widgets/ve.ui.AuthorListWidget.js"
|
||||
],
|
||||
"styles": [
|
||||
"lib/ve/src/ui/styles/widgets/ve.ui.AuthorListWidget.css"
|
||||
],
|
||||
"dependencies": [
|
||||
"ext.visualEditor.core",
|
||||
"dompurify",
|
||||
"socket.io",
|
||||
"oojs-ui.styles.icons-alerts"
|
||||
],
|
||||
"messages": [
|
||||
"visualeditor-rebase-client-author-name"
|
||||
]
|
||||
},
|
||||
"ext.visualEditor.core.desktop": {
|
||||
"scripts": [
|
||||
"lib/ve/src/ui/contexts/ve.ui.DesktopContext.js",
|
||||
|
@ -1058,7 +1118,8 @@
|
|||
"lib/ve/src/ui/styles/ve.ui.DesktopContext.css"
|
||||
],
|
||||
"dependencies": [
|
||||
"ext.visualEditor.core"
|
||||
"ext.visualEditor.core",
|
||||
"ext.visualEditor.rebase"
|
||||
],
|
||||
"targets": [
|
||||
"desktop"
|
||||
|
@ -2020,9 +2081,13 @@
|
|||
"visualeditor-editor": "wikitext",
|
||||
"visualeditor-hidetabdialog": 0
|
||||
},
|
||||
"SpecialPages": {
|
||||
"CollabPad": "SpecialCollabPad"
|
||||
},
|
||||
"AutoloadClasses": {
|
||||
"ApiVisualEditor": "ApiVisualEditor.php",
|
||||
"ApiVisualEditorEdit": "ApiVisualEditorEdit.php",
|
||||
"SpecialCollabPad": "modules/ve-mw-collab/SpecialCollabPad.php",
|
||||
"VisualEditorHooks": "VisualEditor.hooks.php",
|
||||
"VisualEditorDataModule": "VisualEditorDataModule.php",
|
||||
"VisualEditorDesktopArticleTargetInitModule": "VisualEditorDesktopArticleTargetInitModule.php"
|
||||
|
|
75
modules/ve-mw-collab/SpecialCollabPad.php
Normal file
75
modules/ve-mw-collab/SpecialCollabPad.php
Normal file
|
@ -0,0 +1,75 @@
|
|||
<?php
|
||||
class SpecialCollabPad extends SpecialPage {
|
||||
private $prefixes = [];
|
||||
|
||||
/**
|
||||
* @var null|Title
|
||||
*/
|
||||
private $title = null;
|
||||
|
||||
/**
|
||||
* @var null|ParserOutput
|
||||
*/
|
||||
private $output = null;
|
||||
|
||||
function __construct() {
|
||||
parent::__construct( 'CollabPad' );
|
||||
}
|
||||
|
||||
protected function getGroupName() {
|
||||
return 'wiki';
|
||||
}
|
||||
|
||||
public function userCanExecute( User $user ) {
|
||||
global $wgVisualEditorRebaserURL;
|
||||
return !!$wgVisualEditorRebaserURL && parent::userCanExecute( $user );
|
||||
}
|
||||
|
||||
function isListed() {
|
||||
global $wgVisualEditorRebaserURL;
|
||||
return !!$wgVisualEditorRebaserURL;
|
||||
}
|
||||
|
||||
function execute( $par ) {
|
||||
$this->setHeaders();
|
||||
$this->checkPermissions();
|
||||
|
||||
$request = $this->getRequest();
|
||||
|
||||
$output = $this->getOutput();
|
||||
|
||||
$output->addJsConfigVars( 'collabPadPageName', $par );
|
||||
$output->addModuleStyles( 'ext.visualEditor.collabTarget.init.styles' );
|
||||
$output->addModules( 'ext.visualEditor.collabTarget.init' );
|
||||
|
||||
$output->enableOOUI();
|
||||
if ( $par ) {
|
||||
$title = Title::newFromText( $par );
|
||||
$output->setPageTitle( 'CollabPad: ' . $title->getPrefixedText() );
|
||||
$output->addHTML( new OOUI\ProgressBarWidget( [
|
||||
'classes' => [ 've-init-mw-collabTarget-loading' ]
|
||||
] ) );
|
||||
} else {
|
||||
// Scripts only, styles already added above
|
||||
$output->addModules( 'ext.visualEditor.collabTarget' );
|
||||
// TODO: Output this "form" unconditionally so the user can
|
||||
// navigate back to it without reloading the page.
|
||||
$output->addHTML( new OOUI\ActionFieldLayout(
|
||||
new OOUI\TextInputWidget( [
|
||||
'classes' => [ 've-init-mw-collabTarget-nameInput' ],
|
||||
'placeholder' => $this->msg( 'visualeditor-rebase-client-document-name' )->text(),
|
||||
'autofocus' => true,
|
||||
'infusable' => true
|
||||
] ),
|
||||
new OOUI\ButtonWidget( [
|
||||
'classes' => [ 've-init-mw-collabTarget-nameButton' ],
|
||||
'label' => $this->msg( 'visualeditor-rebase-client-document-create-edit' )->text(),
|
||||
// Only enable once JS has loaded
|
||||
'disabled' => true,
|
||||
'infusable' => true
|
||||
] ),
|
||||
[ 'classes' => [ 've-init-mw-collabTarget-nameField' ] ] )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
28
modules/ve-mw-collab/ve.init.mw.CollabTarget.css
Normal file
28
modules/ve-mw-collab/ve.init.mw.CollabTarget.css
Normal file
|
@ -0,0 +1,28 @@
|
|||
/*!
|
||||
* VisualEditor MediaWiki Initialization CollabTarget styles.
|
||||
*
|
||||
* @copyright 2011-2017 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license The MIT License (MIT); see LICENSE.txt
|
||||
*/
|
||||
|
||||
.ve-init-mw-collabTarget-loading,
|
||||
.ve-init-mw-collabTarget-nameField {
|
||||
margin: 0 auto;
|
||||
width: 40em;
|
||||
margin-top: 2em !important; /* stylelint-disable-line declaration-no-important */
|
||||
}
|
||||
|
||||
.ve-init-mw-collabTarget .ve-ui-authorListWidget {
|
||||
display: inline-block;
|
||||
margin: 0.3125em;
|
||||
}
|
||||
|
||||
/* MW theme hack */
|
||||
.ve-init-mw-collabTarget .ve-ui-authorListWidget-author.oo-ui-iconElement .oo-ui-iconElement-icon {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
/* Hack for T165794 */
|
||||
.ve-init-mw-collabTarget .ve-ui-authorListWidget-editName > .oo-ui-fieldLayout-body > .oo-ui-fieldLayout-header > .oo-ui-labelElement-label {
|
||||
padding-top: 0.6em !important; /* stylelint-disable-line declaration-no-important */
|
||||
}
|
98
modules/ve-mw-collab/ve.init.mw.CollabTarget.init.js
Normal file
98
modules/ve-mw-collab/ve.init.mw.CollabTarget.init.js
Normal file
|
@ -0,0 +1,98 @@
|
|||
/*!
|
||||
* VisualEditor MediaWiki DesktopArticleTarget init.
|
||||
*
|
||||
* This file must remain as widely compatible as the base compatibility
|
||||
* for MediaWiki itself (see mediawiki/core:/resources/startup.js).
|
||||
* Avoid use of: ES5, SVG, HTML5 DOM, ContentEditable etc.
|
||||
*
|
||||
* @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license The MIT License (MIT); see LICENSE.txt
|
||||
*/
|
||||
|
||||
( function () {
|
||||
var $content = $( '#mw-content-text' ),
|
||||
conf = mw.config.get( 'wgVisualEditorConfig' ),
|
||||
pageTitle = mw.Title.newFromText( mw.config.get( 'collabPadPageName' ) || '' ),
|
||||
modules = [ 'ext.visualEditor.collabTarget' ]
|
||||
// Add modules from $wgVisualEditorPluginModules
|
||||
.concat( conf.pluginModules.filter( mw.loader.getState ) ),
|
||||
loadingPromise = mw.loader.using( modules );
|
||||
|
||||
if ( !VisualEditorSupportCheck() ) {
|
||||
// VE not supported - say something?
|
||||
return;
|
||||
}
|
||||
|
||||
function showPage( title ) {
|
||||
$( '#firstHeading' ).text( 'CollabPad: ' + title.getPrefixedText() ); // TODO: i18n
|
||||
$content.empty().append(
|
||||
new OO.ui.ProgressBarWidget( {
|
||||
classes: [ 've-init-mw-collabTarget-loading' ]
|
||||
} ).$element
|
||||
);
|
||||
loadingPromise.then( function () {
|
||||
var target = ve.init.mw.targetFactory.create( 'collab' );
|
||||
|
||||
$( 'body' ).addClass( 've-activated ve-active' );
|
||||
|
||||
$content.empty();
|
||||
$( '#content' ).append( target.$element );
|
||||
|
||||
target.transformPage();
|
||||
$( '#firstHeading' ).addClass( 've-init-mw-desktopArticleTarget-uneditableContent' );
|
||||
|
||||
target.documentReady( ve.createDocumentFromHtml( '' ) );
|
||||
target.on( 'surfaceReady', function () {
|
||||
var synchronizer = new ve.dm.SurfaceSynchronizer(
|
||||
target.getSurface().getModel(),
|
||||
title.toString(),
|
||||
{ server: conf.rebaserUrl }
|
||||
),
|
||||
authorList = new ve.ui.AuthorListWidget( synchronizer );
|
||||
|
||||
target.getToolbar().$actions.append( authorList.$element );
|
||||
target.getSurface().getView().setSynchronizer( synchronizer );
|
||||
target.getSurface().getView().focus();
|
||||
} );
|
||||
} );
|
||||
}
|
||||
|
||||
function showForm() {
|
||||
var documentNameInput = OO.ui.infuse( $( '.ve-init-mw-collabTarget-nameInput' ) ),
|
||||
submitButton = OO.ui.infuse( $( '.ve-init-mw-collabTarget-nameButton' ) );
|
||||
|
||||
documentNameInput.setValidation( function ( value ) {
|
||||
var title = mw.Title.newFromText( value );
|
||||
return !!title;
|
||||
} );
|
||||
|
||||
function onSubmit() {
|
||||
var href,
|
||||
title = mw.Title.newFromText( documentNameInput.getValue() );
|
||||
|
||||
if ( title ) {
|
||||
href = window.location.href + '/' + encodeURIComponent( title.toString() );
|
||||
if ( history.pushState ) {
|
||||
// TODO: Handle popstate
|
||||
history.pushState( null, title.getMain(), href );
|
||||
showPage( title );
|
||||
} else {
|
||||
window.location.href = href;
|
||||
}
|
||||
} else {
|
||||
documentNameInput.focus();
|
||||
}
|
||||
}
|
||||
|
||||
submitButton.on( 'click', onSubmit );
|
||||
documentNameInput.on( 'enter', onSubmit );
|
||||
|
||||
submitButton.setDisabled( false );
|
||||
}
|
||||
|
||||
if ( pageTitle ) {
|
||||
showPage( pageTitle );
|
||||
} else {
|
||||
showForm();
|
||||
}
|
||||
}() );
|
76
modules/ve-mw-collab/ve.init.mw.CollabTarget.js
Normal file
76
modules/ve-mw-collab/ve.init.mw.CollabTarget.js
Normal file
|
@ -0,0 +1,76 @@
|
|||
/*!
|
||||
* VisualEditor MediaWiki Initialization CollabTarget class.
|
||||
*
|
||||
* @copyright 2011-2016 VisualEditor Team and others; see AUTHORS.txt
|
||||
* @license The MIT License (MIT); see LICENSE.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
* MediaWiki mobile article target.
|
||||
*
|
||||
* @class
|
||||
* @extends ve.init.mw.Target
|
||||
*
|
||||
* @constructor
|
||||
* @param {Object} [config] Configuration options
|
||||
*/
|
||||
ve.init.mw.CollabTarget = function VeInitMwCollabTarget( config ) {
|
||||
config = config || {};
|
||||
config.toolbarConfig = $.extend( {
|
||||
shadow: true,
|
||||
actions: true,
|
||||
floatable: true
|
||||
}, config.toolbarConfig );
|
||||
|
||||
// Parent constructor
|
||||
ve.init.mw.CollabTarget.super.call( this, config );
|
||||
|
||||
this.$originalContent = $( '<div>' ).addClass( 've-init-mw-desktopArticleTarget-originalContent' );
|
||||
this.$editableContent = $( '#mw-content-text' );
|
||||
|
||||
// Initialization
|
||||
this.$element.addClass( 've-init-mw-articleTarget ve-init-mw-desktopArticleTarget ve-init-mw-collabTarget' ).append( this.$originalContent );
|
||||
};
|
||||
|
||||
/* Inheritance */
|
||||
|
||||
OO.inheritClass( ve.init.mw.CollabTarget, ve.init.mw.Target );
|
||||
|
||||
/* Static Properties */
|
||||
|
||||
ve.init.mw.CollabTarget.static.name = 'collab';
|
||||
|
||||
ve.init.mw.CollabTarget.static.trackingName = 'collab';
|
||||
|
||||
/* Methods */
|
||||
|
||||
/**
|
||||
* Page modifications after editor load.
|
||||
*/
|
||||
ve.init.mw.CollabTarget.prototype.transformPage = function () {
|
||||
this.$originalContent.append( this.$element.siblings() );
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ve.init.mw.CollabTarget.prototype.attachToolbar = function () {
|
||||
this.toolbar.$element.addClass( 've-init-mw-desktopArticleTarget-toolbar ve-init-mw-desktopArticleTarget-toolbar-opened' );
|
||||
this.$element.prepend( this.toolbar.$element );
|
||||
};
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
ve.init.mw.CollabTarget.prototype.setSurface = function ( surface ) {
|
||||
if ( surface !== this.surface ) {
|
||||
this.$editableContent.after( surface.$element );
|
||||
}
|
||||
|
||||
// Parent method
|
||||
ve.init.mw.CollabTarget.super.prototype.setSurface.apply( this, arguments );
|
||||
};
|
||||
|
||||
/* Registration */
|
||||
|
||||
ve.init.mw.targetFactory.register( ve.init.mw.CollabTarget );
|
|
@ -58,6 +58,7 @@
|
|||
"apierror-visualeditor-docserver-http-error": "$1",
|
||||
"apierror-visualeditor-invaliddeflate": "Content provided is not properly deflated",
|
||||
"apierror-visualeditor-latestnotfound": "Could not find latest revision for title",
|
||||
"collabpad": "CollabPad",
|
||||
"tooltip-ca-createsource": "Create the source code of this page",
|
||||
"tooltip-ca-edit": "Edit this page using wikitext",
|
||||
"tooltip-ca-editsource": "Edit the source code of this page",
|
||||
|
|
|
@ -71,6 +71,7 @@
|
|||
"apierror-visualeditor-docserver-http-error": "{{doc-apierror}}\n\nParameters:\n* $1 - Error message, probably in English",
|
||||
"apierror-visualeditor-invaliddeflate": "{{doc-apierror}}",
|
||||
"apierror-visualeditor-latestnotfound": "{{doc-apierror}}",
|
||||
"collabpad": "Name of CollabPad special page",
|
||||
"tooltip-ca-createsource": "Tooltip of the {{msg-mw|Visualeditor-ca-createsource}} tab, used if the page does not exist.\n\nSee also:\n* {{msg-mw|Tooltip-ca-editsource}} - tooltip of the {{msg-mw|Visualeditor-ca-editsource}} tab, used if the page already exists",
|
||||
"tooltip-ca-edit": "Over-ridden tooltip of the wikitext \"Edit source\" tab.",
|
||||
"tooltip-ca-editsource": "Tooltip of the {{msg-mw|Visualeditor-ca-editsource}} tab, used if the page already exists.\n\nSee also:\n* {{msg-mw|Tooltip-ca-createsource}} - tooltip of the {{msg-mw|Visualeditor-ca-createsource}} tab, used if the page does not exist",
|
||||
|
|
Loading…
Reference in a new issue