-
Notifications
You must be signed in to change notification settings - Fork 3.2k
Upgrade CodeMirror to latest v5 #10778
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: trunk
Are you sure you want to change the base?
Upgrade CodeMirror to latest v5 #10778
Conversation
Adds codemirror, csslint, htmlhint, jsonlint, and esprima to package.json dependencies to manage them via npm. This aligns with the strategy for other vendor libraries in Core. Command: npm install codemirror@5.65.18 csslint@1.0.5 htmlhint@1.1.4 jsonlint@1.6.3 esprima@4.0.1 --save-prod --save-exact Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Removes manually bundled codemirror.min.js/css and standalone linters (csslint, esprima, htmlhint, jsonlint) from src/js/_enqueues/vendor/codemirror/. These will be replaced by artifacts generated from npm dependencies via the build process. Core-specific wrappers (fakejshint.js, htmlhint-kses.js) are preserved. Command: rm src/js/_enqueues/vendor/codemirror/codemirror.min.js src/js/_enqueues/vendor/codemirror/codemirror.min.css src/js/_enqueues/vendor/codemirror/csslint.js src/js/_enqueues/vendor/codemirror/esprima.js src/js/_enqueues/vendor/codemirror/htmlhint.js src/js/_enqueues/vendor/codemirror/jsonlint.js Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Creates tools/vendors/codemirror-entry.js, which replicates the logic of the original codemirror.manifest.js. This file aggregates the core library, modes, keymaps, and addons into a single entry point for the build process and exposes the global window.wp.CodeMirror object. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Adds tools/webpack/codemirror.config.js to handle the bundling of the CodeMirror entry point into src/wp-includes/js/codemirror/codemirror.min.js. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Updates Gruntfile.js to include tasks for building CodeMirror: - Registers a 'codemirror' target for webpack to bundle the JS. - Registers a 'codemirror' target for concat to bundle the CSS. - Registers a 'codemirror' target for cssmin to minify the CSS. - Registers a 'codemirror' target for copy to move linters and wrappers. - Creates a combined 'build:codemirror' task. - Adds 'build:codemirror' to the main 'build' task workflow. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Updates the version strings for CodeMirror and its related linters (csslint, esprima, jsonlint, htmlhint) to reflect the upgrade to v5.65.18. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Adds the required license header to the minified CodeMirror bundles during the build process. - Updates tools/webpack/codemirror.config.js to include the license header using BannerPlugin and ensures Terser preserves important comments. - Adds a usebanner:codemirror task to Gruntfile.js to append the license header to the minified CSS. - Dynamically retrieves the CodeMirror version from package.json for inclusion in the header. - Reformats the license headers to use multi-line backtick string literals for better maintainability. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Ensures the CodeMirror license banner is applied to the unminified `codemirror.css` file in addition to the minified version. Also enables the `linebreak` option for the CodeMirror banner to ensure a newline separates the header from the content. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Refactors the CodeMirror CSS build process to add the license banner to the unminified `codemirror.css` file first. The `cssmin` task then generates `codemirror.min.css` from this file, preserving the license header while stripping unnecessary whitespace. - Updates `usebanner:codemirror` to target only the unminified file. - Reorders the `build:codemirror` task sequence to run `usebanner:codemirror` before `cssmin:codemirror`. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Test using WordPress PlaygroundThe changes in this pull request can previewed and tested using a WordPress Playground instance. WordPress Playground is an experimental project that creates a full WordPress instance entirely within the browser. Some things to be aware of
For more details about these limitations and more, check out the Limitations page in the WordPress Playground documentation. |
Updates the CodeMirror CSS build process to perform concatenation and minification in a single `cssmin` task. This eliminates the need for an intermediate unminified file and ensures the license banner is applied correctly to the final minified bundle without an extra newline. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Adds `codemirror`, `csslint`, `esprima`, `htmlhint`, and `jsonlint` to the manually registered vendor scripts data provider in `Tests_Dependencies_Scripts::data_vendor_script_versions_registered_manually`. This ensures that `test_vendor_script_data_provider_includes_all_packages` passes by accounting for these dependencies which are present in `package.json`. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Upgrades `htmlhint` to v1.8.0 and configures it as an external in the CodeMirror Webpack bundle to avoid duplicate code and ensure compatibility with Core wrappers. - Handles the change in HTMLHint's UMD export structure (where the instance is nested under `HTMLHint.HTMLHint`) by applying a build-time patch to `htmlhint.js` during the copy task. This patch unwraps the instance into the global scope, ensuring compatibility with CodeMirror's `html-lint` addon and WordPress's `htmlhint-kses` wrapper. - Configures `tools/webpack/codemirror.config.js` to use `window.*` for linter externals (`htmlhint`, `csslint`, `jshint`, `jsonlint`), preventing `ReferenceError` when these optional libraries are not loaded. - Updates `package.json` and `script-loader.php` to reflect the HTMLHint v1.8.0 upgrade. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Updates the `copy:codemirror` task in `Gruntfile.js` to correctly identify and patch `htmlhint.min.js`. This ensures that the `HTMLHint` global is correctly unwrapped (fixing the namespace issue) when using the minified distribution of HTMLHint v1.8.0. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Upgrades `codemirror` from 5.65.18 to 5.65.20 in `package.json` and `script-loader.php`. This ensures WordPress is using the absolute latest maintenance release of the CodeMirror v5 series. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
|
The following accounts have interacted with this PR and/or linked issues. I will continue to update these lists as activity occurs. You can also manually ask me to refresh this list by adding the Core Committers: Use this line as a base for the props when committing in SVN: To understand the WordPress project's expectations around crediting contributors, please review the Contributor Attribution page in the Core Handbook. |
Aligns the JSHint settings used in the code editor with the project's `.jshintrc` file. This includes updating to ES10, removing deprecated options like `es3`, `onevar`, and `trailing`, and adding missing globals. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR upgrades WordPress Core’s CodeMirror v5 integration to a newer upstream release by sourcing CodeMirror (and related linters) from npm and generating the runtime assets via the build tooling, then updating registered script/style versions accordingly.
Changes:
- Add npm dependencies for
codemirrorand linters (csslint,htmlhint,jsonlint,esprima), and update vendor version assertions in PHPUnit. - Introduce a dedicated Webpack entry/config to bundle CodeMirror + addons/modes, and wire a new
build:codemirrortask into the main Grunt build. - Update
wp_default_scripts()/wp_default_styles()registrations to the new package versions.
Reviewed changes
Copilot reviewed 6 out of 13 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
tools/webpack/codemirror.config.js |
New Webpack config for building codemirror.min.js with a license banner and externals for linters. |
tools/vendors/codemirror-entry.js |
New Webpack entry that imports CodeMirror core + required addons/modes and exposes it on window.wp. |
Gruntfile.js |
Adds webpack:codemirror, cssmin:codemirror, copy:codemirror, banner handling, and integrates build:codemirror into build. |
src/wp-includes/script-loader.php |
Updates registered versions for wp-codemirror and linter handles to match npm package versions. |
tests/phpunit/tests/dependencies/scripts.php |
Extends vendor-version test coverage to include CodeMirror and linter handles. |
package.json / package-lock.json |
Adds/locks new npm dependencies required for the CodeMirror + linter build pipeline. |
src/js/_enqueues/vendor/codemirror/* |
Removes previously bundled vendor artifacts now sourced from npm/build (leaving core wrappers). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Updates `tools/webpack/codemirror.config.js` to export a function that accepts a `buildTarget` parameter, ensuring the bundled CodeMirror script is written to the correct directory (`src/` for dev builds, `build/` for production). Also updates `Gruntfile.js` to pass the `WORKING_DIR` to this configuration function. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Updates the comments in `codemirror-entry.js` to correctly describe the CodeMirror import and explain the distinction between `window.wp.CodeMirror` and the minimal version set by the `runmode-standalone` addon. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Resets the global `usebanner.options.linebreak` to `true` to prevent affecting other build outputs, while maintaining `linebreak: false` specifically for the CodeMirror CSS bundle. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| 'curly' => true, | ||
| 'eqeqeq' => true, | ||
| 'eqnull' => true, | ||
| 'esversion' => 10, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Note that esprima doesn't support this, apparently, so ES6 syntax still is reported as a syntax error 😦
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://esprima.org/doc/es6.html
Given that Esprima hasn't been updated in 8 years, we might want to consider turning JS linting off by default the same as we did for CSS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See Core-44471 for why CSS linting was disabled for a similar reason.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like we could replace Esprima with Espree which is actively maintained: https://www.npmjs.com/package/espree
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hah. So easy: ee2b6bd
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might want to revert this commit for another ticket, but it's closely related and I think makes sense to go out together.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 7 out of 14 changed files in this pull request and generated 3 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // The following are copied from <https://github.com/WordPress/wordpress-develop/blob/6.9.0/.jshintrc>. | ||
| 'boss' => true, | ||
| 'curly' => true, | ||
| 'eqeqeq' => true, | ||
| 'eqnull' => true, | ||
| 'esversion' => 10, | ||
| 'expr' => true, |
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The JSHint defaults are now kept in sync with the repo’s root .jshintrc (which is great), but the comment references a specific GitHub URL/tag. To reduce churn/broken links over time, consider referencing the local .jshintrc file (or a relative path) instead of a versioned external URL.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not really relevant here. It would be nice to not duplicate but in reality this file changes very rarely.
Moves the CodeMirror license banner to a dedicated `codemirror-banner.js` file to avoid duplication between the Grunt and Webpack configurations and ensure consistency across JS and CSS build outputs. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…ions. Sets `target: 'browserslist'` and provides a default for the `env` parameter in `codemirror.config.js` to ensure consistent browser compatibility and prevent runtime errors when called without arguments. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Replaces the outdated `esprima` parser with `espree` to provide support for modern JavaScript (ES6+) validation in the code editor. A new `espree` script handle is registered, and the `fakejshint` wrapper is updated to use it while maintaining the `esprima` handle for backward compatibility. - Adds `espree` to `package.json`. - Creates `tools/vendors/espree-entry.js` and adds a new Webpack entry point to bundle `espree`. - Updates `fakejshint.js` to utilize `window.espree.parse` with ES6+ support. - Registers `espree` in `script-loader.php` and updates `jshint` handle dependencies. - Updates PHPUnit test data provider to include `espree`. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
|
I tested this PR in Playground, by installing my plugin (TablePress), which embeds CodeMirror on its "Plugin Options" screen, for adding CSS code. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 9 out of 17 changed files in this pull request and generated 4 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| src: [ | ||
| WORKING_DIR + 'wp-includes/js/codemirror/codemirror.min.css' | ||
| ] |
Copilot
AI
Jan 23, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
usebanner is invoked without a target as part of build:css (see the build:css task later in this file). Adding a separate usebanner:codemirror target means grunt usebanner will also try to banner wp-includes/js/codemirror/codemirror.min.css during build:css, but that file is only generated in build:codemirror (which runs afterwards). Consider changing build:css to run usebanner:files (and keep usebanner:codemirror only in build:codemirror), or otherwise reordering tasks so the file exists when the usebanner:codemirror target runs.
| src: [ | |
| WORKING_DIR + 'wp-includes/js/codemirror/codemirror.min.css' | |
| ] | |
| src: [] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Addressed in cf742fa.
Gemini's reasoning:
The problem solved is a task execution conflict that would occur during a full production build (
grunt build).In Grunt, if you invoke a task without a specific target (e.g., calling
'usebanner'instead of'usebanner:files'), it automatically tries to run all defined targets for that task.In your
Gruntfile.js,usebannerhas two targets:
files: Handles general WordPress Core CSS/JS.codemirror: Handles the specific CodeMirror CSS bundle.The
build:csstask (which is part of the main Core build) was calling the generic'usebanner'. This meant that every time someone ran a standard CSS build, Grunt would try to add a banner towp-includes/js/codemirror/codemirror.min.css.However, that CodeMirror file is not created until the
build:codemirrortask runs later. This would cause Grunt to throw a "File not found" warning or error during the general CSS build phase.By explicitly calling
'usebanner:files'inbuild:css, we ensure that the general build only touches general files, and the CodeMirror banner is handled only when CodeMirror itself is actually being built.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Updates `build:css` to specifically invoke `usebanner:files` and `build:codemirror` to invoke `usebanner:codemirror`. This prevents the generic `usebanner` task from attempting to process files that have not yet been generated during the general CSS build phase. Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
…endency. Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
Copilot reviewed 9 out of 17 changed files in this pull request and generated 1 comment.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Unprops Copilot for 7db8792 Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Trac ticket: https://core.trac.wordpress.org/ticket/48456
For Gemini CLI, I provided the following spec:
I also provided https://github.com/WordPress/better-code-editing as context for where the CodeMirror integration originally came from.
I then iterated on the plan with Gemini for awhile, and came up with the following:
I then told Gemini to execute the plan, creating commits for each logical step.
Initial Gemini Review
Addressed in 2fb47e4, 3fb2281, 79295b3
Removed in 0dcbf28.
Yes, they match the original manifest: https://github.com/WordPress/better-code-editing/blob/master/wp-includes/js/codemirror/codemirror.manifest.js
Gemini also pointed out an issue where the core library was being included twice before. Now it is included once. This doesn't appear to have any impact on the resulting bundle size, however.
The new
codemirror.min.jsis 620,848 bytes. The old one was 585,414 bytes. So the newer version of CodeMirror is a bit larger.Yes. That is correct.
Since
fakehshint.jsis unchanged, it doesn't seem like it should have its version updated, even though it was swapped out originally in 5bb7fc1 without having its version changed (which it should have to bust caches).Second Gemini Review
The file was actually minified: https://github.com/WordPress/wordpress-develop/blob/trunk/src/js/_enqueues/vendor/codemirror/htmlhint.js
So this is consistent.
Keeping only the minified versions preserves the status quo, and keeps the ZIP from growing.
Demos
PHP file in Plugin Editor
Screen.Recording.2026-01-22.at.21.57.10.mov
JS file in Theme Editor
Screen.Recording.2026-01-22.at.22.09.17.mov
CSS file in Theme Editor
Screen.Recording.2026-01-22.at.22.10.33.mov
Additional CSS in Customizer
Screen.Recording.2026-01-22.at.22.11.47.mov
Custom HTML Widget with disallowed
unfiltered_htmlScreen.Recording.2026-01-22.at.22.14.07.mov
This Pull Request is for code review only. Please keep all other discussion in the Trac ticket. Do not merge this Pull Request. See GitHub Pull Requests for Code Review in the Core Handbook for more details.