File: BaseEditCheck.js

package info (click to toggle)
mediawiki 1%3A1.43.3%2Bdfsg-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 417,464 kB
  • sloc: php: 1,062,949; javascript: 664,290; sql: 9,714; python: 5,458; xml: 3,489; sh: 1,131; makefile: 64
file content (141 lines) | stat: -rw-r--r-- 4,656 bytes parent folder | download | duplicates (2)
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 );
};