[ESLint] Drive lint warnings to zero - #4090
Merged
Merged
Conversation
`regexp/recommended` was added unintentionally during the ESLint v9 migration (cbfeb53) and overrode the curated regex ruleset. Remove that spread so the hand-picked list at the top of eslint.config.mjs is the active policy. Re-add 11 bug-catching rules from `recommended` that don't fight Prism's grammar idioms. Disable `prefer-const` to match team convention. Add globals for `src/plugins/**/demo.js`. Apply minor auto-fixes and inline-disable 4 intentional regex patterns. 869 warnings → 0; lint:ci, build, typecheck, tests, and regex-coverage all pass.
✅ Deploy Preview for dev-prismjs-com ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
3 tasks
LeaVerou
approved these changes
Jun 26, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Restores the team's intentional ESLint regex policy and drives
npm run lint:ciwarnings from 869 → 0 with zero churn in language grammars.The root cause was migration drift: during the ESLint v9 flat-config migration (
cbfeb53d),regexpPlugin.configs.recommended.ruleswas spread alongsideeslint-comments/recommendedand the (now-removed) TypeScript recommended configs. The pre-v9.eslintrc.jshad never extendedplugin:regexp/recommended— the team had a hand-curated 29-rule list at the top of the JS rules block. Restoring the deletion makes the curated list the active policy again.Changes to
eslint.config.mjsregexp/recommendedspread — restores the curated regex policy. ~830 stylistic warnings vanish, no code touched.regexp/recommendedthat survived the audit (see below).prefer-const— matches the team convention of reusingletbindings (already disabled on thesimplifybranch inb4366b2b).src/plugins/**/demo.js(Prism,JSZip,components,saveAs) plusno-unused-vars: off(these scripts expose functions consumed by HTML attributes likedata-adapter="…").Audit — which
regexp/recommendedrules we kept and whyRather than restore the whole preset, I read every currently-active warning in actual Prism source. Every one of the 32 currently-firing warnings fires on an intentional Prism pattern, not a bug:
regexp/no-contradiction-with-assertion^...$[\s\S]*?^\1multi-line block matchers (asciidoc, autoit, d, hcl) — work correctlyregexp/no-misleading-capturing-group<MOD>template substitution (rule can't see substitution); 3 valid edge cases that work for valid inputregexp/no-empty-character-class[^\s\S]/[]deliberately used as recursion terminators in ftl/icu-message-format/lilypond/rust grammarsregexp/no-extra-lookaround-assertionsregexp/no-misleading-unicode-character[\r\n]in systemd.js — rule is for grapheme clusters, not control charsThe 11 rules we kept all have zero current warnings but guard real bug classes Prism could introduce later:
no-empty-group,no-empty-string-literal,no-escape-backspace,no-invalid-regexp,no-invisible-character,no-legacy-features,no-missing-g-flag,no-non-standard-flag,no-potentially-useless-backreference,no-useless-backreference,no-useless-dollar-replacements.Code changes outside the config
After the config changes, 11 warnings remained. Auto-fix handled most:
src/languages/python.js— sortedlazyalphabetically into the keyword alternation (safe;\bboundaries handle prefix collisions)src/plugins/autoloader/demo.js— escaped\}in/\{id\}/gsrc/plugins/toolbar/demo.js—onClick: function (env) {→onClick (env) {src/util/async.js— removed trailing blank doc-comment linesrc/languages/markdown.js— removed 2 dead imports left over from a recent refactor (b8180e33)Four inline-disabled with justifying comments:
src/languages/docker.js:18—no-dupe-disjunctionsfalse positive (the(?!["'])lookahead makes the unquoted alternative disjoint from<STR>)src/languages/mongodb.js:291,src/languages/promql.js:42,src/languages/promql.js:89—sort-alternativeson arrays intentionally ordered by semantics/docs rather than alphabetVerification
npm run lint:ci— 0 warnings (--max-warnings 0passes)npm test— full suite (test:components/core/identifiers/languages/patterns/plugins/runner)npm run regex-coverage— 980 passingnpm run typecheck— clean (core + tests)npm run build— cleanNot in scope
eslint-plugin-regexp2.7.0 → 3.1.1 (separate PR; v3 likely tightens rules)--max-warnings 0(the threshold is correct; goal was to make the count zero)src/languages/**Test plan
npm run lint:cipasses on CI (verified locally and in CI lint job)