Expand all

CodeMirrorVisualEditorHighlight

Syntax highlighter for the VisualEditor 2017 wikitext editor that renders nothing of its own. Unlike CodeMirrorVisualEditor it creates no EditorView: a headless EditorState drives CodeMirror's tokenizer, and the colors are painted onto VisualEditor's own text with the CSS Custom Highlight API via ve.ce.SelectionManager#drawSelections.

With no second rendered layer there is nothing to keep aligned, and the cost is bounded by the viewport rather than the document.

It qualifies as an Editor by holding the tokenizer as its state and applying transactions to it in dispatch(), which is what lets it share CodeMirrorPreferences and the CodeMirrorExtensionRegistry with its parent.

Extends

Constructor

new CodeMirrorVisualEditorHighlight(surface, langSupport, [matchTag]) #

Parameters:

Name Type Attributes Description
surface ve.ui.Surface
langSupport CodeMirrorMediaWiki

MediaWiki mode instance, exposing language, parser and highlightStyle.

matchTag function optional

Headless tag matcher matchTag( state, pos ), returning the same { matched, start, end } shape as findBracketMatch. Omitted if unsupported.

Source:

Properties

$activeLineNode :jQuery|null #

Node currently carrying ACTIVE_LINE_CLASS. Held as the element rather than a line number: an edit elsewhere shifts line numbers, and clearing by index would then strip the class off whichever node had moved into that slot, stranding this one.

Type:

Source:
Node currently carrying ACTIVE_LINE_CLASS.

$textarea :jQuery.<(HTMLTextAreaElement|ve.ui.Surface)> #

jQuery instance of the textarea or VE surface for use with jQuery plugins.

Type:

Overrides:
Source:
jQuery instance of the textarea or VE surface for use with jQuery plugins.

activeLineExtension :Extension #

Extension for highlighting the active line.

Type:

Overrides:
Source:
Extension for highlighting the active line.

bracketConfig :Object #

Bracket-matching config (bracket set and scan distance), reused from the mode.

Type:

Source:
Bracket-matching config (bracket set and scan distance), reused from the mode.

bracketFrameHandle :number|null #

Pending requestAnimationFrame handle for coalescing bracket-match updates.

Type:

  • number | null
Source:
Pending requestAnimationFrame handle for coalescing bracket-match updates.

bracketGroups :Set.<string> #

Bracket highlight groups currently drawn, kept apart from the syntax groups so a syntax refresh does not clear them.

Type:

Source:

Bracket highlight groups currently drawn, kept apart from the syntax groups so a syntax refresh does not clear them.

bracketMatchingConfig :Config|undefined #

The extended configuration for bracket matching. Setting this will update the bracket matching extension

Example

// Highlight matching angle brackets in addition to the default.
mw.hook( 'ext.CodeMirror.ready' ).add( ( cm ) => {
  const config = cm.bracketMatchingConfig || {};
  config.brackets = ( config.brackets || '()[]{}' ) + '<>';
  cm.bracketMatchingConfig = config;
} );

Type:

Overrides:
Source:
The extended configuration for bracket matching.

bracketMatchingExtension :Extension #

This extension adds bracket matching to the CodeMirror editor.

Type:

Overrides:
Source:
This extension adds bracket matching to the CodeMirror editor.

child :CodeMirrorChild #

Get a CodeMirrorChild object for use on other textareas that should have preferences synced with this CodeMirror instance.

Type:

Overrides:
Source:

Get a CodeMirrorChild object for use on other textareas that should have preferences synced with this CodeMirror instance.

closeBracketsExtension :Extension #

This extension adds automatic closing of brackets to the CodeMirror editor.

Type:

Overrides:
Source:
This extension adds automatic closing of brackets to the CodeMirror editor.

columnGuideExtension :Extensionprotected #

This extension adds a vertical column guide to the editor at column 80.

Type:

Overrides:
Source:
This extension adds a vertical column guide to the editor at column 80.

