Edit check/TextMatch
A wiki community can create custom local suggestions using TextMatch. TextMatch is an edit check that searches for predetermined queries and, when a match is found, it displays the regular edit check message-box, along with the message, title, and potential actions for the editor to make.
For example, a TextMatch might provide an option to delete the matched term, or to replace it in a specified way, or just to encourage the editor to think about it. TextMatch checks can be very simple, or can be made more powerful with the configuration options.
Here are two examples. The first detects a potential relative-time phrase and links to the related guidance. The second detects some potential punctuation errors and provides a button to fix them.
Current limitations
[edit]As of July 2026:
- TextMatch will not yet detect content within templates.
There is no way to exclude lists or other code tags from matching, nor to limit content to just lists, tables, headings, etc.SeeinNodebelow.- See Regex queries for more details on regex-specific limitations.
- Open bugs and feature-requests: Phabricator search
Configuration
[edit]TextMatch's configuration consists of the normal Edit check/Configuration, and a number of matchRules.
Each matchRule consists of something to search for and a description of what should be done when that thing is found.
The matchRule definition is fairly flexible, and can accommodate anything from finding a simple word and showing a provided warning, to finding a complicated set of regular expressions and replacing them with something that varies based on what was found.
See the #Example configuration section below for practical demonstrations of these cases.
| Name | Required? | Type | Description | Default |
|---|---|---|---|---|
unique string id
|
Required | String | The short-name of the specific TextMatch | |
query
|
Required | Array or Object | What to search for. This can be in various formats:
Note that any matches must begin and end at word boundaries. For example, if the query is "foo", a match would not be detected in "foobar". This applies to both regex and non-regex matchRules. TextMatch uses the same JavaScript regular expressions that is used in VisualEditor's find/replace feature. |
|
title
|
Required | String | What will be displayed to users in the edit check dialog. This should only include plain text. | |
message
|
Required | String | What will be displayed to users in the edit check dialog. This can include wiki links, and should point the user to any relevant documentation so they can learn more. | |
mode
|
Optional | String | What actions (buttons) should be provided in the edit check dialog. Currently available modes include: "info" (just "dismiss"), "replace" ("replace" and "dismiss"), "delete" ("delete" and "dismiss")
If the mode is unknown or undefined, then it will only show the "dismiss" button. |
""
|
isRegExp
|
Optional | Boolean | If true, TextMatch will treat this query as a regex pattern. See Regex queries for more details. | false
|
config
|
Optional | Object | Various configuration options that can operate on the matchRule level. These are added on top of any configuration that is applied to the entire group of TextMatch editchecks, which they will override.
In the future, we'd like to support more, such as: namespace, and specific page-name. |
|
inNode
|
Optional | String | Require the match to appear inside a node of this type. Node types are from the VisualEditor data model, e.g 'mwHeading' for headings, 'paragraph' for paragraphs. | |
expand
|
Optional | String | If a match is found, this option configures whether to expand the 'problem area' (the area that is highlighted) to surround more content, instead of just the matched text.
Available options are:
|
|
preserveCase
|
Optional | Boolean | If true, and if the matchRule is using mode: "replace", then the suggested replacement term will be in the same case as the matched term (limited to: title case, lowercase, and uppercase).
The case that the replacement has in the matchRule config is the lowest case that will ever be offered as a replacement. This is so that words like 'French' or 'USA' are never turned into invalid forms, even if replacing something fully lowercased. As such, consider writing TextMatch replacements in lowercase unless the term requires specific casing.
|
false
|
import
|
Optional | String | You can define more complex matchRules in separate JSON pages and import them, to keep the main JSON page shorter. (example) Pages must be named MediaWiki:Editcheck-config-<name>.json e.g. "import": "MediaWiki:Editcheck-config-LLM.json"
|
Regex queries
[edit]There are some specific complexities for matchRules that use regex queries.
- Plain backreferences are not supported, due to the way that all regex patterns in a query are bundled together for performance reasons. The suggested workaround is to use named backreferences.
- When using a regex pattern with alternation, order the alternatives from longest to shortest (e.g., use
"enhanc(ed|es|e|ing)"rather than"enhanc(e|ed|es|ing)") . This way the regex matches the full word before any shorter alternative can match a partial word that then fails the word-boundary check.[1]
Regex queries can always be tested using VisualEditor's "find and replace" tool (with the appropriate modifiers enabled). This is helpful to understand what it will and will not support.
- ↑ This is due to all TextMatch rules using a
wholeWordflag that restricts matches to those surrounded by word boundaries. As of June 2026 we are considering making this property configurable.
Testing instructions
[edit]TextMatch is part of the current Suggestion Mode Beta Feature which is available on all Wikipedias (see Deployment status).
To show the Experimental types of checks and suggestions, you can add the &ecenable=experimental URL parameter to an existing VisualEditor edit session.
To test a new type of TextMatch:
- Visit a wiki where TextMatchEditCheck is available and you have admin role. Login.
- On said wiki, visit
MediaWiki:Editcheck-config.json - Tap edit
- Insert JSON from the Example configuration or some custom configs that follow the same format.
- If there’s already JSON present, only copy from "textMatch"; not the outermost curly braces
- Visit an article on that same wiki that is likely to contain one of the matches listed in the JSON
- Open a VisualEditor edit session using the
&ecenable=suggestions,experimentalURL parameter
Example configuration
[edit]Here is an example of what could be configured:
{
"textMatch": {
"enabled": true,
"matchRules": {
"british-english": {
"query": {
"chiseled": "chiselled",
"favor(ed|ite|ing)": "favour$1",
"somberly": "sombrely"
},
"title": "American English",
"mode": "replace",
"isRegExp": true,
"preserveCase": true,
"message": "This article requires British English. Fix?",
"config": {
"maximumEditCount": 500,
"account": "loggedin",
"hasTemplate": [
"Use British English",
"EngvarB"
]
}
},
"potential-LLM": {
"query": [
"(stands as|serves as|is) a (testament|reminder)",
"indelible mark",
"important to note",
"observers have cited"
],
"title": "Potential LLM content",
"message": "Is this LLM-generated content? Every edit that incorporates LLM output should be marked as LLM-assisted by identifying the name and, if possible, version of the AI in the edit summary.",
"isRegExp": true,
"config": {
"caseSensitive": false,
"minOccurrences": 3
},
"expand": "paragraph"
},
"cliches": {
"query": [
"tip of the iceberg",
"white elephant",
"gild the lily",
"take the plunge",
"took the plunge",
"ace up the sleeve",
"bird in the hand",
"twist of fate",
"at the end of the day"
],
"title": "Cliches and idioms",
"message": "Clichés and idioms should generally be avoided in favor of direct, literal expressions.",
"config": {
"account": false
}
},
"relative-time-ref": {
"query": [
"recently",
"lately",
"currently",
"today",
"presently",
"to date",
"years ago",
"formerly",
"in the past",
"traditionally",
"yesterday",
"tomorrow",
"in the future",
"to this day"
],
"title": "Relative time references",
"message": "Absolute specifications of time are preferred to relative constructions such as this, because the latter may go out of date.",
"config": {
"account": false
}
},
"editorializing": {
"query": [
"notably",
"it should be noted",
"arguably",
"interestingly",
"essentially",
"utterly",
"actually",
"clearly",
"absolutely",
"of course",
"without a doubt",
"indeed",
"happily",
"sadly",
"tragically",
"aptly",
"unfortunately",
"untimely"
],
"title": "Editorializing",
"mode": "delete",
"message": "Use of adverbs such as these, to highlight something as particularly significant or certain without attributing that opinion, should usually be avoided so as to maintain an impartial tone.",
"config": {
"account": false
}
},
"puffery": {
"query": [
"legendary",
"greatest",
"acclaimed",
"iconic",
"visionary",
"outstanding",
"leading",
"celebrated",
"popular",
"landmark",
"cutting-edge",
"innovative",
"revolutionary",
"extraordinary",
"brilliant",
"famous",
"renowned",
"remarkable",
"prestigious",
"world-class",
"respected",
"notable",
"virtuoso",
"honorable",
"awesome",
"unique",
"pioneering",
"phenomenal",
"prominent"
],
"title": "Puffery",
"mode": "delete",
"message": "Words such as these are often used without attribution to promote the subject of an article and should usually be avoided.",
"config": {
"account": false
}
}
}
}
}