1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
mw.editcheck.BaseEditCheck = function MWBaseEditCheck( config ) {
this.config = config;
};
OO.initClass( mw.editcheck.BaseEditCheck );
mw.editcheck.BaseEditCheck.static.onlyCoveredNodes = false;
mw.editcheck.BaseEditCheck.static.choices = [
{
action: 'accept',
label: ve.msg( 'editcheck-dialog-action-yes' ),
icon: 'check'
},
{
action: 'reject',
label: ve.msg( 'editcheck-dialog-action-no' ),
icon: 'close'
}
];
mw.editcheck.BaseEditCheck.static.description = ve.msg( 'editcheck-dialog-addref-description' );
/**
* @param {ve.dm.Surface} surfaceModel
* @return {mw.editcheck.EditCheckAction[]}
*/
mw.editcheck.BaseEditCheck.prototype.onBeforeSave = null;
/**
* @param {ve.dm.Surface} surfaceModel
* @return {mw.editcheck.EditCheckAction[]}
*/
mw.editcheck.BaseEditCheck.prototype.onDocumentChange = null;
/**
* @param {string} choice `action` key from static.choices
* @param {mw.editcheck.EditCheckAction} action
* @param {ve.ui.EditCheckContextItem} contextItem
*/
mw.editcheck.BaseEditCheck.prototype.act = null;
/**
* @param {mw.editcheck.EditCheckAction} action
* @return {Object[]}
*/
mw.editcheck.BaseEditCheck.prototype.getChoices = function () {
return this.constructor.static.choices;
};
/**
* @param {mw.editcheck.EditCheckAction} action
* @return {string}
*/
mw.editcheck.BaseEditCheck.prototype.getDescription = function () {
return this.constructor.static.description;
};
/**
* Find out whether the check should be applied
*
* This is a general check for its applicability to the viewer / page, rather
* than a specific check based on the current edit. It's used to filter out
* checks before any maybe-expensive content analysis happens.
*
* @return {boolean} Whether the check should be shown
*/
mw.editcheck.BaseEditCheck.prototype.canBeShown = function () {
// all checks are only in the main namespace for now
if ( mw.config.get( 'wgNamespaceNumber' ) !== mw.config.get( 'wgNamespaceIds' )[ '' ] ) {
return false;
}
// some checks are configured to only be for logged in / out users
if ( mw.editcheck.ecenable ) {
return true;
}
// account status:
// loggedin, loggedout, or any-other-value meaning 'both'
// we'll count temporary users as "logged out" by using isNamed here
if ( this.config.account === 'loggedout' && mw.user.isNamed() ) {
return false;
}
if ( this.config.account === 'loggedin' && !mw.user.isNamed() ) {
return false;
}
// some checks are only shown for newer users
if ( this.config.maximumEditcount && mw.config.get( 'wgUserEditCount', 0 ) > this.config.maximumEditcount ) {
return false;
}
return true;
};
/**
* Get content ranges where at least the minimum about of text has been changed
*
* @param {ve.dm.Document} documentModel
* @return {ve.Range[]}
*/
mw.editcheck.BaseEditCheck.prototype.getModifiedContentRanges = function ( documentModel ) {
return mw.editcheck.getModifiedRanges( documentModel, this.constructor.static.onlyCoveredNodes )
.filter(
( range ) => range.getLength() >= this.config.minimumCharacters &&
this.isRangeInValidSection( range, documentModel )
);
};
/**
* Check if a modified range is a section we don't ignore (config.ignoreSections)
*
* @param {ve.Range} range
* @param {ve.dm.Document} documentModel
* @return {boolean}
*/
mw.editcheck.BaseEditCheck.prototype.isRangeInValidSection = function ( range, documentModel ) {
const ignoreSections = this.config.ignoreSections || [];
if ( ignoreSections.length === 0 && !this.config.ignoreLeadSection ) {
// Nothing is forbidden, so everything is permitted
return true;
}
const isHeading = ( nodeType ) => nodeType === 'mwHeading';
// Note: we set a limit of 1 here because otherwise this will turn around
// to keep looking when it hits the document boundary:
const heading = documentModel.getNearestNodeMatching( isHeading, range.start, -1, 1 );
if ( !heading ) {
// There's no preceding heading, so work out if we count as being in a
// lead section. It's only a lead section if there's more headings
// later in the document, otherwise it's just a stub article.
return !(
this.config.ignoreLeadSection &&
!!documentModel.getNearestNodeMatching( isHeading, range.start, 1 )
);
}
if ( ignoreSections.length === 0 ) {
// There's nothing left to deny
return true;
}
const compare = new Intl.Collator( documentModel.getLang(), { sensitivity: 'accent' } ).compare;
const headingText = documentModel.data.getText( false, heading.getRange() );
// If the heading text matches any of ignoreSections, return false.
return !ignoreSections.some( ( section ) => compare( headingText, section ) === 0 );
};
|