compactPanelsExtension :Extension #

Extension for the compact panel design. The class it adds makes the search and go-to line panels float over the editor instead of pushing the contents down.

Type:

Overrides:
Source:
Extension for the compact panel design.

container :HTMLDivElement #

The .ext-codemirror-wrapper container. This houses both the original textarea and the CodeMirror editor.

Type:

Overrides:
Source:
The .ext-codemirror-wrapper container.

dirCompartment :Compartment #

Compartment to control the direction of the editor.

Type:

Overrides:
Source:
Compartment to control the direction of the editor.

dirExtension :Extensionprotected #

This extension adds the ability to change the direction of the editor.

Type:

Overrides:
Source:
This extension adds the ability to change the direction of the editor.

domEventHandlersExtension :Extensionprotected #

Extension to bubble some DOM events to the original textarea.

The CodeMirror events are natively fired on the EditorView's .cm-content element, which is accessible through view.contentDOM. The scroll event is fired on the .cm-scroller element, which is accessible through view.scrollDOM.

Type:

Overrides:
Source:
Extension to bubble some DOM events to the original textarea.

drawnGroups :Set.<string> #

Highlight group names currently drawn, so stale ones can be removed.

Type:

Source:
Highlight group names currently drawn, so stale ones can be removed.

editRecoveryExtension #

Edit Recovery support.

editorAttributesExtension :Extensionprotected #

This specifies which attributes get added to the .cm-editor element (the entire editor). Subclasses are safe to override this method, but attributes here are considered vital.

Type:

Overrides:
Source:
See:
This specifies which attributes get added to the .cm-editor element (the entire editor).

extensionRegistry :CodeMirrorExtensionRegistry #

Registry of CodeMirror Extensions.

frameHandle :number|null #

Pending requestAnimationFrame handle, used to coalesce refreshes.

Type:

  • number | null
Source:
Pending requestAnimationFrame handle, used to coalesce refreshes.

gotoLine :CodeMirrorGotoLine #

The go-to line panel.

Type:

Overrides:
Source:
The go-to line panel.

headingFrameHandle :number|null #

Pending requestAnimationFrame handle for heading updates.

Type:

  • number | null
Source:
Pending requestAnimationFrame handle for heading updates.

headingLines :Map.<number, number> #

Heading line numbers (1-based) to level, so the classes can be removed again.

Type:

  • Map.<number, number>
Source:
Heading line numbers (1-based) to level, so the classes can be removed again.

highlightRefsExtension :Extensionprotected #

The highlightRefs preference, which the mediawiki mode registers as a CodeMirror theme where there is a view to apply one to.

Type:

Source:

The highlightRefs preference, which the mediawiki mode registers as a CodeMirror theme where there is a view to apply one to.

indentGuidesExtension :Extension #

This extension adds indent guides to the CodeMirror editor.

Type:

Overrides:
Source:
This extension adds indent guides to the CodeMirror editor.

isActive :boolean #

Whether the CodeMirror instance is active.

Type:

  • boolean
Overrides:
Source:
Whether the CodeMirror instance is active.

isDiscussionTools :boolean #

Whether the surface belongs to DiscussionTools, which reuses the 2017 editor for replies and has no line numbers of its own.

Type:

  • boolean
Overrides:
Source:

Whether the surface belongs to DiscussionTools, which reuses the 2017 editor for replies and has no line numbers of its own.

keymap :CodeMirrorKeymap #

CodeMirror key mappings and help dialog.

Type:

Overrides:
Source:
CodeMirror key mappings and help dialog.

langExtension :LanguageSupport #

Language support and its extension(s).

Type:

Overrides:
Source:
Language support and its extension(s).

lineNumberGutter :CodeMirrorVisualEditorHighlightLineNumbering #

The line-number gutter. There is no EditorView to host CodeMirror's own, so this draws numbers beside VisualEditor's paragraphs instead.

Type:

Source:
The line-number gutter.

