mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/VisualEditor
synced 2024-09-25 19:26:46 +00:00
Merge branch 'dmrewrite' of ssh://gerrit.wikimedia.org:29418/mediawiki/extensions/VisualEditor into dmrewrite
This commit is contained in:
commit
5e845979b8
|
@ -9,30 +9,36 @@ class ApiVisualEditor extends ApiBase {
|
|||
$params = $this->extractRequestParams();
|
||||
$page = Title::newFromText( $params['page'] );
|
||||
|
||||
if ($params['paction'] === 'parse') {
|
||||
$parsed = Http::get(
|
||||
$parsoid.$page
|
||||
);
|
||||
if ( $params['paction'] === 'parse' ) {
|
||||
if ( $page->exists() ) {
|
||||
$parsed = Http::get(
|
||||
$parsoid . $page->getPrefixedDBkey()
|
||||
);
|
||||
|
||||
if ( $parsed ) {
|
||||
$result = array(
|
||||
'result' => 'success',
|
||||
'parsed' => $parsed
|
||||
);
|
||||
if ( $parsed ) {
|
||||
$result = array(
|
||||
'result' => 'success',
|
||||
'parsed' => $parsed
|
||||
);
|
||||
} else {
|
||||
$result = array(
|
||||
'result' => 'error'
|
||||
);
|
||||
}
|
||||
} else {
|
||||
$result = array(
|
||||
'result' => 'error'
|
||||
);
|
||||
$result = array( 'result' => 'success', 'parsed' => '' );
|
||||
}
|
||||
} elseif ($params['paction'] === 'save') {
|
||||
} elseif ( $params['paction'] === 'save' ) {
|
||||
// API Posts HTML to Parsoid Service, receives Wikitext,
|
||||
// API Saves Wikitext to page.
|
||||
$wikitext = Http::post( $parsoid.$page, array( 'postData' => array( 'content' => $params['html'] ) ) );
|
||||
$wikitext = Http::post( $parsoid . $page->getPrefixedDBkey(),
|
||||
array( 'postData' => array( 'content' => $params['html'] ) )
|
||||
);
|
||||
|
||||
if ( $wikitext ) {
|
||||
|
||||
/* Save Page */
|
||||
$flags = $params['minor'] === 'true' ? EDIT_MINOR : EDIT_UPDATE;
|
||||
$flags = $params['minor'] === 'true' ? EDIT_MINOR : 0;
|
||||
|
||||
$wikiPage = WikiPage::factory( $page );
|
||||
$status = $wikiPage->doEdit(
|
||||
|
|
|
@ -38,26 +38,4 @@ class VisualEditorHooks {
|
|||
);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents editing in the VisualEditor namespace by non-sysop users.
|
||||
*
|
||||
* This is attached to the MediaWiki 'userCan' hook.
|
||||
*/
|
||||
public static function onUserCan( &$title, &$user, $action, &$result ) {
|
||||
global $wgUser, $wgNamespaceProtection;
|
||||
|
||||
if ( array_key_exists( $title->mNamespace, $wgNamespaceProtection ) ) {
|
||||
$nsProt = $wgNamespaceProtection[$title->mNamespace];
|
||||
if ( !is_array( $nsProt ) ) {
|
||||
$nsProt = array( $nsProt );
|
||||
}
|
||||
foreach( $nsProt as $right ) {
|
||||
if ( $right != '' && !$user->isAllowed( $right ) ) {
|
||||
$result = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -108,6 +108,7 @@ $wgResourceModules += array(
|
|||
'copyrightwarning',
|
||||
'copyrightpage',
|
||||
'edit',
|
||||
'create',
|
||||
'accesskey-ca-edit',
|
||||
'tooltip-ca-edit',
|
||||
'viewsource'
|
||||
|
@ -283,5 +284,4 @@ $wgAPIModules['ve-parsoid'] = 'ApiVisualEditor';
|
|||
// Integration Hooks
|
||||
$wgAutoloadClasses['VisualEditorHooks'] = $dir . 'VisualEditor.hooks.php';
|
||||
$wgHooks['BeforePageDisplay'][] = 'VisualEditorHooks::onBeforePageDisplay';
|
||||
$wgHooks['userCan'][] = 'VisualEditorHooks::onUserCan';
|
||||
$wgHooks['MakeGlobalVariablesScript'][] = 'VisualEditorHooks::onMakeGlobalVariablesScript';
|
||||
|
|
|
@ -599,7 +599,7 @@ return;
|
|||
from + sourceNode.model.getOuterLength()
|
||||
);
|
||||
tx = ve.dm.Transaction.newFromRemoval( this.documentView.model, range );
|
||||
this.model.transact( tx );
|
||||
this.model.change( tx );
|
||||
}
|
||||
} else {
|
||||
// selection removal
|
||||
|
|
|
@ -373,6 +373,10 @@ ve.dm.Converter.prototype.getDataFromDom = function( domElement, annotations, da
|
|||
if ( dataElement ) {
|
||||
data.push( { 'type': '/' + dataElement.type } );
|
||||
}
|
||||
// Don't return an empty document
|
||||
if ( branchType === 'document' && data.length === 0 ) {
|
||||
return [{ 'type': 'paragraph' }, { 'type': '/paragraph' }];
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
*/
|
||||
ve.init.ViewPageTarget = function() {
|
||||
// Inheritance
|
||||
ve.init.Target.call( this, mw.config.get( 'wgPageName' ) );
|
||||
ve.init.Target.call( this, mw.config.get( 'wgRelevantPageName' ) );
|
||||
|
||||
// Properties
|
||||
this.$surface = $( '<div class="ve-surface"></div>' );
|
||||
|
@ -21,9 +21,25 @@ ve.init.ViewPageTarget = function() {
|
|||
this.activating = false;
|
||||
this.deactivating = false;
|
||||
this.scrollTop = null;
|
||||
this.section = null;
|
||||
this.proxiedOnSurfaceModelTransact = ve.proxy( this.onSurfaceModelTransact, this );
|
||||
this.surfaceOptions = { 'toolbars': { 'top': { 'float': !this.isMobileDevice } } };
|
||||
this.currentUri = new mw.Uri( window.location.toString() );
|
||||
this.section = this.currentUri.query.vesection || null;
|
||||
this.namespaceName = mw.config.get( 'wgCanonicalNamespace' );
|
||||
this.viewUri = new mw.Uri( mw.util.wikiGetlink( this.pageName ) );
|
||||
this.editUri = new mw.Uri( this.viewUri.toString() );
|
||||
this.editUri.extend( { 'action': 'edit' } );
|
||||
this.veEditUri = new mw.Uri( this.viewUri.toString() );
|
||||
this.veEditUri.extend( { 'veaction': 'edit' } );
|
||||
this.isViewPage = (
|
||||
this.namespaceName === 'VisualEditor' &&
|
||||
mw.config.get( 'wgAction' ) === 'view' &&
|
||||
this.currentUri.query.diff === undefined
|
||||
);
|
||||
this.canBeActivated = (
|
||||
this.namespaceName === 'VisualEditor' ||
|
||||
this.pageName.substr( 0, 13 ) === 'VisualEditor:'
|
||||
);
|
||||
|
||||
// Events
|
||||
this.addListenerMethods( this, {
|
||||
|
@ -34,21 +50,16 @@ ve.init.ViewPageTarget = function() {
|
|||
} );
|
||||
|
||||
// Initialization
|
||||
var uri = new mw.Uri( window.location.toString() );
|
||||
if ( mw.config.get( 'wgCanonicalNamespace' ) === 'VisualEditor' ) {
|
||||
if ( mw.config.get( 'wgAction' ) === 'view' && uri.query.diff === undefined ) {
|
||||
this.setupSkinTabs();
|
||||
this.setupSectionEditLinks();
|
||||
if ( this.canBeActivated ) {
|
||||
this.setupSkinTabs();
|
||||
this.setupSectionEditLinks();
|
||||
if ( this.isViewPage ) {
|
||||
this.setupToolbarSaveButton();
|
||||
this.setupSaveDialog();
|
||||
if ( uri.query.veaction === 'edit' ) {
|
||||
if ( this.currentUri.query.veaction === 'edit' ) {
|
||||
this.activate();
|
||||
}
|
||||
} else {
|
||||
this.setupSkinTabs();
|
||||
}
|
||||
} else if ( mw.config.get( 'wgRelevantPageName' ).substr( 0, 13 ) === 'VisualEditor:' ) {
|
||||
this.setupSkinTabs();
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -109,9 +120,10 @@ ve.init.ViewPageTarget.prototype.activate = function() {
|
|||
*
|
||||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.deactivate = function() {
|
||||
ve.init.ViewPageTarget.prototype.deactivate = function( override ) {
|
||||
if ( this.active && !this.deactivating ) {
|
||||
if (
|
||||
override ||
|
||||
!this.surface.getModel().getHistory().length ||
|
||||
confirm( 'Are you sure you want to go back to view mode without saving first?' )
|
||||
) {
|
||||
|
@ -166,7 +178,7 @@ ve.init.ViewPageTarget.prototype.onLoadError = function( response, status, error
|
|||
ve.init.ViewPageTarget.prototype.onSave = function( html ) {
|
||||
this.hideSaveDialog();
|
||||
this.replacePageContent( html );
|
||||
this.deactivate();
|
||||
this.deactivate( true );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -201,7 +213,7 @@ ve.init.ViewPageTarget.prototype.onEditTabClick = function( event ) {
|
|||
* @param {Event} event DOM event
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.onEditSectionLinkClick = function( event ) {
|
||||
this.saveEditingSection( $( event.target ).closest( 'h1, h2, h3, h4, h5, h6' )[0] );
|
||||
this.saveEditSection( $( event.target ).closest( 'h1, h2, h3, h4, h5, h6' )[0] );
|
||||
this.activate();
|
||||
// Prevent the edit tab's normal behavior
|
||||
event.preventDefault();
|
||||
|
@ -332,10 +344,12 @@ ve.init.ViewPageTarget.prototype.setupSkinTabs = function() {
|
|||
// Only sysop users will have an edit tab in this namespace, so we might need to add one
|
||||
if ( $( '#ca-edit' ).length === 0 ) {
|
||||
// Add edit tab
|
||||
var action = Number( mw.config.get( 'wgArticleId', 0 ) ) === 0 ?
|
||||
'create' : 'edit';
|
||||
mw.util.addPortletLink(
|
||||
'p-views',
|
||||
'#',
|
||||
mw.msg( 'edit' ),
|
||||
mw.msg( action ), // 'edit' or 'create'
|
||||
'ca-edit',
|
||||
mw.msg( 'tooltip-ca-edit' ),
|
||||
mw.msg( 'accesskey-ca-edit' ),
|
||||
|
@ -358,33 +372,27 @@ ve.init.ViewPageTarget.prototype.setupSkinTabs = function() {
|
|||
// Sysop users will need a new edit source tab since we are highjacking the edit tab
|
||||
mw.util.addPortletLink(
|
||||
'p-cactions',
|
||||
$( '#ca-edit a' ).attr( 'href' ),
|
||||
this.editUri,
|
||||
'Edit Source', // TODO: i18n
|
||||
'ca-editsource'
|
||||
);
|
||||
}
|
||||
var uri = new mw.Uri( window.location.toString() );
|
||||
if (
|
||||
mw.config.get( 'wgCanonicalNamespace' ) === 'VisualEditor' &&
|
||||
mw.config.get( 'wgAction' ) === 'view' &&
|
||||
uri.query.diff === undefined
|
||||
) {
|
||||
if ( this.isViewPage ) {
|
||||
// Allow instant-editing
|
||||
$( '#ca-edit a' ).click( ve.proxy( this.onEditTabClick, this ) );
|
||||
$( '#ca-view a, #ca-nstab-visualeditor a' ).click( ve.proxy( this.onViewTabClick, this ) );
|
||||
} else {
|
||||
var editUri = new mw.Uri( $( '#ca-edit a' ).attr( 'href' ) );
|
||||
delete editUri.query.action;
|
||||
editUri.query.veaction = 'edit';
|
||||
$( '#ca-edit a' ).attr( 'href', editUri );
|
||||
// Route edits through the view page
|
||||
$( '#ca-edit a' ).attr( 'href', this.veEditUri );
|
||||
}
|
||||
// Source editing shouldn't highlight the edit tab
|
||||
if ( mw.config.get( 'wgAction' ) === 'edit' ) {
|
||||
$( '#p-views' ).find( 'li.selected' ).removeClass( 'selected' );
|
||||
}
|
||||
// Fix the URL if there was a veaction param in it
|
||||
if ( uri.query.veaction === 'edit' && window.history.replaceState ) {
|
||||
if ( this.currentUri.query.veaction === 'edit' && window.history.replaceState ) {
|
||||
var title = $( 'head title' ).text();
|
||||
window.history.replaceState( null, title, $( '#ca-view a' ).attr( 'href' ) );
|
||||
window.history.replaceState( null, title, this.viewUri );
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -394,7 +402,18 @@ ve.init.ViewPageTarget.prototype.setupSkinTabs = function() {
|
|||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.setupSectionEditLinks = function() {
|
||||
$( '#mw-content-text .editsection a' ).click( ve.proxy( this.onEditSectionLinkClick, this ) );
|
||||
var $links = $( '#mw-content-text .editsection a' );
|
||||
if ( this.isViewPage ) {
|
||||
$links.click( ve.proxy( this.onEditSectionLinkClick, this ) );
|
||||
} else {
|
||||
var veEditUri = this.veEditUri;
|
||||
$links.each( function() {
|
||||
var veSectionEditUri = new mw.Uri( veEditUri.toString() ),
|
||||
sectionEditUri = new mw.Uri( $(this).attr( 'href' ) );
|
||||
veSectionEditUri.extend( { 'vesection': sectionEditUri.query.section } );
|
||||
$(this).attr( 'href', veSectionEditUri );
|
||||
} );
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -549,7 +568,10 @@ ve.init.ViewPageTarget.prototype.hideSpinner = function() {
|
|||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.showPageContent = function() {
|
||||
$( '#bodyContent' ).children().not( '#siteSub' ).show().fadeTo( 0, 1 );
|
||||
$( '#bodyContent .ve-init-viewPageTarget-content:not(#siteSub)' )
|
||||
.removeClass( 've-init-viewPageTarget-content' )
|
||||
.show()
|
||||
.fadeTo( 0, 1 );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -558,7 +580,9 @@ ve.init.ViewPageTarget.prototype.showPageContent = function() {
|
|||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.mutePageContent = function() {
|
||||
$( '#bodyContent' ).children().not( '#siteSub' ).fadeTo( 'fast', 0.25 );
|
||||
$( '#bodyContent :visible:not(#siteSub)' )
|
||||
.addClass( 've-init-viewPageTarget-content' )
|
||||
.fadeTo( 'fast', 0.6 );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -567,7 +591,9 @@ ve.init.ViewPageTarget.prototype.mutePageContent = function() {
|
|||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.hidePageContent = function() {
|
||||
$( '#bodyContent' ).children().not( '#siteSub' ).hide();
|
||||
$( '#bodyContent :visible:not(#siteSub)' )
|
||||
.addClass( 've-init-viewPageTarget-content' )
|
||||
.hide();
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -667,8 +693,7 @@ ve.init.ViewPageTarget.prototype.transformPageTitle = function() {
|
|||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.mutePageTitle = function() {
|
||||
$( '#firstHeading' ).fadeTo( 'fast', 0.25 );
|
||||
$( '#siteSub' ).fadeTo( 'fast', 0.25 );
|
||||
$( '#firstHeading, #siteSub' ).fadeTo( 'fast', 0.6 );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -677,8 +702,7 @@ ve.init.ViewPageTarget.prototype.mutePageTitle = function() {
|
|||
* @method
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.restorePageTitle = function() {
|
||||
$( '#firstHeading' ).fadeTo( 'fast', 1 );
|
||||
$( '#siteSub' ).fadeTo( 'fast', 1 );
|
||||
$( '#firstHeading, #siteSub' ).fadeTo( 'fast', 1 );
|
||||
setTimeout( function() {
|
||||
$( '#firstHeading' ).removeClass( 've-init-viewPageTarget-pageTitle' );
|
||||
}, 1000 );
|
||||
|
@ -739,19 +763,26 @@ ve.init.ViewPageTarget.prototype.detachSurface = function() {
|
|||
* @method
|
||||
* @param {HTMLElement} heading Heading element of section
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.saveEditSection = function( heading ) {
|
||||
var $page = $( '#mw-content-text' );
|
||||
tocHeading = $page.find( '#toc h2' )[0];
|
||||
ve.init.ViewPageTarget.prototype.getEditSection = function( heading ) {
|
||||
var $page = $( '#mw-content-text' ),
|
||||
section = 0;
|
||||
$page.find( 'h1, h2, h3, h4, h5, h6' ).each( function() {
|
||||
$page.find( 'h1, h2, h3, h4, h5, h6' ).not( '#toc h2' ).each( function() {
|
||||
section++;
|
||||
if ( this === heading ) {
|
||||
return false;
|
||||
}
|
||||
if ( this !== tocHeading ) {
|
||||
section++;
|
||||
}
|
||||
} );
|
||||
this.section = section;
|
||||
return section;
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the numeric index of a section in the page.
|
||||
*
|
||||
* @method
|
||||
* @param {HTMLElement} heading Heading element of section
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.saveEditSection = function( heading ) {
|
||||
this.section = this.getEditSection( heading );
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -761,20 +792,20 @@ ve.init.ViewPageTarget.prototype.saveEditSection = function( heading ) {
|
|||
* @param {Number} section Section to move cursor to
|
||||
*/
|
||||
ve.init.ViewPageTarget.prototype.restoreEditSection = function() {
|
||||
if ( this.section ) {
|
||||
if ( this.section !== null ) {
|
||||
var surfaceView = this.surface.getView(),
|
||||
surfaceModel = surfaceView.getModel();
|
||||
this.$surface
|
||||
.find( '.ve-ce-documentNode' )
|
||||
.find( 'h1, h2, h3, h4, h5, h6' )
|
||||
.eq( this.section )
|
||||
.eq( this.section - 1 )
|
||||
.each( function() {
|
||||
var headingNode = $(this).data( 'node' );
|
||||
if ( headingNode ) {
|
||||
var offset = surfaceModel.getDocument().getNearestContentOffset(
|
||||
headingNode.getModel().getOffset()
|
||||
);
|
||||
surfaceModel.setSelection( new ve.Range( offset, offset ) );
|
||||
surfaceModel.change( null, new ve.Range( offset, offset ) );
|
||||
surfaceView.showSelection( surfaceModel.getSelection() );
|
||||
}
|
||||
} );
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
*
|
||||
* @class
|
||||
* @constructor
|
||||
* @param {String} title Page title of target
|
||||
* @param {String} pageName Name of target page
|
||||
*/
|
||||
ve.init.Target = function( title ) {
|
||||
ve.init.Target = function( pageName ) {
|
||||
// Inheritance
|
||||
ve.EventEmitter.call( this );
|
||||
|
||||
// Properties
|
||||
this.title = title;
|
||||
this.pageName = pageName;
|
||||
this.editToken = mw.user.tokens.get( 'editToken' );
|
||||
this.apiUrl = mw.util.wikiScript( 'api' );
|
||||
this.modules = ['ext.visualEditor.core'];
|
||||
|
@ -101,7 +101,7 @@ ve.init.Target.onLoadError = function( response, text, exception ) {
|
|||
ve.init.Target.onSave = function( response, status ) {
|
||||
this.saving = false;
|
||||
var data = response['ve-parsoid'];
|
||||
if ( !response ) {
|
||||
if ( !data ) {
|
||||
this.emit( 'saveError', 'Invalid response from server' );
|
||||
} else if ( data.result !== 'success' ) {
|
||||
this.emit( 'saveError', 'Unsuccessful request: ' + data.result );
|
||||
|
@ -161,7 +161,7 @@ ve.init.Target.prototype.load = function( callback ) {
|
|||
'data': {
|
||||
'action': 've-parsoid',
|
||||
'paction': 'parse',
|
||||
'page': this.title,
|
||||
'page': this.pageName,
|
||||
'format': 'json'
|
||||
},
|
||||
'dataType': 'json',
|
||||
|
@ -211,7 +211,7 @@ ve.init.Target.prototype.save = function( dom, options, callback ) {
|
|||
'format': 'json',
|
||||
'action': 've-parsoid',
|
||||
'paction': 'save',
|
||||
'page': this.title,
|
||||
'page': this.pageName,
|
||||
'html': $( dom ).html(),
|
||||
'token': this.editToken,
|
||||
'summary': options.summary,
|
||||
|
|
|
@ -74,7 +74,7 @@ ve.FormatDropdownTool.prototype.onSelect = function( item ) {
|
|||
item.type,
|
||||
item.attributes
|
||||
);
|
||||
model.transact ( txs );
|
||||
model.change( txs );
|
||||
surfaceView.showSelection( selection );
|
||||
};
|
||||
|
||||
|
|
|
@ -50,7 +50,7 @@ ve.ui.IndentationButtonTool.prototype.indent = function( listItems ) {
|
|||
'styles',
|
||||
styles.concat( styles[styles.length - 1] )
|
||||
);
|
||||
surface.model.transact( tx );
|
||||
surface.model.change( tx );
|
||||
}
|
||||
}
|
||||
surface.emitCursor();
|
||||
|
@ -69,7 +69,7 @@ ve.ui.IndentationButtonTool.prototype.outdent = function( listItems ) {
|
|||
'styles',
|
||||
styles.slice( 0, styles.length - 1 )
|
||||
);
|
||||
surface.model.transact( tx );
|
||||
surface.model.change( tx );
|
||||
}
|
||||
}
|
||||
surface.emitCursor();
|
||||
|
|
|
@ -83,7 +83,7 @@ ve.ui.ListButtonTool.prototype.unlist = function( node ){
|
|||
[]
|
||||
);
|
||||
|
||||
model.transact ( tx );
|
||||
model.change( tx );
|
||||
|
||||
};
|
||||
ve.ui.ListButtonTool.prototype.onClick = function() {
|
||||
|
|
|
@ -35,17 +35,19 @@ test( 'setSelection', 1, function() {
|
|||
surface.setSelection( new ve.Range( 1, 1 ) );
|
||||
} );
|
||||
|
||||
test( 'transact', 1, function() {
|
||||
test( 'change', 2, function() {
|
||||
var surface = new ve.dm.SurfaceStub();
|
||||
var tx = new ve.dm.Transaction();
|
||||
surface.on( 'transact', function() {
|
||||
ok( true, 'transact was emitted' );
|
||||
} );
|
||||
surface.transact( tx );
|
||||
surface.on( 'change', function() {
|
||||
ok( true, 'change was emitted' );
|
||||
} );
|
||||
surface.change( tx );
|
||||
} );
|
||||
|
||||
|
||||
test('annotate', 1, function(){
|
||||
test( 'annotate', 1, function() {
|
||||
var surface,
|
||||
cases = [
|
||||
{
|
||||
|
@ -105,4 +107,4 @@ test('annotate', 1, function(){
|
|||
);
|
||||
|
||||
}
|
||||
});
|
||||
} );
|
||||
|
|
Loading…
Reference in a new issue