mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/CodeMirror
synced 2024-11-27 07:30:05 +00:00
CodeMirrorModeMediaWiki: autocompletion
Autocomplete magic words, tag names and url protocols. This patch also enables block comment using `<!-- -->`. Bug: T95100 Change-Id: If37da956ac1eb945b96753e6728c0247b1a68b66
This commit is contained in:
parent
6cfde8a849
commit
197b5649ff
|
@ -33,6 +33,11 @@
|
||||||
"description": "List of namespace IDs where template folding should be enabled, or `null` to enable for all namespaces. Set to [] to disable everywhere.",
|
"description": "List of namespace IDs where template folding should be enabled, or `null` to enable for all namespaces. Set to [] to disable everywhere.",
|
||||||
"public": true
|
"public": true
|
||||||
},
|
},
|
||||||
|
"CodeMirrorAutocompleteNamespaces": {
|
||||||
|
"value": null,
|
||||||
|
"description": "List of namespace IDs where autocompletion should be enabled, or `null` to enable for all namespaces. Set to [] to disable everywhere.",
|
||||||
|
"public": true
|
||||||
|
},
|
||||||
"CodeMirrorLineNumberingNamespaces": {
|
"CodeMirrorLineNumberingNamespaces": {
|
||||||
"value": null,
|
"value": null,
|
||||||
"description": "List of namespace IDs where line numbering should be enabled, or `null` to enable for all namespaces. Set to [] to disable everywhere.",
|
"description": "List of namespace IDs where line numbering should be enabled, or `null` to enable for all namespaces. Set to [] to disable everywhere.",
|
||||||
|
@ -46,7 +51,8 @@
|
||||||
"lineNumbering": true,
|
"lineNumbering": true,
|
||||||
"lineWrapping": true,
|
"lineWrapping": true,
|
||||||
"specialChars": true,
|
"specialChars": true,
|
||||||
"templateFolding": true
|
"templateFolding": true,
|
||||||
|
"autocomplete": true
|
||||||
},
|
},
|
||||||
"description": "Defaults for CodeMirror user preferences. See https://w.wiki/BwzZ for more information.",
|
"description": "Defaults for CodeMirror user preferences. See https://w.wiki/BwzZ for more information.",
|
||||||
"public": true
|
"public": true
|
||||||
|
@ -284,7 +290,8 @@
|
||||||
"codemirror.mediawiki.js",
|
"codemirror.mediawiki.js",
|
||||||
"codemirror.mediawiki.config.js",
|
"codemirror.mediawiki.config.js",
|
||||||
"codemirror.mediawiki.bidiIsolation.js",
|
"codemirror.mediawiki.bidiIsolation.js",
|
||||||
"codemirror.mediawiki.templateFolding.js"
|
"codemirror.mediawiki.templateFolding.js",
|
||||||
|
"codemirror.mediawiki.autocomplete.js"
|
||||||
],
|
],
|
||||||
"styles": [
|
"styles": [
|
||||||
"codemirror.mediawiki.less",
|
"codemirror.mediawiki.less",
|
||||||
|
@ -297,7 +304,8 @@
|
||||||
"messages": [
|
"messages": [
|
||||||
"codemirror-fold-template",
|
"codemirror-fold-template",
|
||||||
"codemirror-prefs-bidiisolation",
|
"codemirror-prefs-bidiisolation",
|
||||||
"codemirror-prefs-templatefolding"
|
"codemirror-prefs-templatefolding",
|
||||||
|
"codemirror-prefs-autocomplete"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"ext.CodeMirror.v6.WikiEditor": {
|
"ext.CodeMirror.v6.WikiEditor": {
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
"codemirror-prefs-enable": "Enable syntax highlighting for wikitext",
|
"codemirror-prefs-enable": "Enable syntax highlighting for wikitext",
|
||||||
"codemirror-prefs-title": "Syntax highlighting preferences",
|
"codemirror-prefs-title": "Syntax highlighting preferences",
|
||||||
"codemirror-prefs-templatefolding": "Enable folding of template parameters",
|
"codemirror-prefs-templatefolding": "Enable folding of template parameters",
|
||||||
|
"codemirror-prefs-autocomplete": "Enable autocompletion",
|
||||||
"codemirror-prefs-bidiisolation": "Isolate bidirectional text",
|
"codemirror-prefs-bidiisolation": "Isolate bidirectional text",
|
||||||
"codemirror-prefs-bracketmatching": "Enable bracket matching",
|
"codemirror-prefs-bracketmatching": "Enable bracket matching",
|
||||||
"codemirror-prefs-linenumbering": "Show line numbers",
|
"codemirror-prefs-linenumbering": "Show line numbers",
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
"codemirror-prefs-enable": "Used in user preferences as label for enabling syntax highlighting.",
|
"codemirror-prefs-enable": "Used in user preferences as label for enabling syntax highlighting.",
|
||||||
"codemirror-prefs-title": "Syntax highlighting preferences",
|
"codemirror-prefs-title": "Syntax highlighting preferences",
|
||||||
"codemirror-prefs-templatefolding": "Label for the option to enable folding of template parameters in the CodeMirror preferences panel.",
|
"codemirror-prefs-templatefolding": "Label for the option to enable folding of template parameters in the CodeMirror preferences panel.",
|
||||||
|
"codemirror-prefs-autocomplete": "Label for the option to enable autocompletion in the CodeMirror preferences panel.",
|
||||||
"codemirror-prefs-bidiisolation": "Label for the option to enable bidirectional text isolation in the CodeMirror preferences panel.",
|
"codemirror-prefs-bidiisolation": "Label for the option to enable bidirectional text isolation in the CodeMirror preferences panel.",
|
||||||
"codemirror-prefs-bracketmatching": "Label for the option to enable bracket matching in the CodeMirror preferences panel.",
|
"codemirror-prefs-bracketmatching": "Label for the option to enable bracket matching in the CodeMirror preferences panel.",
|
||||||
"codemirror-prefs-linenumbering": "Label for the option to show line numbers in the CodeMirror preferences panel.",
|
"codemirror-prefs-linenumbering": "Label for the option to show line numbers in the CodeMirror preferences panel.",
|
||||||
|
|
|
@ -62,6 +62,7 @@ class DataScript {
|
||||||
'defaultPreferences' => $mwConfig->get( 'CodeMirrorDefaultPreferences' ),
|
'defaultPreferences' => $mwConfig->get( 'CodeMirrorDefaultPreferences' ),
|
||||||
'lineNumberingNamespaces' => $mwConfig->get( 'CodeMirrorLineNumberingNamespaces' ),
|
'lineNumberingNamespaces' => $mwConfig->get( 'CodeMirrorLineNumberingNamespaces' ),
|
||||||
'templateFoldingNamespaces' => $mwConfig->get( 'CodeMirrorTemplateFoldingNamespaces' ),
|
'templateFoldingNamespaces' => $mwConfig->get( 'CodeMirrorTemplateFoldingNamespaces' ),
|
||||||
|
'autocompleteNamespaces' => $mwConfig->get( 'CodeMirrorAutocompleteNamespaces' ),
|
||||||
'pluginModules' => $registry->getAttribute( 'CodeMirrorPluginModules' ),
|
'pluginModules' => $registry->getAttribute( 'CodeMirrorPluginModules' ),
|
||||||
'tagModes' => $tagModes,
|
'tagModes' => $tagModes,
|
||||||
'tags' => array_fill_keys( $tagNames, true ),
|
'tags' => array_fill_keys( $tagNames, true ),
|
||||||
|
|
20
package-lock.json
generated
20
package-lock.json
generated
|
@ -6,6 +6,7 @@
|
||||||
"": {
|
"": {
|
||||||
"name": "codemirror",
|
"name": "codemirror",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@codemirror/autocomplete": "6.12.0",
|
||||||
"@codemirror/commands": "6.2.5",
|
"@codemirror/commands": "6.2.5",
|
||||||
"@codemirror/language": "6.9.3",
|
"@codemirror/language": "6.9.3",
|
||||||
"@codemirror/search": "6.5.6",
|
"@codemirror/search": "6.5.6",
|
||||||
|
@ -499,6 +500,25 @@
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/@codemirror/autocomplete": {
|
||||||
|
"version": "6.12.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.12.0.tgz",
|
||||||
|
"integrity": "sha512-r4IjdYFthwbCQyvqnSlx0WBHRHi8nBvU+WjJxFUij81qsBfhNudf/XKKmmC2j3m0LaOYUQTf3qiEK1J8lO1sdg==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"dependencies": {
|
||||||
|
"@codemirror/language": "^6.0.0",
|
||||||
|
"@codemirror/state": "^6.0.0",
|
||||||
|
"@codemirror/view": "^6.17.0",
|
||||||
|
"@lezer/common": "^1.0.0"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@codemirror/language": "^6.0.0",
|
||||||
|
"@codemirror/state": "^6.0.0",
|
||||||
|
"@codemirror/view": "^6.0.0",
|
||||||
|
"@lezer/common": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@codemirror/commands": {
|
"node_modules/@codemirror/commands": {
|
||||||
"version": "6.2.5",
|
"version": "6.2.5",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
"node": "18.20.4"
|
"node": "18.20.4"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@codemirror/autocomplete": "6.12.0",
|
||||||
"@codemirror/commands": "6.2.5",
|
"@codemirror/commands": "6.2.5",
|
||||||
"@codemirror/language": "6.9.3",
|
"@codemirror/language": "6.9.3",
|
||||||
"@codemirror/search": "6.5.6",
|
"@codemirror/search": "6.5.6",
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
* This file is managed by Rollup and bundles all the CodeMirror dependencies
|
* This file is managed by Rollup and bundles all the CodeMirror dependencies
|
||||||
* into the single file resources/lib/codemirror6.bundle.dist.js.
|
* into the single file resources/lib/codemirror6.bundle.dist.js.
|
||||||
*/
|
*/
|
||||||
|
import '@codemirror/autocomplete';
|
||||||
import '@codemirror/commands';
|
import '@codemirror/commands';
|
||||||
import '@codemirror/language';
|
import '@codemirror/language';
|
||||||
import '@codemirror/search';
|
import '@codemirror/search';
|
||||||
|
@ -10,6 +11,7 @@ import '@codemirror/view';
|
||||||
import '@lezer/highlight';
|
import '@lezer/highlight';
|
||||||
|
|
||||||
/* eslint-disable es-x/no-export-ns-from */
|
/* eslint-disable es-x/no-export-ns-from */
|
||||||
|
export * from '@codemirror/autocomplete';
|
||||||
export * from '@codemirror/commands';
|
export * from '@codemirror/commands';
|
||||||
export * from '@codemirror/language';
|
export * from '@codemirror/language';
|
||||||
export * from '@codemirror/search';
|
export * from '@codemirror/search';
|
||||||
|
|
|
@ -35,9 +35,10 @@
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
padding: 0 1px;
|
padding: 0 1px;
|
||||||
opacity: 0.6;
|
opacity: 0.6;
|
||||||
}
|
|
||||||
.cm-tooltip-fold:hover {
|
&:hover {
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.cm-editor .cm-foldPlaceholder {
|
.cm-editor .cm-foldPlaceholder {
|
||||||
|
|
20
resources/codemirror.mediawiki.autocomplete.js
Normal file
20
resources/codemirror.mediawiki.autocomplete.js
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
const {
|
||||||
|
autocompletion,
|
||||||
|
acceptCompletion,
|
||||||
|
keymap
|
||||||
|
} = require( 'ext.CodeMirror.v6.lib' );
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CodeMirror extension providing
|
||||||
|
* autocompletion
|
||||||
|
* for the MediaWiki mode. This automatically applied when using {@link CodeMirrorModeMediaWiki}.
|
||||||
|
*
|
||||||
|
* @module CodeMirrorAutocomplete
|
||||||
|
* @type {Extension}
|
||||||
|
*/
|
||||||
|
const autocompleteExtension = [
|
||||||
|
autocompletion( { defaultKeymap: true } ),
|
||||||
|
keymap.of( [ { key: 'Tab', run: acceptCompletion } ] )
|
||||||
|
];
|
||||||
|
|
||||||
|
module.exports = autocompleteExtension;
|
|
@ -1,15 +1,18 @@
|
||||||
const {
|
const {
|
||||||
|
CompletionSource,
|
||||||
HighlightStyle,
|
HighlightStyle,
|
||||||
LanguageSupport,
|
LanguageSupport,
|
||||||
StreamLanguage,
|
StreamLanguage,
|
||||||
StreamParser,
|
StreamParser,
|
||||||
StringStream,
|
StringStream,
|
||||||
Tag,
|
Tag,
|
||||||
|
ensureSyntaxTree,
|
||||||
syntaxHighlighting
|
syntaxHighlighting
|
||||||
} = require( 'ext.CodeMirror.v6.lib' );
|
} = require( 'ext.CodeMirror.v6.lib' );
|
||||||
const mwModeConfig = require( './codemirror.mediawiki.config.js' );
|
const mwModeConfig = require( './codemirror.mediawiki.config.js' );
|
||||||
const bidiIsolationExtension = require( './codemirror.mediawiki.bidiIsolation.js' );
|
const bidiIsolationExtension = require( './codemirror.mediawiki.bidiIsolation.js' );
|
||||||
const templateFoldingExtension = require( './codemirror.mediawiki.templateFolding.js' );
|
const templateFoldingExtension = require( './codemirror.mediawiki.templateFolding.js' );
|
||||||
|
const autocompleteExtension = require( './codemirror.mediawiki.autocomplete.js' );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MediaWiki language support for CodeMirror 6.
|
* MediaWiki language support for CodeMirror 6.
|
||||||
|
@ -35,8 +38,7 @@ class CodeMirrorModeMediaWiki {
|
||||||
*/
|
*/
|
||||||
constructor( config ) {
|
constructor( config ) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
|
this.urlProtocols = new RegExp( `^(?:${ config.urlProtocols })(?=[^\\s\u00a0{[\\]<>~).,'])`, 'i' );
|
||||||
this.urlProtocols = new RegExp( `^(?:${ this.config.urlProtocols })(?=[^\\s\u00a0{[\\]<>~).,'])`, 'i' );
|
|
||||||
this.isBold = false;
|
this.isBold = false;
|
||||||
this.wasBold = false;
|
this.wasBold = false;
|
||||||
this.isItalic = false;
|
this.isItalic = false;
|
||||||
|
@ -51,7 +53,25 @@ class CodeMirrorModeMediaWiki {
|
||||||
this.registerGroundTokens();
|
this.registerGroundTokens();
|
||||||
|
|
||||||
// Dynamically register any tags that aren't already in CodeMirrorModeMediaWikiConfig
|
// Dynamically register any tags that aren't already in CodeMirrorModeMediaWikiConfig
|
||||||
Object.keys( this.config.tags ).forEach( ( tag ) => mwModeConfig.addTag( tag ) );
|
Object.keys( config.tags ).forEach( ( tag ) => mwModeConfig.addTag( tag ) );
|
||||||
|
|
||||||
|
this.functionSynonyms = [
|
||||||
|
...Object.keys( config.functionSynonyms[ 0 ] )
|
||||||
|
.map( ( label ) => ( { type: 'function', label } ) ),
|
||||||
|
...Object.keys( config.functionSynonyms[ 1 ] )
|
||||||
|
.map( ( label ) => ( { type: 'constant', label } ) )
|
||||||
|
];
|
||||||
|
this.doubleUnderscore = [
|
||||||
|
...Object.keys( config.doubleUnderscore[ 0 ] ),
|
||||||
|
...Object.keys( config.doubleUnderscore[ 1 ] )
|
||||||
|
].map( ( label ) => ( { type: 'constant', label } ) );
|
||||||
|
const extTags = Object.keys( config.tags );
|
||||||
|
this.extTags = extTags.map( ( label ) => ( { type: 'type', label } ) );
|
||||||
|
this.htmlTags = Object.keys( mwModeConfig.permittedHtmlTags )
|
||||||
|
.filter( ( tag ) => !extTags.includes( tag ) )
|
||||||
|
.map( ( label ) => ( { type: 'type', label } ) );
|
||||||
|
this.protocols = config.urlProtocols.split( '|' )
|
||||||
|
.map( ( label ) => ( { type: 'namespace', label: label.replace( /\\([:/])/g, '$1' ) } ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1097,6 +1117,87 @@ class CodeMirrorModeMediaWiki {
|
||||||
this.wasItalic = this.isItalic;
|
this.wasItalic = this.isItalic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Autocompletion for magic words and tag names.
|
||||||
|
*
|
||||||
|
* @return {CompletionSource}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
get completionSource() {
|
||||||
|
return ( context ) => {
|
||||||
|
const { state, pos, explicit } = context,
|
||||||
|
tree = ensureSyntaxTree( state, pos ),
|
||||||
|
node = tree && tree.resolve( pos, -1 );
|
||||||
|
if ( !node ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
const types = new Set( node.name.split( '_' ) ),
|
||||||
|
isParserFunction = types.has( mwModeConfig.tags.parserFunctionName ),
|
||||||
|
{ from, to } = node,
|
||||||
|
search = state.sliceDoc( from, to );
|
||||||
|
if ( explicit || isParserFunction && search.includes( '#' ) ) {
|
||||||
|
const validFor = /^[^|{}<>[\]#]*$/;
|
||||||
|
if ( isParserFunction || types.has( mwModeConfig.tags.templateName ) && !search.includes( ':' ) ) {
|
||||||
|
return {
|
||||||
|
from,
|
||||||
|
options: this.functionSynonyms,
|
||||||
|
validFor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
} else if ( !types.has( mwModeConfig.tags.comment ) &&
|
||||||
|
!types.has( mwModeConfig.tags.templateVariableName ) &&
|
||||||
|
!types.has( mwModeConfig.tags.templateName ) &&
|
||||||
|
!types.has( mwModeConfig.tags.linkPageName ) &&
|
||||||
|
!types.has( mwModeConfig.tags.linkToSection ) &&
|
||||||
|
!types.has( mwModeConfig.tags.extLink )
|
||||||
|
) {
|
||||||
|
let mt = context.matchBefore( /__(?:(?!__)[^\s<>[\]{}|#])*$/ );
|
||||||
|
if ( mt ) {
|
||||||
|
return {
|
||||||
|
from: mt.from,
|
||||||
|
options: this.doubleUnderscore,
|
||||||
|
validFor: /^[^\s<>[\]{}|#]*$/
|
||||||
|
};
|
||||||
|
}
|
||||||
|
mt = context.matchBefore( /<\/?[a-z\d]*$/i );
|
||||||
|
const extTags = [ ...types ].filter( ( t ) => t.startsWith( 'mw-tag-' ) ).map( ( s ) => s.slice( 7 ) );
|
||||||
|
if ( mt && mt.to - mt.from > 1 ) {
|
||||||
|
const validFor = /^[a-z\d]*$/i;
|
||||||
|
if ( mt.text[ 1 ] === '/' ) {
|
||||||
|
const extTag = extTags[ extTags.length - 1 ],
|
||||||
|
options = [
|
||||||
|
...this.htmlTags.filter( ( { label } ) => !(
|
||||||
|
label in mwModeConfig.implicitlyClosedHtmlTags
|
||||||
|
) ),
|
||||||
|
...extTag ? [ { type: 'type', label: extTag, boost: 50 } ] : []
|
||||||
|
];
|
||||||
|
return { from: mt.from + 2, options, validFor };
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
from: mt.from + 1,
|
||||||
|
options: [
|
||||||
|
...this.htmlTags,
|
||||||
|
...this.extTags.filter( ( { label } ) => !extTags.includes( label ) )
|
||||||
|
],
|
||||||
|
validFor
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if ( !types.has( mwModeConfig.tags.linkText ) &&
|
||||||
|
!types.has( mwModeConfig.tags.extLinkText ) ) {
|
||||||
|
mt = context.matchBefore( /(?:^|[^[])\[[a-z:/]+$/i );
|
||||||
|
if ( mt ) {
|
||||||
|
return {
|
||||||
|
from: mt.from + ( mt.text[ 1 ] === '[' ? 2 : 1 ),
|
||||||
|
options: this.protocols,
|
||||||
|
validFor: /^[a-z:/]*$/i
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see https://codemirror.net/docs/ref/#language.StreamParser
|
* @see https://codemirror.net/docs/ref/#language.StreamParser
|
||||||
* @return {StreamParser}
|
* @return {StreamParser}
|
||||||
|
@ -1257,7 +1358,18 @@ class CodeMirrorModeMediaWiki {
|
||||||
* @return {Object<Tag>}
|
* @return {Object<Tag>}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
tokenTable: this.tokenTable
|
tokenTable: this.tokenTable,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see https://codemirror.net/docs/ref/#language.StreamParser.languageData
|
||||||
|
* @return {Object<any>}
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
languageData: {
|
||||||
|
// TODO: Rewrite the comment command using jQuery.textSelection
|
||||||
|
commentTokens: { block: { open: '<!--', close: '-->' } },
|
||||||
|
autocomplete: this.completionSource
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1271,6 +1383,7 @@ class CodeMirrorModeMediaWiki {
|
||||||
* @param {boolean} [config.bidiIsolation=false] Enable bidi isolation around HTML tags.
|
* @param {boolean} [config.bidiIsolation=false] Enable bidi isolation around HTML tags.
|
||||||
* This should generally always be enabled on RTL pages, but it comes with a performance cost.
|
* This should generally always be enabled on RTL pages, but it comes with a performance cost.
|
||||||
* @param {boolean} [config.templateFolding=true] Enable template folding.
|
* @param {boolean} [config.templateFolding=true] Enable template folding.
|
||||||
|
* @param {boolean} [config.autocomplete=true] Enable autocompletion.
|
||||||
* @param {Object|null} [mwConfig] Ignore; used only by unit tests.
|
* @param {Object|null} [mwConfig] Ignore; used only by unit tests.
|
||||||
* @return {LanguageSupport}
|
* @return {LanguageSupport}
|
||||||
* @stable to call
|
* @stable to call
|
||||||
|
@ -1292,6 +1405,9 @@ const mediaWikiLang = ( config = { bidiIsolation: false }, mwConfig = null ) =>
|
||||||
if ( config.templateFolding !== false ) {
|
if ( config.templateFolding !== false ) {
|
||||||
cm.preferences.registerExtension( 'templateFolding', templateFoldingExtension, cm.view );
|
cm.preferences.registerExtension( 'templateFolding', templateFoldingExtension, cm.view );
|
||||||
}
|
}
|
||||||
|
if ( config.autocomplete !== false ) {
|
||||||
|
cm.preferences.registerExtension( 'autocomplete', autocompleteExtension, cm.view );
|
||||||
|
}
|
||||||
if ( config.bidiIsolation ) {
|
if ( config.bidiIsolation ) {
|
||||||
cm.preferences.registerExtension( 'bidiIsolation', bidiIsolationExtension, cm.view );
|
cm.preferences.registerExtension( 'bidiIsolation', bidiIsolationExtension, cm.view );
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ const {
|
||||||
unfoldAll,
|
unfoldAll,
|
||||||
unfoldEffect
|
unfoldEffect
|
||||||
} = require( 'ext.CodeMirror.v6.lib' );
|
} = require( 'ext.CodeMirror.v6.lib' );
|
||||||
const modeConfig = require( './codemirror.mediawiki.config.js' );
|
const mwModeConfig = require( './codemirror.mediawiki.config.js' );
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if a SyntaxNode is a template bracket (`{{` or `}}`)
|
* Check if a SyntaxNode is a template bracket (`{{` or `}}`)
|
||||||
|
@ -25,7 +25,7 @@ const modeConfig = require( './codemirror.mediawiki.config.js' );
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
const isBracket = ( node ) => node.name.split( '_' ).includes( modeConfig.tags.templateBracket ),
|
const isBracket = ( node ) => node.name.split( '_' ).includes( mwModeConfig.tags.templateBracket ),
|
||||||
/**
|
/**
|
||||||
* Check if a SyntaxNode is a template delimiter (`|`)
|
* Check if a SyntaxNode is a template delimiter (`|`)
|
||||||
*
|
*
|
||||||
|
@ -33,7 +33,7 @@ const isBracket = ( node ) => node.name.split( '_' ).includes( modeConfig.tags.t
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
isDelimiter = ( node ) => node.name.split( '_' ).includes( modeConfig.tags.templateDelimiter ),
|
isDelimiter = ( node ) => node.name.split( '_' ).includes( mwModeConfig.tags.templateDelimiter ),
|
||||||
/**
|
/**
|
||||||
* Check if a SyntaxNode is part of a template, except for the brackets
|
* Check if a SyntaxNode is part of a template, except for the brackets
|
||||||
*
|
*
|
||||||
|
@ -41,7 +41,7 @@ const isBracket = ( node ) => node.name.split( '_' ).includes( modeConfig.tags.t
|
||||||
* @return {boolean}
|
* @return {boolean}
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
isTemplate = ( node ) => /-template[a-z\d-]+ground/u.test( node.name ) && !isBracket( node ),
|
isTemplate = ( node ) => /-template[a-z\d-]+ground/.test( node.name ) && !isBracket( node ),
|
||||||
/**
|
/**
|
||||||
* Update the stack of opening (+) or closing (-) brackets
|
* Update the stack of opening (+) or closing (-) brackets
|
||||||
*
|
*
|
||||||
|
|
|
@ -182,7 +182,7 @@ class CodeMirrorPreferences extends CodeMirrorPanel {
|
||||||
// Some preferences can be set per-namespace through wiki configuration.
|
// Some preferences can be set per-namespace through wiki configuration.
|
||||||
// Values are an array of namespace IDs, [] to disable everywhere,
|
// Values are an array of namespace IDs, [] to disable everywhere,
|
||||||
// or null to enable everywhere.
|
// or null to enable everywhere.
|
||||||
const namespacePrefs = [ 'lineNumbering', 'templateFolding' ];
|
const namespacePrefs = [ 'lineNumbering', 'templateFolding', 'autocomplete' ];
|
||||||
if ( namespacePrefs.includes( prefName ) ) {
|
if ( namespacePrefs.includes( prefName ) ) {
|
||||||
const namespaces = mw.config.get( 'extCodeMirrorConfig' )[ prefName + 'Namespaces' ];
|
const namespaces = mw.config.get( 'extCodeMirrorConfig' )[ prefName + 'Namespaces' ];
|
||||||
return !namespaces || namespaces.includes( mw.config.get( 'wgNamespaceNumber' ) );
|
return !namespaces || namespaces.includes( mw.config.get( 'wgNamespaceNumber' ) );
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -22,7 +22,12 @@ document.body.appendChild( textarea );
|
||||||
const cm = new CodeMirror( textarea );
|
const cm = new CodeMirror( textarea );
|
||||||
const mwLang = mediaWikiLang(
|
const mwLang = mediaWikiLang(
|
||||||
{ bidiIsolation: true },
|
{ bidiIsolation: true },
|
||||||
{ tags: { ref: true } }
|
{
|
||||||
|
doubleUnderscore: [ {}, {} ],
|
||||||
|
functionSynonyms: [ {}, {} ],
|
||||||
|
tags: { ref: true },
|
||||||
|
urlProtocols: 'http\\:\\/\\/'
|
||||||
|
}
|
||||||
);
|
);
|
||||||
cm.initialize( [ ...cm.defaultExtensions, mwLang ] );
|
cm.initialize( [ ...cm.defaultExtensions, mwLang ] );
|
||||||
// Normally ran by mw.hook, but we don't mock the hook system in the Jest tests.
|
// Normally ran by mw.hook, but we don't mock the hook system in the Jest tests.
|
||||||
|
|
|
@ -184,7 +184,7 @@ const mwLang = mediaWikiLang( {}, {
|
||||||
urlProtocols: 'ftp://|https://|news:',
|
urlProtocols: 'ftp://|https://|news:',
|
||||||
doubleUnderscore: [ {
|
doubleUnderscore: [ {
|
||||||
__notoc__: 'notoc'
|
__notoc__: 'notoc'
|
||||||
} ],
|
}, {} ],
|
||||||
functionSynonyms: [ {}, {
|
functionSynonyms: [ {}, {
|
||||||
'!': '!',
|
'!': '!',
|
||||||
'מיון רגיל': 'defaultsort'
|
'מיון רגיל': 'defaultsort'
|
||||||
|
|
|
@ -17,6 +17,7 @@ class DataScriptTest extends \MediaWikiIntegrationTestCase {
|
||||||
$this->assertStringContainsString( '"extCodeMirrorConfig":', $script );
|
$this->assertStringContainsString( '"extCodeMirrorConfig":', $script );
|
||||||
$this->assertStringContainsString( '"lineNumberingNamespaces":', $script );
|
$this->assertStringContainsString( '"lineNumberingNamespaces":', $script );
|
||||||
$this->assertStringContainsString( '"templateFoldingNamespaces":', $script );
|
$this->assertStringContainsString( '"templateFoldingNamespaces":', $script );
|
||||||
|
$this->assertStringContainsString( '"autocompleteNamespaces":', $script );
|
||||||
$this->assertStringContainsString( '"pluginModules":', $script );
|
$this->assertStringContainsString( '"pluginModules":', $script );
|
||||||
$this->assertStringContainsString( '"tagModes":', $script );
|
$this->assertStringContainsString( '"tagModes":', $script );
|
||||||
$this->assertStringContainsString( '"tags":', $script );
|
$this->assertStringContainsString( '"tags":', $script );
|
||||||
|
|
Loading…
Reference in a new issue