lineNumberingExtension :Extension #

Extension for line numbering.

Type:

Overrides:
Source:
Extension for line numbering.

lineWrappingExtension :Extension #

Extension for line wrapping.

Type:

Overrides:
Source:
Extension for line wrapping.

lintApi :LintSource|undefined #

The function to lint the code in the editor using a MediaWiki API. It can be disabled by setting this.lintApi.disabled = true.

Example

mw.hook( 'ext.CodeMirror.ready' ).add( ( cm ) => {
  if ( cm.lintApi ) {
    cm.lintApi.disabled = true;
  }
} );

Type:

Overrides:
Source:
The function to lint the code in the editor using a MediaWiki API.

lintExtension :Extensionprotected #

This extension adds the ability to lint the code in the editor.

Type:

Overrides:
Source:
This extension adds the ability to lint the code in the editor.

lintSource :LintSource|undefined #

The function to lint the code in the editor using a web worker. It can be disabled by setting this.lintSource.disabled = true.

Example

mw.hook( 'ext.CodeMirror.ready' ).add( ( cm ) => {
  if ( cm.lintSource ) {
    cm.lintSource.disabled = true;
  }
} );

Type:

Overrides:
Source:
The function to lint the code in the editor using a web worker.

matchTag :function|null #

Headless tag matcher, so tag pairs (e.g. <ref>/</ref>) match under the same bracketMatching preference as brackets.

Type:

  • function | null
Source:
Headless tag matcher, so tag pairs (e.g.

mode :string #

The CodeMirror "mode" (language).

Type:

  • string
Overrides:
Source:
The CodeMirror "mode" (language).

Modifier-click link opening, driven by VisualEditor's mouse events: the overlay is pointer-events: none, so CodeMirror's own openLinks extension never fires here.

openLinksEnabled :boolean #

Whether modifier-clicking a link opens it, from the user's openLinks preference.

Type:

  • boolean
Overrides:
Source:
Whether modifier-clicking a link opens it, from the user's openLinks preference.

openLinksExtension :Extensionprotected #

Holds the mark for the link under the pointer. Registered like any other preference, so the registry turns it on and off with openLinks; the range itself moves by effect.

Type:

Overrides:
Source:
Holds the mark for the link under the pointer.

openWindows :number #

Number of modal windows open over the surface. The highlights are suspended while any is; see CodeMirrorVisualEditorHighlight#suspendWhileWindowOpen.

Type:

  • number
Source:
Number of modal windows open over the surface.

parsePassTarget :number|null #

The source offset that the pass count applies to. If the viewport moves to a different offset, the count starts again.

Type:

  • number | null
Source:
The source offset that the pass count applies to.

parsePasses :number #

The number of sequential passes that ended with the parse short of the viewport. See MAX_PARSE_PASSES.

Type:

  • number
Source:
The number of sequential passes that ended with the parse short of the viewport.

persistPreferences :booleanprotected #

Whether to save preference changes to the user's options. Subclasses that are not the user's main editor should override this and return false, so that the editor does not change preferences the user set elsewhere. Preferences are still read, and still apply for the life of the editor.

Note this is distinct from locked preferences, which force a specific PrefValue for the life of the editor.

Type:

  • boolean
Overrides:
Source:
Whether to save preference changes to the user's options.

phrasesExtension :Extensionprotected #

Overrides for the CodeMirror library's internalization system.

Type:

Overrides:
Source:
See:
Overrides for the CodeMirror library's internalization system.

preferences :CodeMirrorPreferences #

The CodeMirror preferences dialog.

Type:

Overrides:
Source:
The CodeMirror preferences dialog.

readOnly :boolean #

Whether the editor is read-only. Assigning to this reconfigures the editor in place, so it can be changed at any time after initialization. Before then it comes from initialReadOnly.

A read-only editor is still focusable and its contents still selectable. Use EditorView.editable to make it non-editable.

Type:

  • boolean
Overrides:
Source:
Whether the editor is read-only.

readOnlyExtension :Extensionprotected #

The read-only state of the editor, in a Compartment so that readOnly can reconfigure it after initialization.

Type:

Overrides:
Source:

The read-only state of the editor, in a Compartment so that readOnly can reconfigure it after initialization.

The CodeMirror search panel.

searchExtension :Extension #

Extension for search and goto line functionality.

Type:

Overrides:
Source:
Extension for search and goto line functionality.

sortLines :CodeMirrorSortLines #

CodeMirror line sorting functionality.

Type:

Overrides:
Source:
CodeMirror line sorting functionality.

specialCharsExtension :Extensionprotected #

We give a small subset of special characters a tooltip explaining what they are. The messages and for what characters are defined here. Any character that does not have a message will instead use CM6 defaults, which is the localization of 'codemirror-control-character' followed by the Unicode number.

Type:

Overrides:
Source:
See:
We give a small subset of special characters a tooltip explaining what they are.

state :EditorState|undefined #

The current EditorState of the CodeMirror editor. This is given by the EditorView instance, which is only available after initialization.

Type:

Overrides:
Source:
The current EditorState of the CodeMirror editor.

supportedPreferences :Array.<string> #

Preferences this integration honours, for ve.ui.CodeMirrorPreferencesPage.

Type:

Overrides:
Source:
Preferences this integration honours, for ve.ui.CodeMirrorPreferencesPage.

surface :ve.ui.Surface #

The VisualEditor surface.

surfaceView :ve.ce.Surface #

The ContentEditable surface.

suspendWhileWindowOpen :boolean #

Whether to suspend the highlights while a modal window is open.

In Safari the cost to paint the highlights increases with the number of registered ranges. The size of each range does not change it. A window repaints the whole viewport when it opens, so on a long page the tab stops responding for more than a minute. See WebKit 323171.

Set this to false, or load the page with cmsuspend=0, to keep the highlights registered and show the browser bug again.

Type:

  • boolean
Source:
Whether to suspend the highlights while a modal window is open.

suspended :boolean #

Whether the highlights are currently suspended.

Type:

  • boolean
Source:
Whether the highlights are currently suspended.

syntaxHighlightingEnabled :boolean #

Whether to paint syntax colors: the no-highlight theme (T419339) turns them off. Bracket matching and line numbering have their own preferences and are unaffected, matching CodeMirrorThemes, where those styles sit outside the theme's rules.

Type:

  • boolean
Source:
Whether to paint syntax colors: the no-highlight theme (T419339) turns them off.

textSelection :CodeMirrorTextSelection #

jQuery.textSelection overrides for CodeMirror.

Type:

Overrides:
Source:
jQuery.textSelection overrides for CodeMirror.

textarea :HTMLTextAreaElement|ve.ui.Surface #

The textarea or VE surface that CodeMirror is bound to.

Type:

Overrides:
Source:
The textarea or VE surface that CodeMirror is bound to.

theme :string #

The applied theme: default, colorblind or no-highlight for this mode. Light and dark variants are resolved in CSS, so only the base name matters here. CodeMirrorThemes puts it in the state, since its own Extensions are styles for a CodeMirror that does not exist here.

Type:

  • string
Source:
The applied theme: default, colorblind or no-highlight for this mode.

themes :CodeMirrorThemes #

The CodeMirror themes manager.

Type:

Overrides:
Source:
The CodeMirror themes manager.

tokenizer :EditorState|null #

Headless tokenizer state, driving CodeMirror's incremental parse without rendering.

Type:

Source:
Headless tokenizer state, driving CodeMirror's incremental parse without rendering.

trailingWhitespaceDrawn :boolean #

Whether the trailing-whitespace group is currently drawn, so clearing it is a no-op when it never was.

Type:

  • boolean
Source:

Whether the trailing-whitespace group is currently drawn, so clearing it is a no-op when it never was.

trailingWhitespaceExtension #

This extension highlights trailing whitespace characters.

Overrides:
Source:
This extension highlights trailing whitespace characters.

trailingWhitespaceFrameHandle :number|null #

Pending requestAnimationFrame handle for trailing-whitespace updates.

Type:

  • number | null
Source:
Pending requestAnimationFrame handle for trailing-whitespace updates.

updateExtension :Extension #

This extension listens for changes in the CodeMirror editor and fires the ext.CodeMirror.input hook with the ViewUpdate object.

Type:

Overrides:
Source:

Fires:

This extension listens for changes in the CodeMirror editor and fires the ext.CodeMirror.input hook with the ViewUpdate object.

view :EditorView #

The editor user interface.

Type:

Overrides:
Source:
The editor user interface.

whitespaceDrawn :boolean #

Whether the whitespace group is currently drawn.

Type:

  • boolean
Source:
Whether the whitespace group is currently drawn.

whitespaceExtension #

This extension highlights whitespace characters.

Overrides:
Source:
This extension highlights whitespace characters.

Methods

addMwHook(hook, fn)protected #

Add a handler for the given Hook. This method is used to ensure no hook handlers are duplicated across lifecycle methods, All handlers will be removed during deactivation.

Parameters:

Name Type Description
hook string
fn function
Overrides:
Source:
Add a handler for the given Hook.

addToDOM(extensions)protected #

Add the CodeMirror EditorView to the DOM, wrapping wrappedElement in the container element.

Parameters:

Name Type Description
extensions Extension
Overrides:
Source:

Add the CodeMirror EditorView to the DOM, wrapping wrappedElement in the container element.

applyExtension(extension) #

Apply an Extension to the CodeMirror editor. This is accomplished through top-level reconfiguration of the EditorView.

If the extension needs to be reconfigured (such as toggling on and off), use the extensionRegistry instead.

Example

const require = await mw.loader.using( 'ext.CodeMirror' );
mw.hook( 'ext.CodeMirror.ready' ).add( ( cm ) => {
  const { EditorView, Prec } = require( 'ext.CodeMirror.lib' );
  // Disable spellchecking. Use Prec.high() to override the
  // contentAttributesExtension which adds spellcheck="true".
  cm.applyExtension( Prec.high( EditorView.contentAttributes.of( {
    spellcheck: 'false'
  } ) ) );
} );

Parameters:

Name Type Description
extension Extension
Overrides:
Source:
See:
Apply an Extension to the CodeMirror editor.

applyLinter(lint, [config]) #

Apply an extra linter to the CodeMirror editor. This linter respects the user preference for enabling or disabling linting.

Example

// Report Ukrainian letter 'і' among Latin letters as a warning.
const lint = {
  pattern: /[a-zA-Z]і|і(?=[a-zA-Z])/g,
  callback( match ) {
    return {
      from: match.index + match[ 0 ].indexOf( 'і' ),
      to: match.index + match[ 0 ].indexOf( 'і' ) + 1,
      severity: 'warning',
      message: 'Ukrainian letter "і" found among Latin letters.',
      actions: [ {
        name: 'To Latin',
        apply( view, from, to ) {
          view.dispatch( {
            changes: { from, to, insert: 'i' }
          } );
        }
      } ]
    };
  }
};
mw.hook( 'ext.CodeMirror.ready' ).add( ( cm ) => {
  cm.applyLinter( lint );
} );

Parameters:

Name Type Attributes Description
lint function | Object

Function that takes a string and returns an array of Diagnostic, or an object with a pattern RegExp and callback function that takes a RegExp match and returns Diagnostic or an array of Diagnostic.

config Object optional

Optional configuration.

Overrides:
Source:
Apply an extra linter to the CodeMirror editor.

bindSurface()protected #

Everything this integration does to VisualEditor's surface while it is active: the overlay styling, and the listeners that keep CodeMirror in step with the surface. Undone by unbindSurface().

Overrides:
Source:

Everything this integration does to VisualEditor's surface while it is active: the overlay styling, and the listeners that keep CodeMirror in step with the surface.

dispatch(spec) #

Apply a transaction to the editor. Together with state, this is what makes a CodeMirror instance an Editor.

Parameters:

Name Type Description
spec Object
Overrides:
Source:

Apply a transaction to the editor.

getLineNumberingExtension([firstLineNumber]) → {Extension} #

Line numbering, starting at the given number.

Use this instead of CodeMirror#lineNumberingExtension when the code in the editor is part of a larger file, and the first line is not line 1.

Parameters:

Name Type Attributes Default Description
firstLineNumber number optional
1

Number to show for the first line.

Returns:

Type
Extension
Overrides:
Source:
Line numbering, starting at the given number.

getNewEditorState(extensions) → {EditorState}protected #

Create a new EditorState with the given extensions and the contents of the element that CodeMirror is bound to.

Parameters:

Name Type Description
extensions Extension

Returns:

Type
EditorState
Overrides:
Source:

Create a new EditorState with the given extensions and the contents of the element that CodeMirror is bound to.

hideEditor()protected #

Hide the editor and give jQuery.textSelection back to the textarea, as deactivate() does on the way out. Integrations that render no editor of their own should override this.

Overrides:
Source:

Hide the editor and give jQuery.textSelection back to the textarea, as deactivate() does on the way out.

onDocumentChanged()protected #

Update whatever tracks the document contents, once onDocumentPrecommit() has mirrored a change into CodeMirror.

Overrides:
Source:

Update whatever tracks the document contents, once onDocumentPrecommit() has mirrored a change into CodeMirror.

onDocumentPrecommit(tx)protected #

Handle precommit events from the document, mirroring the change into CodeMirror.

The document is still in its 'old' state before the transaction has been applied at this point, so the offsets are those of the pre-transaction document. They go in one transaction, which CodeMirror rebases internally, rather than one at a time in reverse.

Parameters:

Name Type Description
tx ve.dm.Transaction
Overrides:
Source:
Handle precommit events from the document, mirroring the change into CodeMirror.

removeFromDOM()protected #

Remove the CodeMirror EditorView from the DOM, unwrapping the element it was attached to, as the inverse of addToDOM(). Integrations that attach CodeMirror to something other than a textarea should override this.

Overrides:
Source:

Remove the CodeMirror EditorView from the DOM, unwrapping the element it was attached to, as the inverse of addToDOM().

removeMwHooks([hook], [fn])protected #

Remove handlers registered with #addMwHook for the given Hook, or remove all handlers if no hook is specified.

Parameters:

Name Type Attributes Description
hook string optional
fn function optional

If specified, only this handler will be removed for the given hook.

Overrides:
Source:

Remove handlers registered with #addMwHook for the given Hook, or remove all handlers if no hook is specified.

setCodeMirrorPreference(prefValue) #

Save CodeMirror enabled preference.

Parameters:

Name Type Description
prefValue boolean

true to enable CodeMirror where possible on page load.

Overrides:
Source:
Save CodeMirror enabled preference.

showEditor()protected #

Reveal the editor and route jQuery.textSelection through it, as activate() does on the way in. Integrations that render no editor of their own should override this.

Overrides:
Source:

Reveal the editor and route jQuery.textSelection through it, as activate() does on the way in.

toggle([force]) #

Toggle CodeMirror on or off from the textarea. This will call initialize if CodeMirror is being enabled for the first time.

Parameters:

Name Type Attributes Description
force boolean optional

true to enable CodeMirror, false to disable. Note that the ext.CodeMirror.toggle hook will not be fired if this parameter is set.

Fires:

Overrides:
Source:
Toggle CodeMirror on or off from the textarea.

unbindSurface()protected #

Undo bindSurface(), leaving VisualEditor's surface as it was found.

Overrides:
Source:

Undo bindSurface(), leaving VisualEditor's surface as it was found.