mirror of
https://gerrit.wikimedia.org/r/mediawiki/extensions/CodeMirror
synced 2024-11-23 13:56:44 +00:00
Isolate build step to CM6 library and restructure files to work with RL
CodeMirror 6 requires the use of NPM, but we can still bundle all CM packages into one file, and then everything else (i.e. our code) is managed by ResourceLoader as per usual. This makes contribution considerably easier as we no longer need a build step for each change. CM5 files are now under resources/legacy, and the CM6 files are moved to the root of the resources/ directory. Only one file, codemirror.bundle.js, is managed by Rollup, while everything else is RL. The Rollup output for now is put under resources/lib/ alongside the CM5 upstream files. This patch is *mostly* renames of files, along with changing ECMAScript Module (ESM) syntax into the CommonJS style that ResourceLoader prefers. We also remove more modern JS syntax (i.e. private class methods) that we were able to use before because we had a build step with Babel. This patch should effectively make no user-facing changes, or to the ResourceLoader modules we offer in Extension:CodeMirror. Finally, bump version in extension.json to 6, to match the upstream lib, and add Bhsd as an author :-) Bug: T368053 Change-Id: Ie258e49f5df8db23a7344ac3c4c9300aaa991042
This commit is contained in:
parent
f3be172173
commit
7d3482f89e
4
.babelrc
4
.babelrc
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"presets": ["@babel/preset-env"],
|
||||
"plugins": ["@babel/plugin-transform-private-methods"]
|
||||
}
|
34
README.md
34
README.md
|
@ -1,27 +1,30 @@
|
|||
The CodeMirror extension provides syntax highlighting in MediaWiki wikitext editors using
|
||||
the [CodeMirror library](https://codemirror.net/).
|
||||
|
||||
CodeMirror 6 homepage: [https://www.mediawiki.org/wiki/Extension:CodeMirror/6](https://www.mediawiki.org/wiki/Extension:CodeMirror/6)
|
||||
|
||||
JS documentation: [https://doc.wikimedia.org/CodeMirror](https://doc.wikimedia.org/CodeMirror)
|
||||
|
||||
## Development
|
||||
|
||||
As part of the [upgrade to CodeMirror 6](https://phabricator.wikimedia.org/T259059),
|
||||
CodeMirror now uses an asset bundler, so during development you'll need to run a script
|
||||
to assemble the frontend assets.
|
||||
### Preface
|
||||
|
||||
Extension:CodeMirror is currently in the process of being upgraded to the new major version, CodeMirror 6.
|
||||
See the [change log](https://www.mediawiki.org/wiki/Extension:CodeMirror/6#Change_log) for details.
|
||||
|
||||
Use of CodeMirror 6 is controlled by the `wgCodeMirrorV6` configuration setting, or by
|
||||
passing in `cm6enable=1` in the URL query string.
|
||||
|
||||
You can find the v6 frontend source files in `src/`, the compiled sources in
|
||||
`resources/dist/`, and other frontend assets managed by ResourceLoader in
|
||||
`resources/*`.
|
||||
CodeMirror 6 requires the use of NPM to bundle the dependencies. These are bundled in
|
||||
[resources/codemirror.bundle.js](resources/codemirror.bundle.js), built using [Rollup](https://rollupjs.org/),
|
||||
and packaged as the `ext.CodeMirror.v6.lib` ResourceLoader module. If you make changes to the
|
||||
versions of the dependencies, you will need to run `npm run build` to update the ResourceLoader module.
|
||||
|
||||
### Commands
|
||||
### NPM commands
|
||||
|
||||
_NOTE: Consider using [Fresh](https://gerrit.wikimedia.org/g/fresh/) to run these tasks._
|
||||
|
||||
* `npm install` to install dependencies.
|
||||
* `npm start` to run the bundler in watch mode, reassembling the files on file change.
|
||||
You'll want to keep this running in a separate terminal during development.
|
||||
* `npm run build` to compile the production assets. You *must* run this step before
|
||||
sending the patch or CI will fail (so that sources and built assets are in sync).
|
||||
* `npm run doc` to generate the API documentation.
|
||||
* `npm test` to run the linting tools, JavaScript unit tests, and build checks.
|
||||
* `npm run test:lint` for linting of JS/LESS/CSS.
|
||||
|
@ -30,9 +33,8 @@ _NOTE: Consider using [Fresh](https://gerrit.wikimedia.org/g/fresh/) to run thes
|
|||
* `npm run test:i18n` for linting of i18n messages with banana-checker.
|
||||
* `npm run test:unit` for the new Jest unit tests.
|
||||
* `npm run selenium-test` for the Selenium tests.
|
||||
* `npm run build` to rebundle the CodeMirror library. If changes are made to the `@codemirror`
|
||||
or `@lezer` dependencies in [package.json](package.json), this command *must* be run before
|
||||
sending the patch or CI will fail.
|
||||
* Older QUnit tests are in `resources/mode/mediawiki/tests/qunit/`. These have been
|
||||
replaced and will be removed after the CodeMirror 6 upgrade.
|
||||
|
||||
## CodeMirror 6 change log
|
||||
|
||||
* See [Extension:CodeMirror/6](https://www.mediawiki.org/wiki/Special:MyLanguage/Extension:CodeMirror/6#Differences_from_CodeMirror_5)
|
||||
replaced and will be removed after the CodeMirror 6 upgrade is complete.
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
{
|
||||
"name": "CodeMirror",
|
||||
"version": "5.0.0",
|
||||
"version": "6.0.0",
|
||||
"author": [
|
||||
"[https://www.mediawiki.org/wiki/User:Pastakhov Pavel Astakhov]",
|
||||
"[https://www.mediawiki.org/wiki/User:Florianschmidtwelzow Florian Schmidt]",
|
||||
"Marijn Haverbeke",
|
||||
"MusikAnimal",
|
||||
"Bhsd",
|
||||
"[https://raw.githubusercontent.com/codemirror/CodeMirror/master/AUTHORS CodeMirror contributors]"
|
||||
],
|
||||
"url": "https://www.mediawiki.org/wiki/Extension:CodeMirror",
|
||||
|
@ -58,9 +59,9 @@
|
|||
"user.options"
|
||||
],
|
||||
"packageFiles": [
|
||||
"ext.CodeMirror.js",
|
||||
"legacy/ext.CodeMirror.js",
|
||||
{
|
||||
"name": "ext.CodeMirror.data.js",
|
||||
"name": "legacy/ext.CodeMirror.data.js",
|
||||
"callback": "MediaWiki\\Extension\\CodeMirror\\DataScript::makeScript"
|
||||
}
|
||||
]
|
||||
|
@ -74,10 +75,10 @@
|
|||
"oojs-ui.styles.icons-editing-styling"
|
||||
],
|
||||
"packageFiles": [
|
||||
"ext.CodeMirror.WikiEditor.js"
|
||||
"legacy/ext.CodeMirror.WikiEditor.js"
|
||||
],
|
||||
"styles": [
|
||||
"ext.CodeMirror.less"
|
||||
"legacy/ext.CodeMirror.less"
|
||||
],
|
||||
"messages": [
|
||||
"codemirror-toggle-label"
|
||||
|
@ -89,22 +90,22 @@
|
|||
],
|
||||
"styles": [
|
||||
"lib/codemirror/lib/codemirror.css",
|
||||
"lib/codemirror-fixes.less"
|
||||
"legacy/codemirror-fixes.less"
|
||||
]
|
||||
},
|
||||
"ext.CodeMirror.addons": {
|
||||
"scripts": [
|
||||
"addon/edit/matchbrackets-wmde.js"
|
||||
"legacy/addon/matchbrackets-wmde.js"
|
||||
],
|
||||
"dependencies": [
|
||||
"ext.CodeMirror.lib"
|
||||
]
|
||||
},
|
||||
"ext.CodeMirror.mode.mediawiki": {
|
||||
"packageFiles": "mode/mediawiki/mediawiki.js",
|
||||
"packageFiles": "legacy/mode/mediawiki/mediawiki.js",
|
||||
"styles": [
|
||||
"mode/mediawiki/mediawiki.less",
|
||||
"mode/mediawiki/colorblind-colors.less"
|
||||
"codemirror.mediawiki.less",
|
||||
"codemirror.mediawiki.colorblind.less"
|
||||
],
|
||||
"dependencies": [
|
||||
"ext.CodeMirror.lib"
|
||||
|
@ -160,11 +161,11 @@
|
|||
"ext.CodeMirror"
|
||||
],
|
||||
"scripts": [
|
||||
"modules/ve-cm/ve.ui.CodeMirrorAction.js",
|
||||
"modules/ve-cm/ve.ui.CodeMirrorTool.js"
|
||||
"legacy/modules/ve-cm/ve.ui.CodeMirrorAction.js",
|
||||
"legacy/modules/ve-cm/ve.ui.CodeMirrorTool.js"
|
||||
],
|
||||
"styles": [
|
||||
"modules/ve-cm/ve.ui.CodeMirror.less"
|
||||
"legacy/modules/ve-cm/ve.ui.CodeMirror.less"
|
||||
],
|
||||
"messages": [
|
||||
"codemirror-toggle-label"
|
||||
|
@ -172,21 +173,21 @@
|
|||
},
|
||||
"ext.CodeMirror.v6": {
|
||||
"dependencies": [
|
||||
"web2017-polyfills",
|
||||
"mediawiki.api",
|
||||
"mediawiki.user",
|
||||
"user.options",
|
||||
"ext.CodeMirror.v6.lib"
|
||||
],
|
||||
"packageFiles": [
|
||||
"dist/codemirror.js",
|
||||
"codemirror.js",
|
||||
"codemirror.textSelection.js",
|
||||
{
|
||||
"name": "ext.CodeMirror.data.js",
|
||||
"callback": "MediaWiki\\Extension\\CodeMirror\\DataScript::makeScript"
|
||||
}
|
||||
],
|
||||
"styles": [
|
||||
"ext.CodeMirror.v6.less"
|
||||
"codemirror.less"
|
||||
],
|
||||
"messages": [
|
||||
"codemirror-find",
|
||||
|
@ -234,22 +235,24 @@
|
|||
"ext.CodeMirror.v6.mode.mediawiki"
|
||||
],
|
||||
"packageFiles": [
|
||||
"dist/codemirror.mediawiki.js"
|
||||
"codemirror.mediawiki.init.js"
|
||||
]
|
||||
},
|
||||
"ext.CodeMirror.v6.lib": {
|
||||
"packageFiles": [
|
||||
"dist/vendor.js"
|
||||
],
|
||||
"dependencies": [
|
||||
"web2017-polyfills"
|
||||
"lib/codemirror6.bundle.dist.js"
|
||||
]
|
||||
},
|
||||
"ext.CodeMirror.v6.mode.mediawiki": {
|
||||
"packageFiles": "dist/codemirror.mode.mediawiki.js",
|
||||
"packageFiles": [
|
||||
"codemirror.mediawiki.js",
|
||||
"codemirror.mediawiki.config.js",
|
||||
"codemirror.mediawiki.bidiIsolation.js",
|
||||
"codemirror.mediawiki.templateFolding.js"
|
||||
],
|
||||
"styles": [
|
||||
"mode/mediawiki/mediawiki.less",
|
||||
"mode/mediawiki/colorblind-colors.less"
|
||||
"codemirror.mediawiki.less",
|
||||
"codemirror.mediawiki.colorblind.less"
|
||||
],
|
||||
"dependencies": [
|
||||
"ext.CodeMirror.v6",
|
||||
|
@ -258,11 +261,10 @@
|
|||
},
|
||||
"ext.CodeMirror.v6.WikiEditor": {
|
||||
"dependencies": [
|
||||
"ext.wikiEditor",
|
||||
"ext.CodeMirror.v6"
|
||||
"ext.wikiEditor"
|
||||
],
|
||||
"packageFiles": [
|
||||
"dist/codemirror.wikieditor.js"
|
||||
"codemirror.wikieditor.js"
|
||||
],
|
||||
"messages": [
|
||||
"codemirror-toggle-label"
|
||||
|
@ -274,7 +276,7 @@
|
|||
"ext.CodeMirror.v6.mode.mediawiki"
|
||||
],
|
||||
"packageFiles": [
|
||||
"dist/codemirror.wikieditor.mediawiki.js"
|
||||
"codemirror.wikieditor.mediawiki.init.js"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
@ -287,8 +289,8 @@
|
|||
"usecodemirror": 0
|
||||
},
|
||||
"QUnitTestModule": {
|
||||
"localBasePath": "resources/mode/mediawiki/tests",
|
||||
"remoteExtPath": "CodeMirror/resources/mode/mediawiki/tests",
|
||||
"localBasePath": "resources/legacy/mode/mediawiki/tests",
|
||||
"remoteExtPath": "CodeMirror/resources/legacy/mode/mediawiki/tests",
|
||||
"packageFiles": [
|
||||
"qunit/CodeMirror.mediawiki.test.js"
|
||||
],
|
||||
|
|
|
@ -11,7 +11,8 @@
|
|||
"node_modules/jsdoc-wmf-theme/plugins/default"
|
||||
],
|
||||
"source": {
|
||||
"include": [ "src" ],
|
||||
"include": [ "resources" ],
|
||||
"exclude": [ "resources/legacy", "resources/lib" ],
|
||||
"includePattern": ".+\\.js$"
|
||||
},
|
||||
"tags": {},
|
||||
|
@ -25,9 +26,10 @@
|
|||
"repository": "https://gerrit.wikimedia.org/g/mediawiki/extensions/CodeMirror",
|
||||
"linkMap": {
|
||||
"jQuery.fn.textSelection": "https://doc.wikimedia.org/mediawiki-core/master/js/jQueryPlugins.html#.textSelection",
|
||||
|
||||
"Compartment": "https://codemirror.net/docs/ref/#state.Compartment",
|
||||
"Decoration": "https://codemirror.net/docs/ref/#view.Decoration",
|
||||
"DecorationSet": "https://codemirror.net/docs/ref/#view.DecorationSet",
|
||||
"Direction": "https://codemirror.net/docs/ref/#view.Direction",
|
||||
"EditorState": "https://codemirror.net/docs/ref/#state.EditorState",
|
||||
"EditorView": "https://codemirror.net/docs/ref/#view.EditorView",
|
||||
"Extension": "https://codemirror.net/docs/ref/#state.Extension",
|
||||
|
|
2665
package-lock.json
generated
2665
package-lock.json
generated
File diff suppressed because it is too large
Load diff
24
package.json
24
package.json
|
@ -1,16 +1,15 @@
|
|||
{
|
||||
"name": "CodeMirror",
|
||||
"name": "codemirror",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"start": "rollup -c --watch",
|
||||
"build": "rollup -c --environment BUILD:production",
|
||||
"build": "rollup -c",
|
||||
"test": "npm run test:lint && npm run test:unit && npm run check-built-assets",
|
||||
"test:lint": "npm run test:lint:styles && npm run test:lint:js && npm run test:lint:i18n",
|
||||
"test:lint:js": "eslint --cache .",
|
||||
"test:lint:styles": "stylelint \"resources/**/*.less\"",
|
||||
"test:lint:i18n": "banana-checker i18n/",
|
||||
"test:unit": "jest",
|
||||
"check-built-assets": "{ git status src/ | grep \"nothing to commit, working tree clean\"; } && { echo 'CHECKING BUILD SOURCES ARE COMMITTED' && npm run build && git status resources/dist/ | grep \"nothing to commit, working tree clean\" || { npm run node-debug; false; }; }",
|
||||
"check-built-assets": "{ git status src/ | grep \"nothing to commit, working tree clean\"; } && { echo 'CHECKING BUILD SOURCES ARE COMMITTED' && npm run build && git status resources/lib/ | grep \"nothing to commit, working tree clean\" || { npm run node-debug; false; }; }",
|
||||
"node-debug": "node -v && npm -v && echo 'ERROR: Please ensure that production assets have been built with `npm run build` and commited, and that you are using the correct version of Node/NPM.'",
|
||||
"selenium-test": "wdio tests/selenium/wdio.conf.js",
|
||||
"doc": "jsdoc -c jsdoc.json"
|
||||
|
@ -19,22 +18,18 @@
|
|||
"node": "18.20.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/plugin-transform-private-methods": "7.23.3",
|
||||
"@babel/preset-env": "7.24.0",
|
||||
"@codemirror/commands": "6.2.5",
|
||||
"@codemirror/language": "6.9.3",
|
||||
"@codemirror/search": "6.5.4",
|
||||
"@codemirror/state": "6.2.1",
|
||||
"@codemirror/view": "6.22.2",
|
||||
"@lezer/highlight": "1.2.0",
|
||||
"@rollup/plugin-babel": "6.0.4",
|
||||
"@rollup/plugin-node-resolve": "15.2.3",
|
||||
"@rollup/plugin-terser": "0.4.4",
|
||||
"@wdio/cli": "7.30.1",
|
||||
"@wdio/junit-reporter": "7.29.1",
|
||||
"@wdio/local-runner": "7.30.1",
|
||||
"@wdio/mocha-framework": "7.26.0",
|
||||
"@wdio/spec-reporter": "7.29.1",
|
||||
"@wdio/cli": "7.36.0",
|
||||
"@wdio/junit-reporter": "7.35.0",
|
||||
"@wdio/local-runner": "7.36.0",
|
||||
"@wdio/mocha-framework": "7.33.0",
|
||||
"@wdio/spec-reporter": "7.33.0",
|
||||
"@wikimedia/mw-node-qunit": "7.2.0",
|
||||
"dotenv": "8.2.0",
|
||||
"eslint-config-wikimedia": "0.28.2",
|
||||
|
@ -45,8 +40,7 @@
|
|||
"jsdoc": "4.0.3",
|
||||
"jsdoc-wmf-theme": "1.1.0",
|
||||
"rollup": "4.13.0",
|
||||
"rollup-plugin-copy": "3.5.0",
|
||||
"stylelint-config-wikimedia": "0.16.1",
|
||||
"wdio-mediawiki": "2.3.0"
|
||||
"wdio-mediawiki": "2.5.0"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,13 +6,18 @@
|
|||
"wikimedia/mediawiki"
|
||||
],
|
||||
"parserOptions": {
|
||||
"sourceType": "commonjs"
|
||||
"sourceType": "module"
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"commonjs": true
|
||||
},
|
||||
"globals": {
|
||||
"CodeMirror": "readonly"
|
||||
"Tree": "readonly"
|
||||
},
|
||||
"rules": {
|
||||
"max-len": "off"
|
||||
"max-len": "off",
|
||||
"es-x/no-array-prototype-includes": "off"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
|
|
18
resources/codemirror.bundle.js
Normal file
18
resources/codemirror.bundle.js
Normal file
|
@ -0,0 +1,18 @@
|
|||
/**
|
||||
* This file is managed by Rollup and bundles all the CodeMirror dependencies
|
||||
* into the single file resources/lib/codemirror6.bundle.dist.js.
|
||||
*/
|
||||
import '@codemirror/commands';
|
||||
import '@codemirror/language';
|
||||
import '@codemirror/search';
|
||||
import '@codemirror/state';
|
||||
import '@codemirror/view';
|
||||
import '@lezer/highlight';
|
||||
|
||||
/* eslint-disable es-x/no-export-ns-from */
|
||||
export * from '@codemirror/commands';
|
||||
export * from '@codemirror/language';
|
||||
export * from '@codemirror/search';
|
||||
export * from '@codemirror/state';
|
||||
export * from '@codemirror/view';
|
||||
export * from '@lezer/highlight';
|
|
@ -1,20 +1,23 @@
|
|||
import { EditorState, Extension, Compartment } from '@codemirror/state';
|
||||
import {
|
||||
const {
|
||||
EditorState,
|
||||
EditorView,
|
||||
drawSelection,
|
||||
lineNumbers,
|
||||
highlightSpecialChars,
|
||||
keymap,
|
||||
rectangularSelection,
|
||||
Extension,
|
||||
Compartment,
|
||||
ViewUpdate,
|
||||
bracketMatching,
|
||||
crosshairCursor,
|
||||
ViewUpdate
|
||||
} from '@codemirror/view';
|
||||
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
|
||||
import { searchKeymap } from '@codemirror/search';
|
||||
import { bracketMatching } from '@codemirror/language';
|
||||
import CodeMirrorTextSelection from './codemirror.textSelection';
|
||||
|
||||
require( '../ext.CodeMirror.data.js' );
|
||||
defaultKeymap,
|
||||
drawSelection,
|
||||
highlightSpecialChars,
|
||||
history,
|
||||
historyKeymap,
|
||||
keymap,
|
||||
lineNumbers,
|
||||
rectangularSelection,
|
||||
searchKeymap
|
||||
} = require( 'ext.CodeMirror.v6.lib' );
|
||||
const CodeMirrorTextSelection = require( './codemirror.textSelection.js' );
|
||||
require( './ext.CodeMirror.data.js' );
|
||||
|
||||
/**
|
||||
* Interface for the CodeMirror editor.
|
||||
|
@ -381,7 +384,7 @@ class CodeMirror {
|
|||
} );
|
||||
|
||||
// Add CodeMirror view to the DOM.
|
||||
this.#addCodeMirrorToDom();
|
||||
this.addCodeMirrorToDom();
|
||||
|
||||
// Hide native textarea and sync CodeMirror contents upon submission.
|
||||
this.$textarea.hide();
|
||||
|
@ -418,7 +421,7 @@ class CodeMirror {
|
|||
*
|
||||
* @private
|
||||
*/
|
||||
#addCodeMirrorToDom() {
|
||||
addCodeMirrorToDom() {
|
||||
this.$textarea.wrap( '<div class="ext-codemirror-wrapper"></div>' );
|
||||
|
||||
this.view = new EditorView( {
|
||||
|
@ -521,4 +524,4 @@ class CodeMirror {
|
|||
}
|
||||
}
|
||||
|
||||
export default CodeMirror;
|
||||
module.exports = CodeMirror;
|
|
@ -1,15 +1,17 @@
|
|||
import {
|
||||
const {
|
||||
Decoration,
|
||||
DecorationSet,
|
||||
Direction,
|
||||
EditorView,
|
||||
PluginSpec,
|
||||
Prec,
|
||||
RangeSet,
|
||||
RangeSetBuilder,
|
||||
ViewPlugin,
|
||||
ViewUpdate
|
||||
} from '@codemirror/view';
|
||||
import { Prec, RangeSet, RangeSetBuilder } from '@codemirror/state';
|
||||
import { syntaxTree } from '@codemirror/language';
|
||||
import { mwModeConfig } from './codemirror.mode.mediawiki.config';
|
||||
ViewUpdate,
|
||||
syntaxTree
|
||||
} = require( 'ext.CodeMirror.v6.lib' );
|
||||
const mwModeConfig = require( './codemirror.mediawiki.config.js' );
|
||||
|
||||
/**
|
||||
* @type {Decoration}
|
||||
|
@ -122,4 +124,4 @@ const bidiIsolationSpec = {
|
|||
* @module CodeMirrorBidiIsolation
|
||||
* @see https://codemirror.net/examples/bidi/
|
||||
*/
|
||||
export default ViewPlugin.fromClass( CodeMirrorBidiIsolation, bidiIsolationSpec );
|
||||
module.exports = ViewPlugin.fromClass( CodeMirrorBidiIsolation, bidiIsolationSpec );
|
|
@ -1,5 +1,9 @@
|
|||
import { Tag, tags } from '@lezer/highlight';
|
||||
import { TagStyle, StreamParser } from '@codemirror/language';
|
||||
const {
|
||||
StreamParser,
|
||||
Tag,
|
||||
TagStyle,
|
||||
tags
|
||||
} = require( 'ext.CodeMirror.v6.lib' );
|
||||
|
||||
/**
|
||||
* Configuration for the MediaWiki highlighting mode for CodeMirror.
|
||||
|
@ -10,7 +14,7 @@ import { TagStyle, StreamParser } from '@codemirror/language';
|
|||
*
|
||||
* @example
|
||||
* // within MediaWiki:
|
||||
* import { mwModeConfig } from 'ext.CodeMirror.v6.mode.mediawiki';
|
||||
* const { mwModeConfig } = require( 'ext.CodeMirror.v6.mode.mediawiki' );
|
||||
* // Reference tags by their constants in the tags property.
|
||||
* if ( tag === mwModeConfig.tags.htmlTagBracket ) {
|
||||
* // …
|
||||
|
@ -118,7 +122,7 @@ class CodeMirrorModeMediaWikiConfig {
|
|||
* @return {Object<string>}
|
||||
*/
|
||||
get tags() {
|
||||
return {
|
||||
return Object.assign( {
|
||||
apostrophes: 'character',
|
||||
apostrophesBold: 'strong',
|
||||
apostrophesItalic: 'emphasis',
|
||||
|
@ -160,9 +164,8 @@ class CodeMirrorModeMediaWikiConfig {
|
|||
templateName: 'moduleKeyword',
|
||||
templateVariable: 'atom',
|
||||
templateVariableBracket: 'brace',
|
||||
templateVariableName: 'variableName',
|
||||
...this.#customTags
|
||||
};
|
||||
templateVariableName: 'variableName'
|
||||
}, this.customTags );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -175,7 +178,7 @@ class CodeMirrorModeMediaWikiConfig {
|
|||
* @return {Object<string>}
|
||||
* @private
|
||||
*/
|
||||
get #customTags() {
|
||||
get customTags() {
|
||||
return {
|
||||
em: 'mw-em',
|
||||
error: 'mw-error',
|
||||
|
@ -203,7 +206,7 @@ class CodeMirrorModeMediaWikiConfig {
|
|||
|
||||
/**
|
||||
* These are custom tokens (a.k.a. tags) that aren't mapped to any of the standardized tags.
|
||||
* Make sure these are also defined in #customTags() above.
|
||||
* Make sure these are also defined in customTags() above.
|
||||
*
|
||||
* TODO: pass parent Tags in Tag.define() where appropriate for better theming.
|
||||
*
|
||||
|
@ -516,4 +519,6 @@ class CodeMirrorModeMediaWikiConfig {
|
|||
* @member CodeMirrorModeMediaWikiConfig
|
||||
* @type {CodeMirrorModeMediaWikiConfig}
|
||||
*/
|
||||
export const mwModeConfig = new CodeMirrorModeMediaWikiConfig();
|
||||
const mwModeConfig = new CodeMirrorModeMediaWikiConfig();
|
||||
|
||||
module.exports = mwModeConfig;
|
|
@ -1,5 +1,5 @@
|
|||
import CodeMirror from './codemirror';
|
||||
import mediaWikiLang from './codemirror.mode.mediawiki';
|
||||
const CodeMirror = require( 'ext.CodeMirror.v6' );
|
||||
const mediaWikiLang = require( 'ext.CodeMirror.v6.mode.mediawiki' );
|
||||
|
||||
const textarea = document.getElementById( 'wpTextbox1' );
|
||||
const cm = new CodeMirror( textarea );
|
|
@ -1,15 +1,15 @@
|
|||
import {
|
||||
const {
|
||||
HighlightStyle,
|
||||
LanguageSupport,
|
||||
StreamLanguage,
|
||||
StreamParser,
|
||||
StringStream,
|
||||
Tag,
|
||||
syntaxHighlighting
|
||||
} from '@codemirror/language';
|
||||
import { mwModeConfig as modeConfig } from './codemirror.mode.mediawiki.config';
|
||||
import { Tag } from '@lezer/highlight';
|
||||
import templateFoldingExtension from './codemirror.templateFolding';
|
||||
import bidiIsolationExtension from './codemirror.bidiIsolation';
|
||||
} = require( 'ext.CodeMirror.v6.lib' );
|
||||
const mwModeConfig = require( './codemirror.mediawiki.config.js' );
|
||||
const bidiIsolationExtension = require( './codemirror.mediawiki.bidiIsolation.js' );
|
||||
const templateFoldingExtension = require( './codemirror.mediawiki.templateFolding.js' );
|
||||
|
||||
/**
|
||||
* MediaWiki language support for CodeMirror 6.
|
||||
|
@ -47,11 +47,11 @@ class CodeMirrorModeMediaWiki {
|
|||
this.oldStyle = null;
|
||||
this.tokens = [];
|
||||
this.oldTokens = [];
|
||||
this.tokenTable = modeConfig.tokenTable;
|
||||
this.tokenTable = mwModeConfig.tokenTable;
|
||||
this.registerGroundTokens();
|
||||
|
||||
// Dynamically register any tags that aren't already in CodeMirrorModeMediaWikiConfig
|
||||
Object.keys( this.config.tags ).forEach( ( tag ) => modeConfig.addTag( tag ) );
|
||||
Object.keys( this.config.tags ).forEach( ( tag ) => mwModeConfig.addTag( tag ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -94,7 +94,7 @@ class CodeMirrorModeMediaWiki {
|
|||
'mw-template3-ext3-link-ground',
|
||||
'mw-template3-ground',
|
||||
'mw-template3-link-ground'
|
||||
].forEach( ( ground ) => modeConfig.addToken( ground ) );
|
||||
].forEach( ( ground ) => mwModeConfig.addToken( ground ) );
|
||||
}
|
||||
|
||||
eatHtmlEntity( stream, style ) {
|
||||
|
@ -109,7 +109,7 @@ class CodeMirrorModeMediaWiki {
|
|||
ok = stream.eatWhile( /[\w.\-:]/ ) && stream.eat( ';' );
|
||||
}
|
||||
if ( ok ) {
|
||||
return modeConfig.tags.htmlEntity;
|
||||
return mwModeConfig.tags.htmlEntity;
|
||||
}
|
||||
return style;
|
||||
}
|
||||
|
@ -120,10 +120,10 @@ class CodeMirrorModeMediaWiki {
|
|||
|
||||
makeStyle( style, state, endGround ) {
|
||||
if ( this.isBold || state.nDt > 0 ) {
|
||||
style += ' ' + modeConfig.tags.strong;
|
||||
style += ' ' + mwModeConfig.tags.strong;
|
||||
}
|
||||
if ( this.isItalic ) {
|
||||
style += ' ' + modeConfig.tags.em;
|
||||
style += ' ' + mwModeConfig.tags.em;
|
||||
}
|
||||
return this.makeLocalStyle( style, state, endGround );
|
||||
}
|
||||
|
@ -196,7 +196,7 @@ class CodeMirrorModeMediaWiki {
|
|||
if ( stream.eat( char ) ) {
|
||||
return this.makeLocalStyle( style, state );
|
||||
}
|
||||
return this.makeLocalStyle( modeConfig.tags.error, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.error, state );
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -205,89 +205,89 @@ class CodeMirrorModeMediaWiki {
|
|||
if ( stream.match( /^[^&<[{~]+/ ) ) {
|
||||
if ( stream.eol() ) {
|
||||
stream.backUp( count );
|
||||
state.tokenize = this.eatEnd( modeConfig.tags.sectionHeader );
|
||||
state.tokenize = this.eatEnd( mwModeConfig.tags.sectionHeader );
|
||||
} else if ( stream.match( /^<!--(?!.*?-->.*?=)/, false ) ) {
|
||||
// T171074: handle trailing comments
|
||||
stream.backUp( count );
|
||||
state.tokenize = this.eatBlock( modeConfig.tags.sectionHeader, '<!--', false );
|
||||
state.tokenize = this.eatBlock( mwModeConfig.tags.sectionHeader, '<!--', false );
|
||||
}
|
||||
return modeConfig.tags.section; // style is null
|
||||
return mwModeConfig.tags.section; // style is null
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.section )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.section )( stream, state );
|
||||
};
|
||||
}
|
||||
|
||||
inVariable( stream, state ) {
|
||||
if ( stream.match( /^[^{}|]+/ ) ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.templateVariableName, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateVariableName, state );
|
||||
}
|
||||
if ( stream.eat( '|' ) ) {
|
||||
state.tokenize = this.inVariableDefault.bind( this );
|
||||
return this.makeLocalStyle( modeConfig.tags.templateVariableDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateVariableDelimiter, state );
|
||||
}
|
||||
if ( stream.match( '}}}' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.templateVariableBracket, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateVariableBracket, state );
|
||||
}
|
||||
if ( stream.match( '{{{' ) ) {
|
||||
state.stack.push( state.tokenize );
|
||||
return this.makeLocalStyle( modeConfig.tags.templateVariableBracket, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateVariableBracket, state );
|
||||
}
|
||||
stream.next();
|
||||
return this.makeLocalStyle( modeConfig.tags.templateVariableName, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateVariableName, state );
|
||||
}
|
||||
|
||||
inVariableDefault( stream, state ) {
|
||||
if ( stream.match( /^[^{}[<&~]+/ ) ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.templateVariable, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateVariable, state );
|
||||
}
|
||||
if ( stream.match( '}}}' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.templateVariableBracket, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateVariableBracket, state );
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.templateVariable )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.templateVariable )( stream, state );
|
||||
}
|
||||
|
||||
inParserFunctionName( stream, state ) {
|
||||
// FIXME: {{#name}} and {{uc}} are wrong, must have ':'
|
||||
if ( stream.match( /^#?[^:}{~]+/ ) ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.parserFunctionName, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.parserFunctionName, state );
|
||||
}
|
||||
if ( stream.eat( ':' ) ) {
|
||||
state.tokenize = this.inParserFunctionArguments.bind( this );
|
||||
return this.makeLocalStyle( modeConfig.tags.parserFunctionDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.parserFunctionDelimiter, state );
|
||||
}
|
||||
if ( stream.match( '}}' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.parserFunctionBracket, state, 'nExt' );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.parserFunctionBracket, state, 'nExt' );
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.parserFunction )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.parserFunction )( stream, state );
|
||||
}
|
||||
|
||||
inParserFunctionArguments( stream, state ) {
|
||||
if ( stream.match( /^[^|}{[<&~]+/ ) ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.parserFunction, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.parserFunction, state );
|
||||
} else if ( stream.eat( '|' ) ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.parserFunctionDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.parserFunctionDelimiter, state );
|
||||
} else if ( stream.match( '}}' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.parserFunctionBracket, state, 'nExt' );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.parserFunctionBracket, state, 'nExt' );
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.parserFunction )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.parserFunction )( stream, state );
|
||||
}
|
||||
|
||||
eatTemplatePageName( haveAte ) {
|
||||
return ( stream, state ) => {
|
||||
if ( stream.match( /^[\s\u00a0]*\|[\s\u00a0]*/ ) ) {
|
||||
state.tokenize = this.eatTemplateArgument( true );
|
||||
return this.makeLocalStyle( modeConfig.tags.templateDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateDelimiter, state );
|
||||
}
|
||||
if ( stream.match( /^[\s\u00a0]*\}\}/ ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.templateBracket, state, 'nTemplate' );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateBracket, state, 'nTemplate' );
|
||||
}
|
||||
if ( stream.match( /^[\s\u00a0]*<!--.*?-->/ ) ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.comment, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.comment, state );
|
||||
}
|
||||
if ( haveAte && stream.sol() ) {
|
||||
// @todo error message
|
||||
|
@ -297,14 +297,14 @@ class CodeMirrorModeMediaWiki {
|
|||
}
|
||||
if ( stream.match( /^[\s\u00a0]*[^\s\u00a0|}<{&~]+/ ) ) {
|
||||
state.tokenize = this.eatTemplatePageName( true );
|
||||
return this.makeLocalStyle( modeConfig.tags.templateName, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateName, state );
|
||||
} else if ( stream.eatSpace() ) {
|
||||
if ( stream.eol() === true ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.templateName, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateName, state );
|
||||
}
|
||||
return this.makeLocalStyle( modeConfig.tags.templateName, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateName, state );
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.templateName )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.templateName )( stream, state );
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -313,19 +313,19 @@ class CodeMirrorModeMediaWiki {
|
|||
if ( expectArgName && stream.eatWhile( /[^=|}{[<&~]/ ) ) {
|
||||
if ( stream.eat( '=' ) ) {
|
||||
state.tokenize = this.eatTemplateArgument( false );
|
||||
return this.makeLocalStyle( modeConfig.tags.templateArgumentName, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateArgumentName, state );
|
||||
}
|
||||
return this.makeLocalStyle( modeConfig.tags.template, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.template, state );
|
||||
} else if ( stream.eatWhile( /[^|}{[<&~]/ ) ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.template, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.template, state );
|
||||
} else if ( stream.eat( '|' ) ) {
|
||||
state.tokenize = this.eatTemplateArgument( true );
|
||||
return this.makeLocalStyle( modeConfig.tags.templateDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateDelimiter, state );
|
||||
} else if ( stream.match( '}}' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.templateBracket, state, 'nTemplate' );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateBracket, state, 'nTemplate' );
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.template )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.template )( stream, state );
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -342,7 +342,7 @@ class CodeMirrorModeMediaWiki {
|
|||
} else {
|
||||
state.tokenize = this.inExternalLink.bind( this );
|
||||
}
|
||||
return this.makeLocalStyle( modeConfig.tags.extLinkProtocol, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.extLinkProtocol, state );
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -355,7 +355,7 @@ class CodeMirrorModeMediaWiki {
|
|||
}
|
||||
if ( stream.match( /^[\s\u00a0]*\]/ ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.extLinkBracket, state, 'nLink' );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.extLinkBracket, state, 'nLink' );
|
||||
}
|
||||
if ( stream.eatSpace() ) {
|
||||
state.tokenize = this.inExternalLinkText.bind( this );
|
||||
|
@ -369,9 +369,9 @@ class CodeMirrorModeMediaWiki {
|
|||
stream.next();
|
||||
}
|
||||
}
|
||||
return this.makeStyle( modeConfig.tags.extLink, state );
|
||||
return this.makeStyle( mwModeConfig.tags.extLink, state );
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.extLink )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.extLink )( stream, state );
|
||||
}
|
||||
|
||||
inExternalLinkText( stream, state ) {
|
||||
|
@ -383,12 +383,12 @@ class CodeMirrorModeMediaWiki {
|
|||
}
|
||||
if ( stream.eat( ']' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.extLinkBracket, state, 'nLink' );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.extLinkBracket, state, 'nLink' );
|
||||
}
|
||||
if ( stream.match( /^[^'\]{&~<]+/ ) ) {
|
||||
return this.makeStyle( modeConfig.tags.extLinkText, state );
|
||||
return this.makeStyle( mwModeConfig.tags.extLinkText, state );
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.extLinkText )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.extLinkText )( stream, state );
|
||||
}
|
||||
|
||||
inLink( stream, state ) {
|
||||
|
@ -400,24 +400,24 @@ class CodeMirrorModeMediaWiki {
|
|||
}
|
||||
if ( stream.match( /^[\s\u00a0]*#[\s\u00a0]*/ ) ) {
|
||||
state.tokenize = this.inLinkToSection.bind( this );
|
||||
return this.makeLocalStyle( modeConfig.tags.link, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.link, state );
|
||||
}
|
||||
if ( stream.match( /^[\s\u00a0]*\|[\s\u00a0]*/ ) ) {
|
||||
state.tokenize = this.eatLinkText();
|
||||
return this.makeLocalStyle( modeConfig.tags.linkDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.linkDelimiter, state );
|
||||
}
|
||||
if ( stream.match( /^[\s\u00a0]*\]\]/ ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.linkBracket, state, 'nLink' );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.linkBracket, state, 'nLink' );
|
||||
}
|
||||
if ( stream.match( /^[\s\u00a0]*[^\s\u00a0#|\]&~{]+/ ) || stream.eatSpace() ) {
|
||||
return this.makeStyle(
|
||||
`${ modeConfig.tags.linkPageName } ${ modeConfig.tags.pageName }`,
|
||||
`${ mwModeConfig.tags.linkPageName } ${ mwModeConfig.tags.pageName }`,
|
||||
state
|
||||
);
|
||||
}
|
||||
return this.eatWikiText(
|
||||
`${ modeConfig.tags.linkPageName } ${ modeConfig.tags.pageName }`
|
||||
`${ mwModeConfig.tags.linkPageName } ${ mwModeConfig.tags.pageName }`
|
||||
)( stream, state );
|
||||
}
|
||||
|
||||
|
@ -430,17 +430,17 @@ class CodeMirrorModeMediaWiki {
|
|||
}
|
||||
// FIXME '{{' breaks links, example: [[z{{page]]
|
||||
if ( stream.match( /^[^|\]&~{}]+/ ) ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.linkToSection, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.linkToSection, state );
|
||||
}
|
||||
if ( stream.eat( '|' ) ) {
|
||||
state.tokenize = this.eatLinkText();
|
||||
return this.makeLocalStyle( modeConfig.tags.linkDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.linkDelimiter, state );
|
||||
}
|
||||
if ( stream.match( ']]' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.linkBracket, state, 'nLink' );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.linkBracket, state, 'nLink' );
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.linkToSection )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.linkToSection )( stream, state );
|
||||
}
|
||||
|
||||
eatLinkText() {
|
||||
|
@ -449,28 +449,28 @@ class CodeMirrorModeMediaWiki {
|
|||
let tmpstyle;
|
||||
if ( stream.match( ']]' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.linkBracket, state, 'nLink' );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.linkBracket, state, 'nLink' );
|
||||
}
|
||||
if ( stream.match( '\'\'\'' ) ) {
|
||||
linkIsBold = !linkIsBold;
|
||||
return this.makeLocalStyle(
|
||||
`${ modeConfig.tags.linkText } ${ modeConfig.tags.apostrophes }`,
|
||||
`${ mwModeConfig.tags.linkText } ${ mwModeConfig.tags.apostrophes }`,
|
||||
state
|
||||
);
|
||||
}
|
||||
if ( stream.match( '\'\'' ) ) {
|
||||
linkIsItalic = !linkIsItalic;
|
||||
return this.makeLocalStyle(
|
||||
`${ modeConfig.tags.linkText } ${ modeConfig.tags.apostrophes }`,
|
||||
`${ mwModeConfig.tags.linkText } ${ mwModeConfig.tags.apostrophes }`,
|
||||
state
|
||||
);
|
||||
}
|
||||
tmpstyle = modeConfig.tags.linkText;
|
||||
tmpstyle = mwModeConfig.tags.linkText;
|
||||
if ( linkIsBold ) {
|
||||
tmpstyle += ' ' + modeConfig.tags.strong;
|
||||
tmpstyle += ' ' + mwModeConfig.tags.strong;
|
||||
}
|
||||
if ( linkIsItalic ) {
|
||||
tmpstyle += ' ' + modeConfig.tags.em;
|
||||
tmpstyle += ' ' + mwModeConfig.tags.em;
|
||||
}
|
||||
if ( stream.match( /^[^'\]{&~<]+/ ) ) {
|
||||
return this.makeStyle( tmpstyle, state );
|
||||
|
@ -490,23 +490,23 @@ class CodeMirrorModeMediaWiki {
|
|||
name = name.toLowerCase();
|
||||
|
||||
if ( isHtmlTag ) {
|
||||
if ( isCloseTag && !modeConfig.implicitlyClosedHtmlTags[ name ] ) {
|
||||
state.tokenize = this.eatChar( '>', modeConfig.tags.htmlTagBracket );
|
||||
if ( isCloseTag && !mwModeConfig.implicitlyClosedHtmlTags[ name ] ) {
|
||||
state.tokenize = this.eatChar( '>', mwModeConfig.tags.htmlTagBracket );
|
||||
} else {
|
||||
state.tokenize = this.eatHtmlTagAttribute( name );
|
||||
}
|
||||
return this.makeLocalStyle( modeConfig.tags.htmlTagName, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.htmlTagName, state );
|
||||
}
|
||||
// it is the extension tag
|
||||
if ( isCloseTag ) {
|
||||
state.tokenize = this.eatChar(
|
||||
'>',
|
||||
`${ modeConfig.tags.extTagBracket } mw-ext-${ name }`
|
||||
`${ mwModeConfig.tags.extTagBracket } mw-ext-${ name }`
|
||||
);
|
||||
} else {
|
||||
state.tokenize = this.eatExtTagAttribute( name );
|
||||
}
|
||||
return this.makeLocalStyle( `${ modeConfig.tags.extTagName } mw-ext-${ name }`, state );
|
||||
return this.makeLocalStyle( `${ mwModeConfig.tags.extTagName } mw-ext-${ name }`, state );
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -514,20 +514,20 @@ class CodeMirrorModeMediaWiki {
|
|||
return ( stream, state ) => {
|
||||
|
||||
if ( stream.match( /^(?:"[^<">]*"|'[^<'>]*'|[^>/<{&~])+/ ) ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.htmlTagAttribute, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.htmlTagAttribute, state );
|
||||
}
|
||||
if ( stream.eat( '>' ) ) {
|
||||
if ( !( name in modeConfig.implicitlyClosedHtmlTags ) ) {
|
||||
if ( !( name in mwModeConfig.implicitlyClosedHtmlTags ) ) {
|
||||
state.inHtmlTag.push( name );
|
||||
}
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.htmlTagBracket, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.htmlTagBracket, state );
|
||||
}
|
||||
if ( stream.match( '/>' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.htmlTagBracket, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.htmlTagBracket, state );
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.htmlTagAttribute )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.htmlTagAttribute )( stream, state );
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -546,7 +546,7 @@ class CodeMirrorModeMediaWiki {
|
|||
return ( stream, state ) => {
|
||||
|
||||
if ( stream.match( /^(?:"[^">]*"|'[^'>]*'|[^>/<{&~])+/ ) ) {
|
||||
return this.makeLocalStyle( `${ modeConfig.tags.extTagAttribute } mw-ext-${ name }`, state );
|
||||
return this.makeLocalStyle( `${ mwModeConfig.tags.extTagAttribute } mw-ext-${ name }`, state );
|
||||
}
|
||||
if ( stream.eat( '>' ) ) {
|
||||
state.extName = name;
|
||||
|
@ -570,13 +570,13 @@ class CodeMirrorModeMediaWiki {
|
|||
}
|
||||
|
||||
state.tokenize = this.eatExtTagArea( name );
|
||||
return this.makeLocalStyle( `${ modeConfig.tags.extTagBracket } mw-ext-${ name }`, state );
|
||||
return this.makeLocalStyle( `${ mwModeConfig.tags.extTagBracket } mw-ext-${ name }`, state );
|
||||
}
|
||||
if ( stream.match( '/>' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( `${ modeConfig.tags.extTagBracket } mw-ext-${ name }`, state );
|
||||
return this.makeLocalStyle( `${ mwModeConfig.tags.extTagBracket } mw-ext-${ name }`, state );
|
||||
}
|
||||
return this.eatWikiText( `${ modeConfig.tags.extTagAttribute } mw-ext-${ name }` )( stream, state );
|
||||
return this.eatWikiText( `${ mwModeConfig.tags.extTagAttribute } mw-ext-${ name }` )( stream, state );
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -615,7 +615,7 @@ class CodeMirrorModeMediaWiki {
|
|||
stream.next(); // eat <
|
||||
stream.next(); // eat /
|
||||
state.tokenize = this.eatTagName( name.length, true, false );
|
||||
return this.makeLocalStyle( `${ modeConfig.tags.extTagBracket } mw-ext-${ name }`, state );
|
||||
return this.makeLocalStyle( `${ mwModeConfig.tags.extTagBracket } mw-ext-${ name }`, state );
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -623,7 +623,7 @@ class CodeMirrorModeMediaWiki {
|
|||
return ( stream, state ) => {
|
||||
let ret;
|
||||
if ( state.extMode === false ) {
|
||||
ret = modeConfig.tags.extTag;
|
||||
ret = mwModeConfig.tags.extTag;
|
||||
stream.skipToEnd();
|
||||
} else {
|
||||
ret = `mw-tag-${ state.extName } ` +
|
||||
|
@ -643,7 +643,7 @@ class CodeMirrorModeMediaWiki {
|
|||
stream.match( '{|' );
|
||||
stream.eatSpace();
|
||||
state.tokenize = this.inTableDefinition.bind( this );
|
||||
return modeConfig.tags.tableBracket;
|
||||
return mwModeConfig.tags.tableBracket;
|
||||
}
|
||||
|
||||
inTableDefinition( stream, state ) {
|
||||
|
@ -651,7 +651,7 @@ class CodeMirrorModeMediaWiki {
|
|||
state.tokenize = this.inTable.bind( this );
|
||||
return this.inTable( stream, state );
|
||||
}
|
||||
return this.eatWikiText( modeConfig.tags.tableDefinition )( stream, state );
|
||||
return this.eatWikiText( mwModeConfig.tags.tableDefinition )( stream, state );
|
||||
}
|
||||
|
||||
inTable( stream, state ) {
|
||||
|
@ -661,25 +661,25 @@ class CodeMirrorModeMediaWiki {
|
|||
if ( stream.eat( '-' ) ) {
|
||||
stream.eatSpace();
|
||||
state.tokenize = this.inTableDefinition.bind( this );
|
||||
return this.makeLocalStyle( modeConfig.tags.tableDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.tableDelimiter, state );
|
||||
}
|
||||
if ( stream.eat( '+' ) ) {
|
||||
stream.eatSpace();
|
||||
state.tokenize = this.eatTableRow( true, false, true );
|
||||
return this.makeLocalStyle( modeConfig.tags.tableDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.tableDelimiter, state );
|
||||
}
|
||||
if ( stream.eat( '}' ) ) {
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.tableBracket, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.tableBracket, state );
|
||||
}
|
||||
stream.eatSpace();
|
||||
state.tokenize = this.eatTableRow( true, false );
|
||||
return this.makeLocalStyle( modeConfig.tags.tableDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.tableDelimiter, state );
|
||||
}
|
||||
if ( stream.eat( '!' ) ) {
|
||||
stream.eatSpace();
|
||||
state.tokenize = this.eatTableRow( true, true );
|
||||
return this.makeLocalStyle( modeConfig.tags.tableDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.tableDelimiter, state );
|
||||
}
|
||||
}
|
||||
return this.eatWikiText( '' )( stream, state );
|
||||
|
@ -689,9 +689,9 @@ class CodeMirrorModeMediaWiki {
|
|||
eatTableRow( isStart, isHead, isCaption ) {
|
||||
let tag = '';
|
||||
if ( isCaption ) {
|
||||
tag = modeConfig.tags.tableCaption;
|
||||
tag = mwModeConfig.tags.tableCaption;
|
||||
} else if ( isHead ) {
|
||||
tag = modeConfig.tags.strong;
|
||||
tag = mwModeConfig.tags.strong;
|
||||
}
|
||||
return ( stream, state ) => {
|
||||
if ( stream.sol() ) {
|
||||
|
@ -707,11 +707,11 @@ class CodeMirrorModeMediaWiki {
|
|||
this.isBold = false;
|
||||
this.isItalic = false;
|
||||
state.tokenize = this.eatTableRow( true, isHead, isCaption );
|
||||
return this.makeLocalStyle( modeConfig.tags.tableDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.tableDelimiter, state );
|
||||
}
|
||||
if ( isStart && stream.eat( '|' ) ) {
|
||||
state.tokenize = this.eatTableRow( false, isHead, isCaption );
|
||||
return this.makeLocalStyle( modeConfig.tags.tableDelimiter, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.tableDelimiter, state );
|
||||
}
|
||||
}
|
||||
return this.eatWikiText( tag )( stream, state );
|
||||
|
@ -721,7 +721,7 @@ class CodeMirrorModeMediaWiki {
|
|||
eatFreeExternalLinkProtocol( stream, state ) {
|
||||
stream.match( this.urlProtocols );
|
||||
state.tokenize = this.eatFreeExternalLink.bind( this );
|
||||
return this.makeLocalStyle( modeConfig.tags.freeExtLinkProtocol, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.freeExtLinkProtocol, state );
|
||||
}
|
||||
|
||||
eatFreeExternalLink( stream, state ) {
|
||||
|
@ -731,24 +731,24 @@ class CodeMirrorModeMediaWiki {
|
|||
if ( stream.peek() === '~' ) {
|
||||
if ( !stream.match( /^~~~+/, false ) ) {
|
||||
stream.match( /^~*/ );
|
||||
return this.makeLocalStyle( modeConfig.tags.freeExtLink, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.freeExtLink, state );
|
||||
}
|
||||
} else if ( stream.peek() === '{' ) {
|
||||
if ( !stream.match( '{{', false ) ) {
|
||||
stream.next();
|
||||
return this.makeLocalStyle( modeConfig.tags.freeExtLink, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.freeExtLink, state );
|
||||
}
|
||||
} else if ( stream.peek() === '\'' ) {
|
||||
if ( !stream.match( '\'\'', false ) ) {
|
||||
stream.next();
|
||||
return this.makeLocalStyle( modeConfig.tags.freeExtLink, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.freeExtLink, state );
|
||||
}
|
||||
} else if ( stream.match( /^[).,]+(?=[^\s\u00a0{[\]<>~).,])/ ) ) {
|
||||
return this.makeLocalStyle( modeConfig.tags.freeExtLink, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.freeExtLink, state );
|
||||
}
|
||||
}
|
||||
state.tokenize = state.stack.pop();
|
||||
return this.makeLocalStyle( modeConfig.tags.freeExtLink, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.freeExtLink, state );
|
||||
}
|
||||
|
||||
eatList( stream, state ) {
|
||||
|
@ -757,7 +757,7 @@ class CodeMirrorModeMediaWiki {
|
|||
if ( mt && !this.isNested( state ) && mt[ 0 ].includes( ';' ) ) {
|
||||
state.nDt += mt[ 0 ].split( ';' ).length - 1;
|
||||
}
|
||||
return this.makeLocalStyle( modeConfig.tags.list, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.list, state );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -781,13 +781,13 @@ class CodeMirrorModeMediaWiki {
|
|||
if ( !stream.match( '//', false ) && stream.match( this.urlProtocols ) ) {
|
||||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.eatFreeExternalLink.bind( this );
|
||||
return this.makeLocalStyle( modeConfig.tags.freeExtLinkProtocol, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.freeExtLinkProtocol, state );
|
||||
}
|
||||
ch = stream.next();
|
||||
switch ( ch ) {
|
||||
case '-':
|
||||
if ( stream.match( /^---+/ ) ) {
|
||||
return modeConfig.tags.hr;
|
||||
return mwModeConfig.tags.hr;
|
||||
}
|
||||
break;
|
||||
case '=':
|
||||
|
@ -798,7 +798,7 @@ class CodeMirrorModeMediaWiki {
|
|||
stream.backUp( tmp[ 2 ].length );
|
||||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.eatSectionHeader( tmp[ 3 ].length );
|
||||
return modeConfig.tags.sectionHeader + ' ' +
|
||||
return mwModeConfig.tags.sectionHeader + ' ' +
|
||||
/**
|
||||
* Tokens used here include:
|
||||
* - cm-mw-section-1
|
||||
|
@ -808,7 +808,7 @@ class CodeMirrorModeMediaWiki {
|
|||
* - cm-mw-section-5
|
||||
* - cm-mw-section-6
|
||||
*/
|
||||
modeConfig.tags[ `sectionHeader${ tmp[ 1 ].length + 1 }` ];
|
||||
mwModeConfig.tags[ `sectionHeader${ tmp[ 1 ].length + 1 }` ];
|
||||
}
|
||||
break;
|
||||
case ';':
|
||||
|
@ -831,11 +831,11 @@ class CodeMirrorModeMediaWiki {
|
|||
if ( stream.match( /^:+/ ) ) { // ::{|
|
||||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.eatStartTable.bind( this );
|
||||
return modeConfig.tags.indenting;
|
||||
return mwModeConfig.tags.indenting;
|
||||
}
|
||||
stream.eat( '{' );
|
||||
} else {
|
||||
return modeConfig.tags.skipFormatting;
|
||||
return mwModeConfig.tags.skipFormatting;
|
||||
}
|
||||
// break is not necessary here
|
||||
// falls through
|
||||
|
@ -844,7 +844,7 @@ class CodeMirrorModeMediaWiki {
|
|||
stream.eatSpace();
|
||||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.inTableDefinition.bind( this );
|
||||
return modeConfig.tags.tableBracket;
|
||||
return mwModeConfig.tags.tableBracket;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -867,10 +867,10 @@ class CodeMirrorModeMediaWiki {
|
|||
this.prepareItalicForCorrection( stream );
|
||||
}
|
||||
this.isBold = !this.isBold;
|
||||
return this.makeLocalStyle( modeConfig.tags.apostrophesBold, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.apostrophesBold, state );
|
||||
} else if ( stream.eat( '\'' ) ) { // italic
|
||||
this.isItalic = !this.isItalic;
|
||||
return this.makeLocalStyle( modeConfig.tags.apostrophesItalic, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.apostrophesItalic, state );
|
||||
}
|
||||
break;
|
||||
case '[':
|
||||
|
@ -880,7 +880,7 @@ class CodeMirrorModeMediaWiki {
|
|||
state.nLink++;
|
||||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.inLink.bind( this );
|
||||
return this.makeLocalStyle( modeConfig.tags.linkBracket, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.linkBracket, state );
|
||||
}
|
||||
} else {
|
||||
mt = stream.match( this.urlProtocols );
|
||||
|
@ -889,7 +889,7 @@ class CodeMirrorModeMediaWiki {
|
|||
stream.backUp( mt[ 0 ].length );
|
||||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.eatExternalLinkProtocol( mt[ 0 ].length );
|
||||
return this.makeLocalStyle( modeConfig.tags.extLinkBracket, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.extLinkBracket, state );
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -901,7 +901,7 @@ class CodeMirrorModeMediaWiki {
|
|||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.inVariable.bind( this );
|
||||
return this.makeLocalStyle(
|
||||
modeConfig.tags.templateVariableBracket,
|
||||
mwModeConfig.tags.templateVariableBracket,
|
||||
state
|
||||
);
|
||||
} else if ( stream.match( /^{(?!{(?!{))[\s\u00a0]*/ ) ) {
|
||||
|
@ -911,7 +911,7 @@ class CodeMirrorModeMediaWiki {
|
|||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.inParserFunctionName.bind( this );
|
||||
return this.makeLocalStyle(
|
||||
modeConfig.tags.parserFunctionBracket,
|
||||
mwModeConfig.tags.parserFunctionBracket,
|
||||
state
|
||||
);
|
||||
}
|
||||
|
@ -931,7 +931,7 @@ class CodeMirrorModeMediaWiki {
|
|||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.inParserFunctionName.bind( this );
|
||||
return this.makeLocalStyle(
|
||||
modeConfig.tags.parserFunctionBracket,
|
||||
mwModeConfig.tags.parserFunctionBracket,
|
||||
state
|
||||
);
|
||||
}
|
||||
|
@ -940,39 +940,39 @@ class CodeMirrorModeMediaWiki {
|
|||
state.nTemplate++;
|
||||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.eatTemplatePageName( false );
|
||||
return this.makeLocalStyle( modeConfig.tags.templateBracket, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.templateBracket, state );
|
||||
}
|
||||
break;
|
||||
case '<':
|
||||
isCloseTag = !!stream.eat( '/' );
|
||||
tagname = stream.match( /^[^>/\s\u00a0.*,[\]{}$^+?|/\\'`~<=!@#%&()-]+/ );
|
||||
if ( stream.match( '!--' ) ) { // comment
|
||||
return chain( this.eatBlock( modeConfig.tags.comment, '-->' ) );
|
||||
return chain( this.eatBlock( mwModeConfig.tags.comment, '-->' ) );
|
||||
}
|
||||
if ( tagname ) {
|
||||
tagname = tagname[ 0 ].toLowerCase();
|
||||
if ( tagname in this.config.tags ) {
|
||||
// Parser function
|
||||
if ( isCloseTag === true ) {
|
||||
return modeConfig.tags.error;
|
||||
return mwModeConfig.tags.error;
|
||||
}
|
||||
stream.backUp( tagname.length );
|
||||
state.stack.push( state.tokenize );
|
||||
state.tokenize = this.eatTagName( tagname.length, isCloseTag, false );
|
||||
return this.makeLocalStyle( `${ modeConfig.tags.extTagBracket } mw-ext-${ tagname }`, state );
|
||||
return this.makeLocalStyle( `${ mwModeConfig.tags.extTagBracket } mw-ext-${ tagname }`, state );
|
||||
}
|
||||
if ( tagname in modeConfig.permittedHtmlTags ) {
|
||||
if ( tagname in mwModeConfig.permittedHtmlTags ) {
|
||||
// Html tag
|
||||
if ( isCloseTag === true && tagname !== state.inHtmlTag.pop() ) {
|
||||
// Increment position so that the closing '>' gets highlighted red.
|
||||
stream.pos++;
|
||||
return modeConfig.tags.error;
|
||||
return mwModeConfig.tags.error;
|
||||
}
|
||||
if (
|
||||
isCloseTag === true &&
|
||||
tagname in modeConfig.implicitlyClosedHtmlTags
|
||||
tagname in mwModeConfig.implicitlyClosedHtmlTags
|
||||
) {
|
||||
return modeConfig.tags.error;
|
||||
return mwModeConfig.tags.error;
|
||||
}
|
||||
stream.backUp( tagname.length );
|
||||
state.stack.push( state.tokenize );
|
||||
|
@ -980,17 +980,17 @@ class CodeMirrorModeMediaWiki {
|
|||
tagname.length,
|
||||
// Opening void tags should also be treated as the closing tag.
|
||||
isCloseTag ||
|
||||
( tagname in modeConfig.implicitlyClosedHtmlTags ),
|
||||
( tagname in mwModeConfig.implicitlyClosedHtmlTags ),
|
||||
true
|
||||
);
|
||||
return this.makeLocalStyle( modeConfig.tags.htmlTagBracket, state );
|
||||
return this.makeLocalStyle( mwModeConfig.tags.htmlTagBracket, state );
|
||||
}
|
||||
stream.backUp( tagname.length );
|
||||
}
|
||||
break;
|
||||
case '~':
|
||||
if ( stream.match( /^~{2,4}/ ) ) {
|
||||
return modeConfig.tags.signature;
|
||||
return mwModeConfig.tags.signature;
|
||||
}
|
||||
break;
|
||||
// Maybe double underscored Magic Word such as __TOC__
|
||||
|
@ -1017,7 +1017,7 @@ class CodeMirrorModeMediaWiki {
|
|||
'__' + name[ 0 ].toLowerCase() in this.config.doubleUnderscore[ 0 ] ||
|
||||
'__' + name[ 0 ] in this.config.doubleUnderscore[ 1 ]
|
||||
) {
|
||||
return modeConfig.tags.doubleUnderscore;
|
||||
return mwModeConfig.tags.doubleUnderscore;
|
||||
}
|
||||
if ( !stream.eol() ) {
|
||||
// Two underscore symbols at the end can be the
|
||||
|
@ -1032,7 +1032,7 @@ class CodeMirrorModeMediaWiki {
|
|||
case ':':
|
||||
if ( state.nDt > 0 && !this.isNested( state ) ) {
|
||||
state.nDt--;
|
||||
return modeConfig.tags.indenting;
|
||||
return mwModeConfig.tags.indenting;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
@ -1266,14 +1266,14 @@ class CodeMirrorModeMediaWiki {
|
|||
* @return {LanguageSupport}
|
||||
* @stable to call
|
||||
*/
|
||||
export default ( config = { bidiIsolation: false }, mwConfig = null ) => {
|
||||
const mediaWikiLang = ( config = { bidiIsolation: false }, mwConfig = null ) => {
|
||||
mwConfig = mwConfig || mw.config.get( 'extCodeMirrorConfig' );
|
||||
const mode = new CodeMirrorModeMediaWiki( mwConfig );
|
||||
const parser = mode.mediawiki;
|
||||
const lang = StreamLanguage.define( parser );
|
||||
const langExtension = [ syntaxHighlighting(
|
||||
HighlightStyle.define(
|
||||
modeConfig.getTagStyles( parser )
|
||||
mwModeConfig.getTagStyles( parser )
|
||||
)
|
||||
) ];
|
||||
|
||||
|
@ -1292,3 +1292,5 @@ export default ( config = { bidiIsolation: false }, mwConfig = null ) => {
|
|||
|
||||
return new LanguageSupport( lang, langExtension );
|
||||
};
|
||||
|
||||
module.exports = mediaWikiLang;
|
|
@ -1,8 +1,22 @@
|
|||
import { showTooltip, keymap, Tooltip, KeyBinding } from '@codemirror/view';
|
||||
import { StateField, Extension, EditorState } from '@codemirror/state';
|
||||
import { foldEffect, syntaxTree, ensureSyntaxTree, foldedRanges, unfoldAll, unfoldEffect, codeFolding } from '@codemirror/language';
|
||||
import { SyntaxNode, Tree } from '@lezer/common';
|
||||
import { mwModeConfig as modeConfig } from './codemirror.mode.mediawiki.config';
|
||||
const {
|
||||
EditorState,
|
||||
Extension,
|
||||
KeyBinding,
|
||||
StateField,
|
||||
SyntaxNode,
|
||||
Tree,
|
||||
Tooltip,
|
||||
codeFolding,
|
||||
ensureSyntaxTree,
|
||||
foldEffect,
|
||||
foldedRanges,
|
||||
keymap,
|
||||
showTooltip,
|
||||
syntaxTree,
|
||||
unfoldAll,
|
||||
unfoldEffect
|
||||
} = require( 'ext.CodeMirror.v6.lib' );
|
||||
const modeConfig = require( './codemirror.mediawiki.config.js' );
|
||||
|
||||
/**
|
||||
* Check if a SyntaxNode is a template bracket (`{{` or `}}`)
|
||||
|
@ -280,7 +294,7 @@ const foldKeymap = [
|
|||
* @module CodeMirrorTemplateFolding
|
||||
* @type {Extension}
|
||||
*/
|
||||
export default [
|
||||
const templateFoldingExtension = [
|
||||
codeFolding( {
|
||||
placeholderDOM( view ) {
|
||||
const element = document.createElement( 'span' );
|
||||
|
@ -314,3 +328,5 @@ export default [
|
|||
} ),
|
||||
keymap.of( foldKeymap )
|
||||
];
|
||||
|
||||
module.exports = templateFoldingExtension;
|
|
@ -1,5 +1,4 @@
|
|||
import { EditorView } from '@codemirror/view';
|
||||
import { EditorSelection } from '@codemirror/state';
|
||||
const { EditorSelection, EditorView } = require( 'ext.CodeMirror.v6.lib' );
|
||||
|
||||
/**
|
||||
* [jQuery.textSelection]{@link jQuery.fn.textSelection} implementation for CodeMirror.
|
||||
|
@ -230,4 +229,4 @@ class CodeMirrorTextSelection {
|
|||
}
|
||||
}
|
||||
|
||||
export default CodeMirrorTextSelection;
|
||||
module.exports = CodeMirrorTextSelection;
|
|
@ -1,7 +1,10 @@
|
|||
import CodeMirror from './codemirror';
|
||||
import { EditorSelection, Extension } from '@codemirror/state';
|
||||
import { EditorView } from '@codemirror/view';
|
||||
import { LanguageSupport } from '@codemirror/language';
|
||||
const {
|
||||
EditorSelection,
|
||||
EditorView,
|
||||
Extension,
|
||||
LanguageSupport
|
||||
} = require( 'ext.CodeMirror.v6.lib' );
|
||||
const CodeMirror = require( 'ext.CodeMirror.v6' );
|
||||
|
||||
/**
|
||||
* CodeMirror integration with
|
||||
|
@ -242,4 +245,4 @@ class CodeMirrorWikiEditor extends CodeMirror {
|
|||
}
|
||||
}
|
||||
|
||||
export default CodeMirrorWikiEditor;
|
||||
module.exports = CodeMirrorWikiEditor;
|
|
@ -1,5 +1,5 @@
|
|||
import CodeMirrorWikiEditor from './codemirror.wikieditor';
|
||||
import mediaWikiLang from './codemirror.mode.mediawiki';
|
||||
const CodeMirrorWikiEditor = require( 'ext.CodeMirror.v6.WikiEditor' );
|
||||
const mediaWikiLang = require( 'ext.CodeMirror.v6.mode.mediawiki' );
|
||||
|
||||
// TODO: remove URL feature flag once bidi isolation is more stable.
|
||||
const urlParams = new URLSearchParams( window.location.search );
|
1
resources/dist/codemirror.js
vendored
1
resources/dist/codemirror.js
vendored
File diff suppressed because one or more lines are too long
1
resources/dist/codemirror.mediawiki.js
vendored
1
resources/dist/codemirror.mediawiki.js
vendored
|
@ -1 +0,0 @@
|
|||
"use strict";var e=require("ext.CodeMirror.v6"),i=require("ext.CodeMirror.v6.mode.mediawiki");require("ext.CodeMirror.v6.lib");var r=new e(document.getElementById("wpTextbox1")),o=new URLSearchParams(window.location.search);r.initialize([r.defaultExtensions,i({bidiIsolation:o.get("cm6bidi")})]);
|
1
resources/dist/codemirror.mode.mediawiki.js
vendored
1
resources/dist/codemirror.mode.mediawiki.js
vendored
File diff suppressed because one or more lines are too long
1
resources/dist/codemirror.wikieditor.js
vendored
1
resources/dist/codemirror.wikieditor.js
vendored
|
@ -1 +0,0 @@
|
|||
"use strict";var e=require("ext.CodeMirror.v6.lib"),t=function(t){function r(t,i){var o;return e._classCallCheck(this,r),(o=e._callSuper(this,r,[t])).langExtension=i,o.useCodeMirror=mw.user.options.get("usecodemirror")>0,o.realtimePreviewHandler=null,o}return e._inherits(r,t),e._createClass(r,[{key:"setCodeMirrorPreference",value:function(t){this.useCodeMirror=t,e._get(e._getPrototypeOf(r.prototype),"setCodeMirrorPreference",this).call(this,t)}},{key:"enableCodeMirror",value:function(){var t=this;if(!this.view){var r=this.$textarea.prop("selectionStart"),i=this.$textarea.prop("selectionEnd"),o=this.$textarea.scrollTop(),a=this.$textarea.is(":focus"),s=[this.defaultExtensions,this.langExtension,e.EditorView.updateListener.of((function(e){e.docChanged&&"function"==typeof t.realtimePreviewHandler&&t.realtimePreviewHandler()}))];if(this.initialize(s),this.addRealtimePreviewHandler(),requestAnimationFrame((function(){t.view.scrollDOM.scrollTop=o})),0!==r||0!==i){var n=e.EditorSelection.range(r,i),d=e.EditorView.scrollIntoView(n);d.value.isSnapshot=!0,this.view.dispatch({selection:e.EditorSelection.create([n]),effects:d})}a&&this.view.focus(),mw.hook("ext.CodeMirror.switch").fire(!0,$(this.view.dom))}}},{key:"addRealtimePreviewHandler",value:function(){var e=this;mw.hook("ext.WikiEditor.realtimepreview.enable").add((function(t){e.realtimePreviewHandler=t.getEventHandler().bind(t)})),mw.hook("ext.WikiEditor.realtimepreview.disable").add((function(){e.realtimePreviewHandler=null}))}},{key:"addCodeMirrorToWikiEditor",value:function(){var e=this,t=this.$textarea.data("wikiEditor-context"),r=t&&t.modules&&t.modules.toolbar;r&&(this.$textarea.wikiEditor("addToToolbar",{section:"main",groups:{codemirror:{tools:{CodeMirror:{label:mw.msg("codemirror-toggle-label"),type:"toggle",oouiIcon:"highlight",action:{type:"callback",execute:function(){return e.switchCodeMirror()}}}}}}}),r.$toolbar.find(".tool[rel=CodeMirror]").attr("id","mw-editbutton-codemirror"),this.readOnly&&this.$textarea.data("wikiEditor-context").$ui.addClass("ext-codemirror-readonly"),this.useCodeMirror&&this.enableCodeMirror(),this.updateToolbarButton(),this.logUsage({editor:"wikitext",enabled:this.useCodeMirror,toggled:!1,edit_start_ts_ms:1e3*parseInt($('input[name="wpStarttime"]').val(),10)||0}))}},{key:"updateToolbarButton",value:function(){var e=$("#mw-editbutton-codemirror");e.toggleClass("mw-editbutton-codemirror-active",this.useCodeMirror),e.data("setActive")&&e.data("setActive")(this.useCodeMirror)}},{key:"switchCodeMirror",value:function(){this.view?(this.setCodeMirrorPreference(!1),this.destroy(),mw.hook("ext.CodeMirror.switch").fire(!1,this.$textarea)):(this.enableCodeMirror(),this.setCodeMirrorPreference(!0)),this.updateToolbarButton(),this.logUsage({editor:"wikitext",enabled:this.useCodeMirror,toggled:!0,edit_start_ts_ms:1e3*parseInt($('input[name="wpStarttime"]').val(),10)||0})}}]),r}(require("ext.CodeMirror.v6"));module.exports=t;
|
|
@ -1 +0,0 @@
|
|||
"use strict";var r=require("ext.CodeMirror.v6.WikiEditor"),i=require("ext.CodeMirror.v6.mode.mediawiki");require("ext.CodeMirror.v6.lib"),require("ext.CodeMirror.v6");var e=new URLSearchParams(window.location.search);mw.loader.getState("ext.wikiEditor")&&mw.hook("wikiEditor.toolbarReady").add((function(o){new r(o,i({bidiIsolation:"rtl"===o.attr("dir")&&e.get("cm6bidi")})).addCodeMirrorToWikiEditor()}));
|
1
resources/dist/vendor.js
vendored
1
resources/dist/vendor.js
vendored
File diff suppressed because one or more lines are too long
29
resources/legacy/.eslintrc.json
Normal file
29
resources/legacy/.eslintrc.json
Normal file
|
@ -0,0 +1,29 @@
|
|||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"wikimedia/client",
|
||||
"wikimedia/jquery",
|
||||
"wikimedia/mediawiki"
|
||||
],
|
||||
"parserOptions": {
|
||||
"sourceType": "commonjs"
|
||||
},
|
||||
"globals": {
|
||||
"CodeMirror": "readonly"
|
||||
},
|
||||
"rules": {
|
||||
"max-len": "off",
|
||||
"es-x/no-object-assign": "warn"
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"files": [
|
||||
"addon/*.js"
|
||||
],
|
||||
"rules": {
|
||||
"computed-property-spacing": [ "error", "never" ],
|
||||
"indent": [ "error", 2 ]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -146,7 +146,6 @@ function init() {
|
|||
*/
|
||||
function enableCodeMirror() {
|
||||
const config = mw.config.get( 'extCodeMirrorConfig' );
|
||||
|
||||
mw.loader.using( codeMirrorCoreModules.concat( config.pluginModules ), () => {
|
||||
const selectionStart = $textbox1.prop( 'selectionStart' ),
|
||||
selectionEnd = $textbox1.prop( 'selectionEnd' ),
|
22861
resources/lib/codemirror6.bundle.dist.js
Normal file
22861
resources/lib/codemirror6.bundle.dist.js
Normal file
File diff suppressed because it is too large
Load diff
|
@ -1,99 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
const nodeResolve = require( '@rollup/plugin-node-resolve' );
|
||||
const copy = require( 'rollup-plugin-copy' );
|
||||
const babel = require( '@rollup/plugin-babel' );
|
||||
const terser = require( '@rollup/plugin-terser' );
|
||||
|
||||
const isProduction = process.env.BUILD === 'production';
|
||||
|
||||
/**
|
||||
* Mapping of import paths to ResourceLoader module names.
|
||||
* See usage in 'plugins' below for explanation.
|
||||
*
|
||||
* @type {Object}
|
||||
*/
|
||||
const importAliases = {
|
||||
'./vendor.js': 'ext.CodeMirror.v6.lib',
|
||||
'./codemirror.js': 'ext.CodeMirror.v6',
|
||||
'./codemirror.wikieditor.js': 'ext.CodeMirror.v6.WikiEditor',
|
||||
'./codemirror.mode.mediawiki.js': 'ext.CodeMirror.v6.mode.mediawiki'
|
||||
};
|
||||
|
||||
module.exports = [
|
||||
{
|
||||
// One entry for each ResourceLoader module that we want to ship.
|
||||
input: [
|
||||
'src/codemirror.js',
|
||||
'src/codemirror.mode.mediawiki.js',
|
||||
'src/codemirror.mediawiki.js',
|
||||
'src/codemirror.wikieditor.js',
|
||||
'src/codemirror.wikieditor.mediawiki.js'
|
||||
],
|
||||
input: 'resources/codemirror.bundle.js',
|
||||
|
||||
output: {
|
||||
entryFileNames: '[name].js',
|
||||
dir: 'resources/dist',
|
||||
|
||||
// Magically makes our ECMAScript Modules work with the
|
||||
// CommonJS-style preferred by ResourceLoader. Ta-da!
|
||||
format: 'cjs',
|
||||
|
||||
// Remove hash from chunked file name. We only want vendor code to be
|
||||
// chunked, and we need the file name to be stable for use by ResourceLoader.
|
||||
chunkFileNames: () => '[name].js',
|
||||
|
||||
// Bundle all vendor code into a single file called 'vendor.js'.
|
||||
// This includes the Babel helpers because they are used by all our modules.
|
||||
manualChunks: ( id ) => {
|
||||
if ( id.includes( 'node_modules' ) || id.includes( 'rollupPluginBabelHelpers' ) ) {
|
||||
return 'vendor';
|
||||
}
|
||||
}
|
||||
file: 'resources/lib/codemirror6.bundle.dist.js',
|
||||
format: 'cjs'
|
||||
},
|
||||
|
||||
plugins: [
|
||||
nodeResolve(),
|
||||
|
||||
// HACK: Rollup doesn't know about ResourceLoader and attempts to `require`
|
||||
// modules using a relative path, when they need to match the RL module name.
|
||||
// Here we do string replacements to fix that. This is nasty and brittle, but
|
||||
// otherwise we couldn't offer standalone CodeMirror functionality via RL,
|
||||
// which is necessary for usage in on-wiki scripts and gadgets (T214989).
|
||||
copy( {
|
||||
targets: [ {
|
||||
src: 'resources/dist/*',
|
||||
dest: 'resources/dist/',
|
||||
transform: ( contents ) => {
|
||||
Object.keys( importAliases ).forEach( ( alias ) => {
|
||||
contents = contents.toString().replace(
|
||||
`require("${ alias }")`,
|
||||
`require("${ importAliases[ alias ] }")`
|
||||
);
|
||||
// Yuck, need to do the same with single apostrophes
|
||||
// in the event terser is disabled such as during dev builds.
|
||||
contents = contents.toString().replace(
|
||||
`require('${ alias }')`,
|
||||
`require('${ importAliases[ alias ] }')`
|
||||
);
|
||||
} );
|
||||
return contents;
|
||||
}
|
||||
} ],
|
||||
hook: 'writeBundle'
|
||||
} ),
|
||||
|
||||
isProduction ? babel( { babelHelpers: 'bundled' } ) : null,
|
||||
|
||||
isProduction ? terser() : null
|
||||
],
|
||||
|
||||
onwarn: ( warning, warn ) => {
|
||||
// Suppress "not exported" warnings. We import those for IDE support not for the build.
|
||||
if ( warning.code === 'MISSING_EXPORT' ) {
|
||||
return;
|
||||
}
|
||||
warn( warning );
|
||||
}
|
||||
nodeResolve()
|
||||
]
|
||||
}
|
||||
];
|
||||
|
|
|
@ -1,24 +0,0 @@
|
|||
{
|
||||
"root": true,
|
||||
"extends": [
|
||||
"wikimedia/client-es6",
|
||||
"wikimedia/jquery",
|
||||
"wikimedia/mediawiki"
|
||||
],
|
||||
"parserOptions": {
|
||||
"sourceType": "module",
|
||||
"ecmaVersion": 2022
|
||||
},
|
||||
"env": {
|
||||
"browser": true,
|
||||
"commonjs": true
|
||||
},
|
||||
"globals": {
|
||||
"Tree": "readonly"
|
||||
},
|
||||
"rules": {
|
||||
"es-x/no-array-prototype-includes": 0,
|
||||
"es-x/no-class-fields": 0,
|
||||
"es-x/no-rest-spread-properties": 0
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
import CodeMirror from '../../src/codemirror.js';
|
||||
import mediaWikiLang from '../../src/codemirror.mode.mediawiki.js';
|
||||
const CodeMirror = require( '../../resources/codemirror.js' );
|
||||
const mediaWikiLang = require( '../../resources/codemirror.mediawiki.js' );
|
||||
|
||||
const testCases = [
|
||||
{
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
import { StreamParser } from '@codemirror/language';
|
||||
import { Tag } from '@lezer/highlight';
|
||||
import CodeMirror from '../../src/codemirror.js';
|
||||
import mediaWikiLang from '../../src/codemirror.mode.mediawiki.js';
|
||||
import { mwModeConfig } from '../../src/codemirror.mode.mediawiki.config.js';
|
||||
const { StreamParser } = require( '@codemirror/language' );
|
||||
const { Tag } = require( '@lezer/highlight' );
|
||||
const CodeMirror = require( '../../resources/codemirror.js' );
|
||||
const mediaWikiLang = require( '../../resources/codemirror.mediawiki.js' );
|
||||
const mwModeConfig = require( '../../resources/codemirror.mediawiki.config.js' );
|
||||
|
||||
// NOTE: each test case should have a space before the closing </div>
|
||||
// This is to avoid interactive UI components from showing up in the test output.
|
|
@ -1,5 +1,6 @@
|
|||
import { EditorView } from '@codemirror/view';
|
||||
import CodeMirror from '../../src/codemirror.js';
|
||||
/* eslint-disable-next-line n/no-missing-require */
|
||||
const { EditorView } = require( 'ext.CodeMirror.v6.lib' );
|
||||
const CodeMirror = require( '../../resources/codemirror.js' );
|
||||
const $textarea = $( '<textarea>' ),
|
||||
cm = new CodeMirror( $textarea );
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
mw.loader = { getState: jest.fn() };
|
||||
|
||||
const CodeMirrorWikiEditor = require( '../../src/codemirror.wikieditor.js' ).default,
|
||||
const CodeMirrorWikiEditor = require( '../../resources/codemirror.wikieditor.js' ),
|
||||
$textarea = $( '<textarea>' )
|
||||
.text( 'The Smashing Pumpkins' ),
|
||||
cmWe = new CodeMirrorWikiEditor( $textarea );
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
jest.mock( '../../ext.CodeMirror.data.js', () => jest.fn(), { virtual: true } );
|
||||
const mockBundle = require( '../../resources/lib/codemirror6.bundle.dist.js' );
|
||||
jest.mock( 'ext.CodeMirror.v6.lib', () => mockBundle, { virtual: true } );
|
||||
const mockCodeMirror = require( '../../resources/codemirror.js' );
|
||||
jest.mock( 'ext.CodeMirror.v6', () => mockCodeMirror, { virtual: true } );
|
||||
jest.mock( '../../resources/ext.CodeMirror.data.js', () => jest.fn(), { virtual: true } );
|
||||
global.mw = require( '@wikimedia/mw-node-qunit/src/mockMediaWiki.js' )();
|
||||
mw.user = Object.assign( mw.user, {
|
||||
options: {
|
||||
|
|
Loading…
Reference in a new issue