This repository contains a modified version of the frontend scripts and styles from MediaWiki extension CodeMirror. The goal is to support a standalone integration between CodeMirror and Wikitext, without the need for a MediaWiki environment.
Here is a demo. To experiment with the RTL (right-to-left) support, you can append ?rtl=1
to the URL.
Nonetheless, this repository also provides a customized version with additional functionality for use on a MediaWiki site. Browser editing tools such as Wikiplus-highlight and an InPageEdit plugin are built upon it. Please refer to a separate README file for the information.
Expand
You can install the package via npm and import it as a module:
npm install @bhsd/codemirror-mediawiki
import {
CodeMirror6,
registerMediaWiki,
registerHTML,
registerCSS,
registerJavaScript,
registerJSON,
registerLua,
registerVue,
} from '@bhsd/codemirror-mediawiki';
Expand
You can download the code via CDN, for example:
// static import
import {
CodeMirror6,
registerMediaWiki,
registerHTML,
registerCSS,
registerJavaScript,
registerJSON,
registerLua,
registerVue,
} from 'https://cdn.jsdelivr.net/npm/@bhsd/codemirror-mediawiki';
or
import {
CodeMirror6,
registerMediaWiki,
registerHTML,
registerCSS,
registerJavaScript,
registerJSON,
registerLua,
registerVue,
} from 'https://unpkg.com/@bhsd/codemirror-mediawiki';
or
// dynamic import
const {
CodeMirror6,
registerMediaWiki,
registerHTML,
registerCSS,
registerJavaScript,
registerJSON,
registerLua,
registerVue,
} = await import('https://cdn.jsdelivr.net/npm/@bhsd/codemirror-mediawiki');
or
const {
CodeMirror6,
registerMediaWiki,
registerHTML,
registerCSS,
registerJavaScript,
registerJSON,
registerLua,
registerVue,
} = await import('https://unpkg.com/@bhsd/codemirror-mediawiki');
Expand
The CSS mode contains a dialect for Extension:TemplateStyles. You can bundle the CSS mode by importing the registerCSS
function:
import {registerCSS} from '@bhsd/codemirror-mediawiki';
registerCSS();
If you want a more granular control over the extensions, you can import the registerCSSCore
function and the desired extensions:
import {registerCSSCore} from '@bhsd/codemirror-mediawiki';
registerCSSCore();
In addition to the common extensions, here are some CSS-specific extensions. Note that these extensions may not take effect if the corresponding common extensions are not registered:
import {registerColorPickerForCSS} from '@bhsd/codemirror-mediawiki';
registerColorPickerForCSS();
Expand
This is a mixed MediaWiki-HTML mode, which is used for Extension:Widgets. You can bundle the HTML mode by importing the registerHTML
function:
import {registerHTML} from '@bhsd/codemirror-mediawiki';
registerHTML();
If you want a more granular control over the extensions, you can import the registerHTMLCore
function and the desired extensions:
import {registerHTMLCore} from '@bhsd/codemirror-mediawiki';
registerHTMLCore();
In addition to the common extensions, here are some HTML-specific extensions. Note that these extensions may not take effect if the corresponding common extensions are not registered:
import {
registerCloseBracketsForHTML,
registerColorPickerForHTML,
} from '@bhsd/codemirror-mediawiki';
registerCloseBracketsForHTML();
registerColorPickerForHTML();
Expand
You can bundle the JavaScript mode by importing the registerJavaScript
function:
import {registerJavaScript} from '@bhsd/codemirror-mediawiki';
registerJavaScript();
If you want a more granular control over the extensions, you can import the registerJavaScriptCore
function and the desired extensions:
import {registerJavaScriptCore} from '@bhsd/codemirror-mediawiki';
registerJavaScriptCore();
Expand
You can bundle the JSON mode by importing the registerJSON
function:
import {registerJSON} from '@bhsd/codemirror-mediawiki';
registerJSON();
If you want a more granular control over the extensions, you can import the registerJSONCore
function and the desired extensions:
import {registerJSONCore} from '@bhsd/codemirror-mediawiki';
registerJSONCore();
Expand
You can bundle the Lua mode by importing the registerLua
function:
import {registerLua} from '@bhsd/codemirror-mediawiki';
registerLua();
If you want a more granular control over the extensions, you can import the registerLuaCore
function and the desired extensions:
import {registerLuaCore} from '@bhsd/codemirror-mediawiki';
registerLuaCore();
Expand
You can bundle the MediaWiki mode by importing the registerMediaWiki
function:
import {registerMediaWiki} from '@bhsd/codemirror-mediawiki';
registerMediaWiki();
If you want a more granular control over the extensions, you can import the registerMediaWikiCore
function and the desired extensions:
import {registerMediaWikiCore} from '@bhsd/codemirror-mediawiki';
registerMediaWikiCore();
In addition to the common extensions, here are some MediaWiki-specific extensions. Note that these extensions may not take effect if the corresponding common extensions are not registered:
import {
registerColorPickerForMediaWiki,
registerBracketMatchingForMediaWiki,
registerCodeFoldingForMediaWiki
} from '@bhsd/codemirror-mediawiki';
registerColorPickerForMediaWiki();
registerBracketMatchingForMediaWiki();
registerCodeFoldingForMediaWiki();
Expand
You can bundle the Vue mode by importing the registerVue
function:
import {registerVue} from '@bhsd/codemirror-mediawiki';
registerVue();
If you want a more granular control over the extensions, you can import the registerVueCore
function and the desired extensions:
import {registerVueCore} from '@bhsd/codemirror-mediawiki';
registerVueCore();
In addition to the common extensions, here are some Vue-specific extensions. Note that these extensions may not take effect if the corresponding common extensions are not registered:
import {
registerCloseBracketsForVue,
registerColorPickerForVue,
} from '@bhsd/codemirror-mediawiki';
registerCloseBracketsForVue();
registerColorPickerForVue();
Expand
You can also register other languages by importing the registerLanguage
function:
import {registerLanguage} from '@bhsd/codemirror-mediawiki';
import {python} from '@codemirror/lang-python';
registerLanguage('python', python);
If you want a more granular control over the extensions, you can import the registerLanguageCore
function and the desired extensions:
import {registerLanguageCore} from '@bhsd/codemirror-mediawiki';
import {python} from '@codemirror/lang-python';
registerLanguageCore('python', python);
This is the default theme, which is a light theme.
Expand
This is a dark theme created by Takuya Matsuyama and 鬼影233. You need to register this theme before using it:
import {registerTheme, nord} from '@bhsd/codemirror-mediawiki';
registerTheme('nord', nord);
Expand
You can also register other themes by importing the registerTheme
function:
import {registerTheme} from '@bhsd/codemirror-mediawiki';
import {oneDark} from '@codemirror/theme-one-dark';
registerTheme('one-dark', oneDark);
Expand
param: HTMLTextAreaElement
the textarea element to be replaced by CodeMirror
param: string
the language mode to be used, default as plain text
param: unknown
the language configuration, only required for the MediaWiki mode and the mixed MediaWiki-HTML mode
param: boolean
whether to initialize immediately, default as true
let cm;
cm = new CodeMirror6(textarea); // plain text
cm = new CodeMirror6(textarea, 'mediawiki', mwConfig);
cm = new CodeMirror6(textarea, 'html', mwConfig);
cm = new CodeMirror6(textarea, 'css');
cm = new CodeMirror6(textarea, 'javascript');
cm = new CodeMirror6(textarea, 'json');
cm = new CodeMirror6(textarea, 'lua');
cm = new CodeMirror6(textarea, 'vue');
Expand
version added: 2.28.0
type: 'sanitized-css' | undefined
Only used for Extension:TemplateStyles as a dialect of the CSS mode.
Expand
version added: 2.0.14
type: string
The current language mode, read-only.
Expand
type: HTMLTextAreaElement
The textarea element replaced by CodeMirror, read-only.
Expand
type: EditorView | undefined
The CodeMirror EditorView instance, read-only.
Expand
version added: 2.1.3
type: boolean
Whether the editor is visible, read-only.
Expand
version added: 2.28.2
Destroy the instance. This method is irrevocable and not recommended for general use. Instead, you should call the toggle
method to hide the editor.
cm.destroy();
Expand
version added: 2.2.2
param: KeyBinding[]
the extra key bindings
Add extra key bindings. Need initialization first.
cm.extraKeys([
{key: 'Tab', run: () => console.log('Tab'), preventDefault: true},
]);
Expand
version added: 2.1.3
param: Record<string, any>
the optional linter configuration
returns: Promise<(state: EditorState) => Diagnostic[] | Promise<Diagnostic[]>>
Get the default linting function, which can be used as the argument of lint
.
const linter = await cm.getLinter(); // default linter configuration
const linterMediawiki = await cm.getLinter({include: true, i18n: 'zh-hans'}); // wikilint configuration
const linterJavaScript = await cm.getLinter({env, parserOptions, rules}); // ESLint configuration
const linterCSS = await cm.getLinter({rules}); // Stylelint configuration
Expand
version added: 2.4.2
param: number
position
returns: SyntaxNode | undefined
Get the syntax node at the given position.
const tree = cm.getNodeAt(0);
Expand
version added: 3.2.0
param: string
extension name
returns: boolean
Check if the editor enables the given extension.
const hasAutocompletion = cm.hasPreference('autocompletion');
Expand
version added: 2.11.1
param: unknown
the optional language configuration
Initialize the editor.
cm.initialize();
Expand
param: (state: EditorState) => Diagnostic[] | Promise<Diagnostic[]>
the linting function
Set the linting function.
cm.lint(({doc}) => [
/**
* @type {Diagnostic}
* @see https://codemirror.net/docs/ref/#lint.Diagnostic
*/
{
from: 0,
to: doc.toString().length,
message: 'error message',
severity: 'error',
},
]);
Expand
version added: 2.3.3
param: Record<string, string>
localization table
Set the localization table.
cm.localize({
'Find': '查找',
});
Expand
version added: 2.0.9
param: string[] | Record<string, boolean>
the extensions to enable
Set the preferred CodeMirror extensions. Available extensions are introduced later.
cm.prefer([
'allowMultipleSelections',
'autocompletion',
'bracketMatching',
'closeBrackets',
'codeFolding',
'highlightActiveLine',
'highlightSelectionMatches',
'highlightSpecialChars',
'highlightTrailingWhitespace',
'highlightWhitespace',
'scrollPastEnd',
// only available in CSS and MediaWiki modes
'colorPicker',
// only available in MediaWiki mode
'escape',
'hover',
'inlayHints',
'openLinks',
'refHover',
'signatureHelp',
]);
cm.prefer({
allowMultipleSelections: false,
autocompletion: false,
bracketMatching: false,
closeBrackets: false,
codeFolding: false,
highlightActiveLine: false,
highlightSelectionMatches: false,
highlightSpecialChars: false,
highlightTrailingWhitespace: false,
highlightWhitespace: false,
scrollPastEnd: false,
// only available in CSS and MediaWiki modes
colorPicker: false,
// only available in MediaWiki mode
escape: false,
hover: false,
inlayHints: false,
openLinks: false,
refHover: false,
signatureHelp: false,
});
Expand
version added: 2.6.2
param: number | {anchor: number, head: number}
the position or range to scroll to, default as the current cursor position
Scroll to the given position or range. Need initialization first.
cm.scrollTo();
Expand
version added: 2.1.8
param: string
new content
param: boolean
whether to force the content to be set in the read-only mode, default as false
Reset the content of the editor. Need initialization first.
cm.setContent('');
Expand
version added: 2.0.9
param: string
the indentation string, default as tab
Set the indentation string.
cm.setIndent(' '.repeat(2));
cm.setIndent('\t');
Expand
param: string
the language mode to be used, default as plain text
param: unknown
the optional language configuration
Set the language mode.
cm.setLanguage('mediawiki', mwConfig);
cm.setLanguage('html', mwConfig);
cm.setLanguage('css');
cm.setLanguage('javascript');
cm.setLanguage('json');
cm.setLanguage('lua');
cm.setLanguage('vue');
Expand
version added: 2.28.0
param: boolean
whether to enable line wrapping
Switch between line wrapping and no line wrapping.
cm.setLineWrapping(false);
cm.setLineWrapping(true);
Expand
version added: 3.3.0
param: string
the theme name
Set the theme of the editor. The default theme is light
, other themes need to be registered using the registerTheme
function first:
import {registerTheme, nord} from '@bhsd/codemirror-mediawiki';
registerTheme('nord', nord);
cm.setTheme('nord');
Expand
version added: 2.1.3
param: boolean
whether to show the editor, optional
Switch between the CodeMirror editor and the native textarea. Need initialization first.
cm.toggle();
cm.toggle(true); // show CodeMirror
cm.toggle(false); // hide CodeMirror
Expand
Refresh linting immediately.
Expand
version added: 2.4.7
param: Config
the WikiLint configuration
returns: MwConfig
Derive the configuration for the MediaWiki mode from WikiLint configuration.
const mwConfig = CodeMirror6.getMwConfig(config);
Expand
version added: 2.2.2
param: EditorView
the CodeMirror EditorView instance
param: (str: string, range: {from: number, to: number}) => string | [string, number, number?]
the replacement function
Replace the selected text with the return value of the replacement function.
CodeMirror6.replaceSelections(cm.view, str => str.toUpperCase());
Expand
version added: 2.1.11
Allow multiple selections. This extension also enables rectangular selections by holding down the Alt
key.
For granular control over the bundled extensions, you can import the registerAllowMultipleSelections
function:
import {registerAllowMultipleSelections} from '@bhsd/codemirror-mediawiki';
registerAllowMultipleSelections();
Expand
version added: 2.5.1
Provide autocompletion for MediaWiki, CSS and JavaScript modes.
For granular control over the bundled extensions, you can import the registerAutocompletion
function:
import {registerAutocompletion} from '@bhsd/codemirror-mediawiki';
registerAutocompletion();
Expand
version added: 2.0.9
Matched or unmatched brackets or tags are highlighted in cyan or dark red when the cursor is next to them.
For granular control over the bundled extensions, you can import the registerBracketMatching
function:
import {registerBracketMatching} from '@bhsd/codemirror-mediawiki';
registerBracketMatching();
Expand
version added: 2.0.9
Automatically close brackets ({
, [
and (
) and quotes ("
, and '
except for the MediaWiki mode).
For granular control over the bundled extensions, you can import the registerCloseBrackets
function:
import {registerCloseBrackets} from '@bhsd/codemirror-mediawiki';
registerCloseBrackets();
Expand
version added: 2.3.0
Fold sections, templates, parser functions and extension tags in the MediaWiki mode, and code blocks in other modes.
Key bindings:
Ctrl
+Shift
+[
/Cmd
+Alt
+[
: Fold at the selected textCtrl
+Shift
+]
/Cmd
+Alt
+]
: Unfold at the selected textCtrl
+Alt
+[
: Fold allCtrl
+Alt
+]
: Unfold all
For granular control over the bundled extensions, you can import the registerCodeFolding
function:
import {registerCodeFolding} from '@bhsd/codemirror-mediawiki';
registerCodeFolding();
Expand
version added: 2.18.0
Provide color pickers for CSS and MediaWiki modes.
For granular control over the bundled extensions, you can import the registerColorPicker
functions. Note that you also need to register this extension for specific languages(CSS, MediaWiki or Vue):
import {registerColorPicker} from '@bhsd/codemirror-mediawiki';
registerColorPicker();
Expand
version added: 2.2.2
Key bindings:
Ctrl
/Cmd
+[
: Escape the selected text with HTML entitiesCtrl
/Cmd
+]
: Escape the selected text with URL encoding
For granular control over the bundled extensions, you can import the registerEscape
function:
import {registerEscape} from '@bhsd/codemirror-mediawiki';
registerEscape();
Expand
Highlight the line the cursor is on in light cyan.
For granular control over the bundled extensions, you can import the registerHighlightActiveLine
function:
import {registerHighlightActiveLine} from '@bhsd/codemirror-mediawiki';
registerHighlightActiveLine();
Expand
version added: 2.15.3
Highlight texts that match the selection in light green.
For granular control over the bundled extensions, you can import the registerHighlightSelectionMatches
function:
import {registerHighlightSelectionMatches} from '@bhsd/codemirror-mediawiki';
registerHighlightSelectionMatches();
Expand
Show invisible characters as red dots.
For granular control over the bundled extensions, you can import the registerHighlightSpecialChars
function:
import {registerHighlightSpecialChars} from '@bhsd/codemirror-mediawiki';
registerHighlightSpecialChars();
Expand
version added: 2.0.9
Highlight trailing whitespace in a red-orange color.
For granular control over the bundled extensions, you can import the registerHighlightTrailingWhitespace
function:
import {registerHighlightTrailingWhitespace} from '@bhsd/codemirror-mediawiki';
registerHighlightTrailingWhitespace();
Expand
version added: 2.0.12
Show spaces and tabs as dots and arrows.
For granular control over the bundled extensions, you can import the registerHighlightWhitespace
function:
import {registerHighlightWhitespace} from '@bhsd/codemirror-mediawiki';
registerHighlightWhitespace();
Expand
version added: 2.21.1
Show the help information of a magic word when hovering.
For granular control over the bundled extensions, you can import the registerHover
function:
import {registerHover} from '@bhsd/codemirror-mediawiki';
registerHover();
Expand
version added: 2.22.0
Show inlay hints for anonymous parameters.
For granular control over the bundled extensions, you can import the registerInlayHints
function:
import {registerInlayHints} from '@bhsd/codemirror-mediawiki';
registerInlayHints();
Expand
version added: 2.19.6
CTRL/CMD-click opens a link in a new tab.
For granular control over the bundled extensions, you can import the registerOpenLinks
function:
import {registerOpenLinks} from '@bhsd/codemirror-mediawiki';
registerOpenLinks();
Expand
version added: 2.17.1
Show the content of the <ref>
tag defined elsewhere when hovering.
For granular control over the bundled extensions, you can import the registerRefHover
function:
import {registerRefHover} from '@bhsd/codemirror-mediawiki';
registerRefHover();
Expand
version added: 2.15.3
Allow the editor to be scrolled down past the end of the document.
For granular control over the bundled extensions, you can import the registerScrollPastEnd
function:
import {registerScrollPastEnd} from '@bhsd/codemirror-mediawiki';
registerScrollPastEnd();
Expand
version added: 2.21.1
Show the parser function signature when typing.
For granular control over the bundled extensions, you can import the registerSignatureHelp
function:
import {registerSignatureHelp} from '@bhsd/codemirror-mediawiki';
registerSignatureHelp();
Expand
- Extension:Translate is not supported.
- Extension:Poem should prevent preformatted text (Example).
- Non-existing parser functions starting with
#
are highlighted as parser functions (Example). - Wikitext in template parameter names is not highlighted (Example).
- Template parameter names followed by a newline are not recognized (Example).
- Comments at the SOL should not break section headings (Example).
- Comments at the SOL should not break table syntax (Example).
- IPv6 addresses are not supported (Example).
- External links inside double brackets are highlighted incorrectly (Example).
- Comments at the SOL break the highlighting (Example).
- False positives of preformatted text when there are categories (Example) or HTML tags (Example).
- BCP 47 language codes are not supported in language conversion (Example).