Skip to content

fix(cm): preserve CodeMirror mode aliases and improve mode picker#1974

Merged
bajrangCoder merged 1 commit intoAcode-Foundation:mainfrom
bajrangCoder:fix/codemirror-supported-modes
Mar 23, 2026
Merged

fix(cm): preserve CodeMirror mode aliases and improve mode picker#1974
bajrangCoder merged 1 commit intoAcode-Foundation:mainfrom
bajrangCoder:fix/codemirror-supported-modes

Conversation

@bajrangCoder
Copy link
Copy Markdown
Member

No description provided.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Mar 23, 2026

Greptile Summary

This PR overhauls the CodeMirror mode registry to preserve language aliases (e.g. "cpp" → C++, "js" → JavaScript) and improves the mode picker palette with alphabetical sorting, active-mode pinning, and searchable hidden terms. It also fixes a regex injection bug in inputhints where raw user input was passed directly to new RegExp().

Key changes:

  • modelist.tsMode now carries aliases and filenameMatchers; addMode/removeMode maintain alias entries in modesByName; new getMode(name) export resolves a mode by its canonical name or any registered alias.
  • supportedModes.ts — language registration loop now preserves alias arrays from @codemirror/language-data, clones RegExp filename matchers, and slugifies unsafe mode IDs (c++cpp, c#csharp).
  • editorFile.js / editorManager.js — mode resolution now goes through getMode() first, so alias-stored values in localStorage.modeassoc are correctly mapped to their canonical mode.
  • inputhints/index.jsbug fix: user search input is now escaped with escapeRegExp before being compiled into a RegExp, preventing crashes on special characters.
  • changeMode/index.js — modes are sorted alphabetically with the active mode pinned to the top; the search span now includes aliases and extensions for better discoverability.
  • package.json — added lang-angular, lang-jinja, lang-less, lang-liquid, lang-sql, and lang-wast language packages.

Issues found:

  • The HTML template in changeMode/index.js interpolates caption, mode, and aliases directly into an innerHTML string without HTML-escaping. Safe today with built-in language data, but exposes a DOM-injection path if a plugin registers a mode with characters like <, >, or & in its caption.
  • escapeRegExp and normalizeModeKey are defined independently in three separate files (modelist.ts, supportedModes.ts, inputhints/index.js) and should be extracted into a shared utility module.

Confidence Score: 4/5

  • Safe to merge after fixing the unescaped HTML in the hint template; core alias logic and regex escaping fixes are solid.
  • The alias registry, regex-safety fix in inputhints, and improved mode picker are all well-implemented. The one concrete issue — unescaped HTML in the innerHTML hint template in changeMode/index.js — doesn't affect built-in language data today but is a real injection path for plugin-registered modes. Resolving that brings this to a clear merge.
  • src/palettes/changeMode/index.js — the HTML template interpolation should sanitize caption/mode/alias values before inserting them as innerHTML.

Important Files Changed

Filename Overview
src/cm/modelist.ts Core mode registry refactored to support aliases and RegExp filename matchers. addMode/removeMode correctly maintain alias entries in modesByName. New getMode() export enables direct lookup by alias. supportsFile now handles null extRe and resets lastIndex on stateful RegExps. Specificity scoring extended for filenameMatchers. Logic is sound.
src/cm/supportedModes.ts Language registration loop now preserves alias arrays, clones RegExp filename matchers, and slugifies unsafe mode IDs (e.g. "c++" → "cpp"). Duplicate utility functions (normalizeModeKey, escapeRegExp) are defined locally instead of shared with modelist.ts.
src/palettes/changeMode/index.js Mode picker improved with alphabetical sorting, active-mode pinning at top, and searchable hidden terms. HTML injection risk: title and searchTerms are embedded in an innerHTML template without escaping — currently safe for built-in language data but unsafe if plugins register modes with HTML-special characters in captions.
src/components/inputhints/index.js Fixed ReDoS/crash: user input is now escaped before being used as a RegExp. Added active flag support to HintObj and the Hint JSX component, enabling CSS highlighting of the current selection.
src/lib/editorFile.js Mode resolution now goes through getMode() first (respecting aliases) before falling back to path detection. currentLanguageExtension now correctly reflects the explicitly-set mode's extension rather than always re-deriving it from the filename.
src/lib/editorManager.js getFileLanguageId now resolves language IDs through getMode() so that alias-stored modes (e.g. "cpp" → C++) are correctly mapped to their canonical name for LSP language IDs.
package.json Added new language packages (lang-angular, lang-jinja, lang-less, lang-liquid, lang-sql, lang-wast) and updated lang-javascript to 6.2.5. Removed direct @codemirror/autocomplete and @codemirror/commands dependencies (presumably now pulled in transitively). Added list:modes utility script.
bun.lock Lock file updated to reflect new/upgraded dependencies. Version pinning looks consistent with package.json changes.

Sequence Diagram

sequenceDiagram
    participant P as changeMode palette
    participant EF as editorFile.setMode()
    participant ML as modelist
    participant SM as supportedModes (init)

    Note over SM,ML: App startup
    SM->>ML: addMode(modeId, pattern, caption, loader, {aliases, filenameMatchers})
    ML->>ML: modesByName[modeId] = mode
    ML->>ML: modesByName[alias] = mode (for each alias)
    ML->>ML: modes.push(mode)

    Note over P,EF: User picks a mode
    P->>P: generateHints() — sort, pin active, add alias search terms
    P->>EF: onselect(modeId) → activeFile.setMode(modeId)
    EF->>ML: getMode(modeId)
    ML-->>EF: Mode (found by primary key or alias)
    EF->>EF: currentMode = mode.name
    EF->>EF: currentLanguageExtension = mode.getExtension()

    Note over EF,ML: File open with stored association
    EF->>EF: mode = localStorage.modeassoc[ext]
    EF->>ML: getMode(storedMode)
    alt alias resolved
        ML-->>EF: Mode
    else not found
        ML-->>EF: null
        EF->>ML: getModeForPath(filename)
        ML-->>EF: Mode (by extension/filename regex)
    end
Loading

Reviews (1): Last reviewed commit: "fix(cm): preserve CodeMirror mode aliase..." | Re-trigger Greptile

Comment thread src/palettes/changeMode/index.js
Comment thread src/cm/supportedModes.ts
@bajrangCoder bajrangCoder merged commit 95031ba into Acode-Foundation:main Mar 23, 2026
5 checks passed
@bajrangCoder bajrangCoder deleted the fix/codemirror-supported-modes branch March 23, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant