Edit check: move some methods into BaseEditCheck

This is mostly cleanup from 4cd67004d removing Diff, which was the
original caller of the moved functions.

Change-Id: I015cb310527d9e7593e4ba6ac15ac204435d9ab4
This commit is contained in:
David Lynch 2024-11-25 10:46:02 -06:00
parent d2134d7df2
commit 2c73af983e
3 changed files with 99 additions and 79 deletions

View file

@ -104,11 +104,97 @@ mw.editcheck.BaseEditCheck.prototype.canBeShown = function () {
* @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 )
);
return this.getModifiedRanges( documentModel, this.constructor.static.onlyCoveredNodes, true );
};
/**
* Get content ranges which have been inserted
*
* @param {ve.dm.Document} documentModel
* @param {boolean} coveredNodesOnly Only include ranges which cover the whole of their node
* @param {boolean} onlyContentRanges Only return ranges which are content branch node interiors
* @return {ve.Range[]}
*/
mw.editcheck.BaseEditCheck.prototype.getModifiedRanges = function ( documentModel, coveredNodesOnly, onlyContentRanges ) {
if ( !documentModel.completeHistory.getLength() ) {
return [];
}
let operations;
try {
operations = documentModel.completeHistory.squash().transactions[ 0 ].operations;
} catch ( err ) {
// TransactionSquasher can sometimes throw errors; until T333710 is
// fixed just count this as not needing a reference.
mw.errorLogger.logError( err, 'error.visualeditor' );
return [];
}
const ranges = [];
let offset = 0;
const endOffset = documentModel.getDocumentRange().end;
operations.every( ( op ) => {
if ( op.type === 'retain' ) {
offset += op.length;
} else if ( op.type === 'replace' ) {
const insertedRange = new ve.Range( offset, offset + op.insert.length );
offset += op.insert.length;
// 1. Only trigger if the check is a pure insertion, with no adjacent content removed (T340088)
if ( op.remove.length === 0 ) {
if ( onlyContentRanges ) {
ve.batchPush(
ranges,
// 2. Only fully inserted paragraphs (ranges that cover the whole node) (T345121)
this.getContentRangesFromRange( documentModel, insertedRange, coveredNodesOnly )
);
} else {
ranges.push( insertedRange );
}
}
}
// Reached the end of the doc / start of internal list, stop searching
return offset < endOffset;
} );
return ranges.filter( ( range ) => this.isRangeValid( range, documentModel ) );
};
/**
* Return the content ranges (content branch node interiors) contained within a range
*
* For a content branch node entirely contained within the range, its entire interior
* range will be included. For a content branch node overlapping with the range boundary,
* only the covered part of its interior range will be included.
*
* @param {ve.dm.Document} documentModel The documentModel to search
* @param {ve.Range} range The range to include
* @param {boolean} covers Only include ranges which cover the whole of their node
* @return {ve.Range[]} The contained content ranges (content branch node interiors)
*/
mw.editcheck.BaseEditCheck.prototype.getContentRangesFromRange = function ( documentModel, range, covers ) {
const ranges = [];
documentModel.selectNodes( range, 'branches' ).forEach( ( spec ) => {
if (
spec.node.canContainContent() && (
!covers || (
!spec.range || // an empty range means the node is covered
spec.range.equalsSelection( spec.nodeRange )
)
)
) {
ranges.push( spec.range || spec.nodeRange );
}
} );
return ranges;
};
/**
* Test whether the range is valid for the check to apply
*
* @param {ve.Range} range
* @param {ve.dm.Document} documentModel
* @return {boolean}
*/
mw.editcheck.BaseEditCheck.prototype.isRangeValid = function ( range, documentModel ) {
return this.isRangeInValidSection( range, documentModel );
};
/**

View file

@ -114,6 +114,14 @@ mw.editcheck.AddReferenceEditCheck.prototype.act = function ( choice, action, co
}
};
/**
* @inheritdoc
*/
mw.editcheck.AddReferenceEditCheck.prototype.isRangeValid = function ( range, documentModel ) {
return range.getLength() >= ( this.config.minimumCharacters || 0 ) &&
mw.editcheck.AddReferenceEditCheck.super.prototype.isRangeValid.call( this, range, documentModel );
};
/**
* Adjust a fragment to include/exclude trailing punctuation
*

View file

@ -15,35 +15,6 @@ require( './BaseEditCheck.js' );
// require( './editchecks/TextMatchEditCheck.js' );
require( './editchecks/AddReferenceEditCheck.js' );
/**
* Return the content ranges (content branch node interiors) contained within a range
*
* For a content branch node entirely contained within the range, its entire interior
* range will be included. For a content branch node overlapping with the range boundary,
* only the covered part of its interior range will be included.
*
* @param {ve.dm.Document} documentModel The documentModel to search
* @param {ve.Range} range The range to include
* @param {boolean} covers Only include ranges which cover the whole of their node
* @return {ve.Range[]} The contained content ranges (content branch node interiors)
*/
mw.editcheck.getContentRanges = function ( documentModel, range, covers ) {
const ranges = [];
documentModel.selectNodes( range, 'branches' ).forEach( ( spec ) => {
if (
spec.node.canContainContent() && (
!covers || (
!spec.range || // an empty range means the node is covered
spec.range.equalsSelection( spec.nodeRange )
)
)
) {
ranges.push( spec.range || spec.nodeRange );
}
} );
return ranges;
};
/**
* Check if the document has content needing a reference, for AddReferenceEditCheck
*
@ -62,51 +33,6 @@ mw.editcheck.hasAddedContentNeedingReference = function ( documentModel, include
return check.findAddedContent( documentModel, includeReferencedContent ).length > 0;
};
/**
* Get content ranges which have been inserted
*
* @param {ve.dm.Document} documentModel
* @param {boolean} coveredNodesOnly Only include ranges which cover the whole of their node
* @return {ve.Range[]}
*/
mw.editcheck.getModifiedRanges = function ( documentModel, coveredNodesOnly ) {
if ( !documentModel.completeHistory.getLength() ) {
return [];
}
let operations;
try {
operations = documentModel.completeHistory.squash().transactions[ 0 ].operations;
} catch ( err ) {
// TransactionSquasher can sometimes throw errors; until T333710 is
// fixed just count this as not needing a reference.
mw.errorLogger.logError( err, 'error.visualeditor' );
return [];
}
const ranges = [];
let offset = 0;
const endOffset = documentModel.getDocumentRange().end;
operations.every( ( op ) => {
if ( op.type === 'retain' ) {
offset += op.length;
} else if ( op.type === 'replace' ) {
const insertedRange = new ve.Range( offset, offset + op.insert.length );
offset += op.insert.length;
// 1. Only trigger if the check is a pure insertion, with no adjacent content removed (T340088)
if ( op.remove.length === 0 ) {
ve.batchPush(
ranges,
// 2. Only fully inserted paragraphs (ranges that cover the whole node) (T345121)
mw.editcheck.getContentRanges( documentModel, insertedRange, coveredNodesOnly )
);
}
}
// Reached the end of the doc / start of internal list, stop searching
return offset < endOffset;
} );
return ranges;
};
mw.editcheck.rejections = [];
mw.editcheck.getRejectionReasons = function () {