mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/CodeMirror
synced 2024-11-23 22:03:28 +00:00
CM6: move bidiIsolation to be part of CodeMirrorModeMediaWiki
The extension is custom built for MediaWiki (i.e. handling of extension tags like <ref> that aren't HTML tags), so it only makes sense to bundle it as part of the MediaWiki language mode. Resultantly, we can no longer check the direction of the textarea where we enable bidi isolation, because the language mode should have no knowledge of the textarea. Instead we offer a `config` object (akin to other language modes offered by CodeMirror), with currently only one option: `bidiIsolation`. It is the responsibility of the caller to enable this where desired. Also make templateFolding and CodeMirrorModeMediaWiki use `export default` since they both only export one thing. This commit is in preparation for Ide716247e5, where we need bidi isolation separated from the CodeMirror class due to its dependency on CodeMirrorModeMediaConfig. Bug: T358804 Bug: T214989 Change-Id: If3211bd259bd7833919a627faabd86ae7aa81b53
This commit is contained in:
parent
b18ded0a13
commit
00f947e97f
2
resources/dist/main.js
vendored
2
resources/dist/main.js
vendored
File diff suppressed because one or more lines are too long
2
resources/dist/main.js.map.json
vendored
2
resources/dist/main.js.map.json
vendored
File diff suppressed because one or more lines are too long
|
@ -4,7 +4,6 @@ import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
|
||||||
import { searchKeymap } from '@codemirror/search';
|
import { searchKeymap } from '@codemirror/search';
|
||||||
import { bracketMatching } from '@codemirror/language';
|
import { bracketMatching } from '@codemirror/language';
|
||||||
import CodemirrorTextSelection from './codemirror.textSelection';
|
import CodemirrorTextSelection from './codemirror.textSelection';
|
||||||
import bidiIsolationExtension from './codemirror.bidiIsolation';
|
|
||||||
|
|
||||||
// Necessary so that `require` doesn't get mangled into `__webpack_require__`,
|
// Necessary so that `require` doesn't get mangled into `__webpack_require__`,
|
||||||
// which ResourceLoader won't recognize and thus be unable to load the virtual file.
|
// which ResourceLoader won't recognize and thus be unable to load the virtual file.
|
||||||
|
@ -68,11 +67,6 @@ export default class CodeMirror {
|
||||||
extensions.push( keymap.of( historyKeymap ) );
|
extensions.push( keymap.of( historyKeymap ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add bidi isolation to tags on RTL pages (T358804).
|
|
||||||
if ( this.$textarea.attr( 'dir' ) === 'rtl' ) {
|
|
||||||
extensions.push( bidiIsolationExtension );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set to [] to disable everywhere, or null to enable everywhere
|
// Set to [] to disable everywhere, or null to enable everywhere
|
||||||
const namespaces = mw.config.get( 'extCodeMirrorConfig' ).lineNumberingNamespaces;
|
const namespaces = mw.config.get( 'extCodeMirrorConfig' ).lineNumberingNamespaces;
|
||||||
if ( !namespaces || namespaces.includes( mw.config.get( 'wgNamespaceNumber' ) ) ) {
|
if ( !namespaces || namespaces.includes( mw.config.get( 'wgNamespaceNumber' ) ) ) {
|
||||||
|
|
|
@ -8,7 +8,8 @@ import {
|
||||||
} from '@codemirror/language';
|
} from '@codemirror/language';
|
||||||
import { mwModeConfig as modeConfig } from './codemirror.mode.mediawiki.config';
|
import { mwModeConfig as modeConfig } from './codemirror.mode.mediawiki.config';
|
||||||
import { Tag } from '@lezer/highlight';
|
import { Tag } from '@lezer/highlight';
|
||||||
import { templateFoldingExtension } from './codemirror.templateFolding';
|
import templateFoldingExtension from './codemirror.templateFolding';
|
||||||
|
import bidiIsolationExtension from './codemirror.bidiIsolation';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapted from the original CodeMirror 5 stream parser by Pavel Astakhov
|
* Adapted from the original CodeMirror 5 stream parser by Pavel Astakhov
|
||||||
|
@ -1211,6 +1212,12 @@ class CodeMirrorModeMediaWiki {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {Object} mediaWikiLangConfig
|
||||||
|
* @property {boolean} [bidiIsolation=false] Enable bidi isolation around HTML tags.
|
||||||
|
* This should generally always be enabled on RTL pages, but it comes with a performance cost.
|
||||||
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a LanguageSupport instance for the MediaWiki mode.
|
* Gets a LanguageSupport instance for the MediaWiki mode.
|
||||||
*
|
*
|
||||||
|
@ -1220,12 +1227,13 @@ class CodeMirrorModeMediaWiki {
|
||||||
* const cm = new CodeMirror( textarea );
|
* const cm = new CodeMirror( textarea );
|
||||||
* cm.initialize( [ ...cm.defaultExtensions, mediaWikiLang() ] );
|
* cm.initialize( [ ...cm.defaultExtensions, mediaWikiLang() ] );
|
||||||
*
|
*
|
||||||
* @param {Object|null} [config] Used only by unit tests.
|
* @param {mediaWikiLangConfig} [config] Configuration options for the MediaWiki mode.
|
||||||
|
* @param {Object|null} [mwConfig] Ignore; used only by unit tests.
|
||||||
* @return {LanguageSupport}
|
* @return {LanguageSupport}
|
||||||
*/
|
*/
|
||||||
export const mediaWikiLang = ( config = null ) => {
|
export default ( config = { bidiIsolation: false }, mwConfig = null ) => {
|
||||||
config = config || mw.config.get( 'extCodeMirrorConfig' );
|
mwConfig = mwConfig || mw.config.get( 'extCodeMirrorConfig' );
|
||||||
const mode = new CodeMirrorModeMediaWiki( config );
|
const mode = new CodeMirrorModeMediaWiki( mwConfig );
|
||||||
const parser = mode.mediawiki;
|
const parser = mode.mediawiki;
|
||||||
const lang = StreamLanguage.define( parser );
|
const lang = StreamLanguage.define( parser );
|
||||||
const langExtension = [ syntaxHighlighting(
|
const langExtension = [ syntaxHighlighting(
|
||||||
|
@ -1235,11 +1243,17 @@ export const mediaWikiLang = ( config = null ) => {
|
||||||
) ];
|
) ];
|
||||||
|
|
||||||
// Add template folding if in supported namespace.
|
// Add template folding if in supported namespace.
|
||||||
const templateFoldingNs = config.templateFoldingNamespaces;
|
const templateFoldingNs = mwConfig.templateFoldingNamespaces;
|
||||||
// Set to [] to disable everywhere, or null to enable everywhere.
|
// Set to [] to disable everywhere, or null to enable everywhere.
|
||||||
if ( !templateFoldingNs || templateFoldingNs.includes( mw.config.get( 'wgNamespaceNumber' ) ) ) {
|
if ( !templateFoldingNs || templateFoldingNs.includes( mw.config.get( 'wgNamespaceNumber' ) ) ) {
|
||||||
langExtension.push( templateFoldingExtension );
|
langExtension.push( templateFoldingExtension );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Bundle the bidi isolation extension, as it's coded specifically for MediaWiki.
|
||||||
|
// This is behind a config option for performance reasons (we only use it on RTL pages).
|
||||||
|
if ( config.bidiIsolation ) {
|
||||||
|
langExtension.push( bidiIsolationExtension );
|
||||||
|
}
|
||||||
|
|
||||||
return new LanguageSupport( lang, langExtension );
|
return new LanguageSupport( lang, langExtension );
|
||||||
};
|
};
|
||||||
|
|
|
@ -222,7 +222,7 @@ const foldKeymap = [
|
||||||
];
|
];
|
||||||
|
|
||||||
/** @type {Extension} */
|
/** @type {Extension} */
|
||||||
export const templateFoldingExtension = [
|
export default [
|
||||||
codeFolding( {
|
codeFolding( {
|
||||||
placeholderDOM( view ) {
|
placeholderDOM( view ) {
|
||||||
const element = document.createElement( 'span' );
|
const element = document.createElement( 'span' );
|
||||||
|
|
|
@ -1,9 +1,12 @@
|
||||||
import CodeMirrorWikiEditor from './codemirror.wikieditor';
|
import CodeMirrorWikiEditor from './codemirror.wikieditor';
|
||||||
import { mediaWikiLang } from './codemirror.mode.mediawiki';
|
import mediaWikiLang from './codemirror.mode.mediawiki';
|
||||||
|
|
||||||
if ( mw.loader.getState( 'ext.wikiEditor' ) ) {
|
if ( mw.loader.getState( 'ext.wikiEditor' ) ) {
|
||||||
mw.hook( 'wikiEditor.toolbarReady' ).add( ( $textarea ) => {
|
mw.hook( 'wikiEditor.toolbarReady' ).add( ( $textarea ) => {
|
||||||
const cmWE = new CodeMirrorWikiEditor( $textarea, mediaWikiLang() );
|
const cmWE = new CodeMirrorWikiEditor(
|
||||||
|
$textarea,
|
||||||
|
mediaWikiLang( { bidiIsolation: $textarea.attr( 'dir' ) === 'rtl' } )
|
||||||
|
);
|
||||||
cmWE.addCodeMirrorToWikiEditor();
|
cmWE.addCodeMirrorToWikiEditor();
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import CodeMirror from '../../src/codemirror.js';
|
import CodeMirror from '../../src/codemirror.js';
|
||||||
import { mediaWikiLang } from '../../src/codemirror.mode.mediawiki.js';
|
import mediaWikiLang from '../../src/codemirror.mode.mediawiki.js';
|
||||||
|
|
||||||
const testCases = [
|
const testCases = [
|
||||||
{
|
{
|
||||||
|
@ -14,9 +14,10 @@ const textarea = document.createElement( 'textarea' );
|
||||||
textarea.dir = 'rtl';
|
textarea.dir = 'rtl';
|
||||||
document.body.appendChild( textarea );
|
document.body.appendChild( textarea );
|
||||||
const cm = new CodeMirror( textarea );
|
const cm = new CodeMirror( textarea );
|
||||||
const mwLang = mediaWikiLang( {
|
const mwLang = mediaWikiLang(
|
||||||
tags: {}
|
{ bidiIsolation: true },
|
||||||
} );
|
{ tags: {} }
|
||||||
|
);
|
||||||
cm.initialize( [ ...cm.defaultExtensions, mwLang ] );
|
cm.initialize( [ ...cm.defaultExtensions, mwLang ] );
|
||||||
|
|
||||||
describe( 'CodeMirrorBidiIsolation', () => {
|
describe( 'CodeMirrorBidiIsolation', () => {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import CodeMirror from '../../src/codemirror.js';
|
import CodeMirror from '../../src/codemirror.js';
|
||||||
import { mediaWikiLang } from '../../src/codemirror.mode.mediawiki.js';
|
import mediaWikiLang from '../../src/codemirror.mode.mediawiki.js';
|
||||||
import { mwModeConfig } from '../../src/codemirror.mode.mediawiki.config.js';
|
import { mwModeConfig } from '../../src/codemirror.mode.mediawiki.config.js';
|
||||||
|
|
||||||
// NOTE: each test case should have a space before the closing </div>
|
// NOTE: each test case should have a space before the closing </div>
|
||||||
|
@ -163,7 +163,7 @@ const textarea = document.createElement( 'textarea' );
|
||||||
document.body.appendChild( textarea );
|
document.body.appendChild( textarea );
|
||||||
const cm = new CodeMirror( textarea );
|
const cm = new CodeMirror( textarea );
|
||||||
// Stub the config normally provided by mw.config.get('extCodeMirrorConfig')
|
// Stub the config normally provided by mw.config.get('extCodeMirrorConfig')
|
||||||
const mwLang = mediaWikiLang( {
|
const mwLang = mediaWikiLang( {}, {
|
||||||
urlProtocols: 'ftp://|https://|news:',
|
urlProtocols: 'ftp://|https://|news:',
|
||||||
doubleUnderscore: [ {
|
doubleUnderscore: [ {
|
||||||
__notoc__: 'notoc'
|
__notoc__: 'notoc'
|
||||||
|
|
Loading…
Reference in a new issue