### Initialize Basic CodeMirror Editor Source: https://github.com/codemirror/website/blob/main/site/examples/basic/index.md Instantiate an EditorView with basic setup. This is the simplest way to get a functional editor. ```javascript import {basicSetup} from "codemirror" import {EditorView} from "@codemirror/view" const view = new EditorView({ doc: "Start document", parent: document.body, extensions: [basicSetup] }) ``` -------------------------------- ### Minimal CodeMirror Editor Setup Source: https://github.com/codemirror/website/blob/main/site/docs/ref/index.html Demonstrates the basic setup for a CodeMirror editor using essential view and command modules. Requires importing EditorView and keymap from '@codemirror/view' and defaultKeymap from '@codemirror/commands'. ```javascript import {EditorView, keymap} from "@codemirror/view" import {defaultKeymap} from "@codemirror/commands" let myView = new EditorView({ doc: "hello", extensions: [keymap.of(defaultKeymap)], parent: document.body }) ``` -------------------------------- ### CodeMirror Editor Setup with Basic Extensions Source: https://github.com/codemirror/website/blob/main/site/docs/guide/index.md Configures a CodeMirror editor with common features included in the 'basicSetup' extension and language support for JavaScript. This is a more convenient way to start. ```javascript import {EditorView, basicSetup} from "codemirror" import {javascript} from "@codemirror/lang-javascript" let view = new EditorView({ extensions: [basicSetup, javascript()], parent: document.body }) ``` -------------------------------- ### Build CodeMirror Website Source: https://github.com/codemirror/website/blob/main/README.md Standard npm commands to install dependencies, build the website, and list the output directory. ```bash npm i npm run build ls output # ← the website is in there ``` -------------------------------- ### Main Editor State Setup Source: https://github.com/codemirror/website/blob/main/site/examples/split/index.md Sets up the state for the main editor, including the history extension. ```typescript let startState = EditorState.create({ doc: "The first editor content.\n", extensions: [ history(), EditorView.updateListener.of(update => { if (update.docChanged) console.log("Main editor changed") }) ] }); ``` -------------------------------- ### Install CodeMirror and Rollup Dependencies Source: https://github.com/codemirror/website/blob/main/site/examples/bundle/index.md Install the required CodeMirror packages, Rollup, and the node-resolve plugin using npm. This sets up your project for bundling. ```shell # The CodeMirror packages used in our script npm i codemirror @codemirror/lang-javascript # Rollup and its plugin npm i rollup @rollup/plugin-node-resolve ``` -------------------------------- ### Minimal CodeMirror Editor Setup Source: https://github.com/codemirror/website/blob/main/site/examples/bundle/index.md This is the most basic CodeMirror editor setup. It uses `minimalSetup` which includes essential extensions for a functional editor, resulting in a smaller bundle size compared to `basicSetup`. ```javascript import {EditorView, minimalSetup} from "codemirror" let editor = new EditorView({ extensions: minimalSetup, parent: document.body }) ``` -------------------------------- ### Bundle CodeMirror with Rollup Source: https://context7.com/codemirror/website/llms.txt This example demonstrates how to bundle a CodeMirror editor using Rollup for browser compatibility. Ensure you have installed the necessary npm packages. ```javascript import { EditorView, basicSetup } from "codemirror" import { javascript } from "@codemirror/lang-javascript" new EditorView({ extensions: [basicSetup, javascript()], parent: document.body }) ``` ```shell # Install packages npm install codemirror @codemirror/lang-javascript npm install rollup @rollup/plugin-node-resolve # Bundle npx rollup editor.mjs -f iife -o editor.bundle.js -p @rollup/plugin-node-resolve ``` ```javascript // rollup.config.mjs import { nodeResolve } from "@rollup/plugin-node-resolve" export default { input: "./editor.mjs", output: { file: "./editor.bundle.js", format: "iife" }, plugins: [nodeResolve()] } ``` ```html ``` -------------------------------- ### Example Usage of ToggleWith Source: https://github.com/codemirror/website/blob/main/site/examples/config/index.md Demonstrates how to use the `toggleWith` function to conditionally apply editor attributes. This example applies a yellow background when the extension is active. ```javascript toggleWith("Mod-o", EditorView.editorAttributes.of({ style: "background: yellow" })) ``` -------------------------------- ### Extension Precedence Example Source: https://github.com/codemirror/website/blob/main/site/examples/config/index.md Demonstrates how extensions are ordered and how precedence affects their resolution. Higher precedence extensions are applied before lower ones. ```javascript [..., [keymap.of(A)], ..., [[], ..., [keymap.of(B)]]] ``` ```javascript [Prec.high(A), B, Prec.high([C, D])] ``` -------------------------------- ### Minimal Viable CodeMirror Editor Setup Source: https://github.com/codemirror/website/blob/main/site/docs/guide/index.md Sets up a basic CodeMirror editor using core packages. Requires explicit import of state, view, and command modules. ```javascript import {EditorState} from "@codemirror/state" import {EditorView, keymap} from "@codemirror/view" import {defaultKeymap} from "@codemirror/commands" let startState = EditorState.create({ doc: "Hello World", extensions: [keymap.of(defaultKeymap)] }) let view = new EditorView({ state: startState, parent: document.body }) ``` -------------------------------- ### Basic Editor Setup with basicSetup Source: https://context7.com/codemirror/website/llms.txt Sets up a minimal CodeMirror editor with common extensions like syntax highlighting and autocompletion. Requires importing EditorView, basicSetup, and language extensions. ```javascript import { EditorView, basicSetup } from "codemirror" import { javascript } from "@codemirror/lang-javascript" const view = new EditorView({ doc: "console.log('hello world')", extensions: [basicSetup, javascript()], parent: document.getElementById("editor") }) // Read current document console.log(view.state.doc.toString()) // => "console.log('hello world')" ``` -------------------------------- ### Integrate Language Support in CodeMirror Source: https://github.com/codemirror/website/blob/main/site/examples/basic/index.md Add language-specific support, such as JavaScript syntax highlighting and autocompletion, to the CodeMirror editor. This example includes the basic setup and the JavaScript language extension. ```javascript import {javascript} from "@codemirror/lang-javascript" import {EditorView, basicSetup} from "codemirror" const view = new EditorView({ doc: "Start document", parent: document.body, extensions: [ basicSetup, javascript({typescript: true}) ] }) ``` -------------------------------- ### Minimal Editor Setup (Low Bundle Size) Source: https://context7.com/codemirror/website/llms.txt Constructs a CodeMirror editor with only essential extensions for a smaller bundle size. This approach requires manually selecting and importing each needed extension. ```javascript import { EditorView, keymap, lineNumbers, highlightActiveLine, highlightSpecialChars, drawSelection, dropCursor } from "@codemirror/view" import { EditorState, EditorStateConfig } from "@codemirror/state" import { defaultKeymap, history, historyKeymap } from "@codemirror/commands" import { syntaxHighlighting, defaultHighlightStyle } from "@codemirror/language" import { javascript } from "@codemirror/lang-javascript" const view = new EditorView({ doc: "// type here", parent: document.body, extensions: [ lineNumbers(), highlightSpecialChars(), history(), drawSelection(), dropCursor(), highlightActiveLine(), syntaxHighlighting(defaultHighlightStyle), javascript(), keymap.of([...defaultKeymap, ...historyKeymap]) ] }) ``` -------------------------------- ### Second Editor State Setup Source: https://github.com/codemirror/website/blob/main/site/examples/split/index.md Sets up the state for the second editor, which does not track its own history but binds history keys to the main editor. ```typescript let otherState = EditorState.create({ doc: "The second editor content.\n", extensions: [ EditorView.updateListener.of(update => { if (update.docChanged) console.log("Second editor changed") }) ] }); ``` -------------------------------- ### Extension Bundles Source: https://github.com/codemirror/website/blob/main/site/docs/extensions/index.html Pre-defined bundles of extensions for common setups. ```APIDOC ## basicSetup ### Description An array of extensions that enables many of the features listed on this page. ### Type Extension Array ### Reference `[basicSetup](../ref/#codemirror.basicSetup)` ``` ```APIDOC ## minimalSetup ### Description A much more minimal collection of extensions, containing just the ones that are recommended for every editor. ### Type Extension Array ### Reference `[minimalSetup](../ref/#codemirror.minimalSetup)` ``` -------------------------------- ### Setup Collaborative Editing Environment Source: https://github.com/codemirror/website/blob/main/site/examples/collab/index.md Includes HTML structure and script tags to load CodeMirror and the collaborative editing module. This sets up the server controls and editor areas. ```html
Server
``` -------------------------------- ### Editor View Setup Source: https://github.com/codemirror/website/blob/main/site/examples/split/index.md Creates and mounts two CodeMirror editor views, linking them with the synchronizing dispatch function. ```typescript let mainEditor = new EditorView({ state: startState, parent: document.getElementById("editor1")!, dispatch: syncDispatch(mainEditor, otherEditor) }); let otherEditor = new EditorView({ state: otherState, parent: document.getElementById("editor2")!, dispatch: syncDispatch(mainEditor, otherEditor) }); ``` -------------------------------- ### Dynamic Reconfiguration with Compartments Source: https://context7.com/codemirror/website/llms.txt Use Compartments to swap out parts of the extension configuration at runtime. This example shows how to switch languages and change tab sizes. ```javascript import { EditorView, basicSetup } from "codemirror" import { EditorState, Compartment } from "@codemirror/state" import { python } from "@codemirror/lang-python" import { javascript } from "@codemirror/lang-javascript" const language = new Compartment() const tabSize = new Compartment() const view = new EditorView({ state: EditorState.create({ doc: "print('hello')", extensions: [ basicSetup, language.of(python()), tabSize.of(EditorState.tabSize.of(4)) ] }), parent: document.body }) // Switch language at runtime function setLanguage(lang) { view.dispatch({ effects: language.reconfigure(lang) }) } setLanguage(javascript()) // Change tab size at runtime function setTabSize(size) { view.dispatch({ effects: tabSize.reconfigure(EditorState.tabSize.of(size)) }) } setTabSize(2) // Toggle an extension on/off function toggleWith(key, extension) { const compartment = new Compartment() function toggle(view) { const on = compartment.get(view.state) === extension view.dispatch({ effects: compartment.reconfigure(on ? [] : extension) }) return true } return [compartment.of([]), keymap.of([{ key, run: toggle }])] } ``` -------------------------------- ### Peer Extension Setup Source: https://github.com/codemirror/website/blob/main/site/examples/collab/index.md Configures a CodeMirror view plugin for peer-to-peer collaboration. It manages asynchronous logic, pulling updates, and pushing local changes. ```typescript const peerExtension = (version: number, connection: Connection) => ViewPlugin.fromClass(class { pending = null connection constructor(view: EditorView) { this.connection = connection this.poll() // Start polling for updates } async poll() { let updates = await connection.pullUpdates(this.pending) if (updates.length) { this.view.dispatch(receiveUpdates(this.view.state, updates)) this.pending = null } this.pending = setTimeout(this.poll.bind(this), 5000) } update(update: ViewUpdate) { if (update.docChanged) { // If local changes occurred, push them let changes = update.state.changes.changedRanges() if (changes.length) { let pushChanges = [ {version: update.startState.doc.version, changes: ChangeSet.of(changes)} ] connection.pushUpdates(pushChanges) } } } destroy() { clearTimeout(this.pending) } }, { // Provide the collab extension provide: provideExtension(version, connection) }) function provideExtension(version: number, connection: Connection) { return EditorView.domEventHandlers({ // Example: Handle a custom event to trigger a push // In a real app, this would be more sophisticated }).provide(collab.collab({baseVersion: version,... }) } ``` -------------------------------- ### Tooltip Extensions Setup Source: https://github.com/codemirror/website/blob/main/site/examples/tooltip/index.md Combines the cursor tooltip field and its base theme into a single extension for easy integration into the CodeMirror editor. ```typescript const cursorTooltip = EditorView.extend({ "&.cm-focused .cm-tooltip-cursor": { backgroundColor: "#66d9ef", color: "black" } }) const cursorTooltipExtensions = [ cursorTooltipField, cursorTooltip ] ``` -------------------------------- ### Configure CodeMirror Editor with Custom Extensions Source: https://github.com/codemirror/website/blob/main/site/examples/basic/index.md Initialize an EditorView with a detailed list of extensions for fine-grained control over editor features. This example shows how to include common functionalities like line numbers, syntax highlighting, and keymaps. ```javascript import {Extension, EditorState} from "@codemirror/state" import { EditorView, keymap, highlightSpecialChars, drawSelection, highlightActiveLine, dropCursor, rectangularSelection, crosshairCursor, lineNumbers, highlightActiveLineGutter } from "@codemirror/view" import { defaultHighlightStyle, syntaxHighlighting, indentOnInput, bracketMatching, foldGutter, foldKeymap } from "@codemirror/language" import { defaultKeymap, history, historyKeymap } from "@codemirror/commands" import { searchKeymap, highlightSelectionMatches } from "@codemirror/search" import { autocompletion, completionKeymap, closeBrackets, closeBracketsKeymap } from "@codemirror/autocomplete" import {lintKeymap} from "@codemirror/lint" const view = new EditorView({ doc: "Start document", parent: document.body, extensions: [ // A line number gutter lineNumbers(), // A gutter with code folding markers foldGutter(), // Replace non-printable characters with placeholders highlightSpecialChars(), // The undo history history(), // Replace native cursor/selection with our own drawSelection(), // Show a drop cursor when dragging over the editor dropCursor(), // Allow multiple cursors/selections EditorState.allowMultipleSelections.of(true), // Re-indent lines when typing specific input indentOnInput(), // Highlight syntax with a default style syntaxHighlighting(defaultHighlightStyle), // Highlight matching brackets near cursor bracketMatching(), // Automatically close brackets closeBrackets(), // Load the autocompletion system autocompletion(), // Allow alt-drag to select rectangular regions rectangularSelection(), // Change the cursor to a crosshair when holding alt crosshairCursor(), // Style the current line specially highlightActiveLine(), // Style the gutter for current line specially highlightActiveLineGutter(), // Highlight text that matches the selected text highlightSelectionMatches(), keymap.of([ // Closed-brackets aware backspace ...closeBracketsKeymap, // A large set of basic bindings ...defaultKeymap, // Search-related keys ...searchKeymap, // Redo/undo keys ...historyKeymap, // Code folding bindings ...foldKeymap, // Autocompletion keys ...completionKeymap, // Keys related to the linter system ...lintKeymap ]) ] }) ``` -------------------------------- ### Placeholder Text Decoration Example Source: https://github.com/codemirror/website/blob/main/site/examples/decoration/index.md Displays placeholder text when the editor is empty. This uses a mark decoration to style the placeholder. ```typescript import {Decoration, EditorView, RangeSet} from "@codemirror/view" import {StateField, EditorState, EditorSelection} from "@codemirror/state" const placeholderTheme = EditorView.baseTheme({ "& .cm-placeholder": { color: "#888", fontStyle: "italic" } }) const placeholderPlugin = StateField.define>({ create(state) { return placeholder(state) }, update(value, tr) { if (tr.docChanged) { return placeholder(tr.state) } return value.map(tr.changes) }, provide: f => EditorView.decorations.from(f) }) function placeholder(state: EditorState) { if (state.doc.toString() === "") { return Decoration.set([ Decoration.mark({ class: "cm-placeholder" }).range(0, 0) ]) } return Decoration.none } const editor = new EditorView({ state: EditorState.create({ doc: "", extensions: [placeholderPlugin, placeholderTheme] }), parent: document.body }) ``` -------------------------------- ### Basic Autocompletion Setup Source: https://github.com/codemirror/website/blob/main/site/examples/autocompletion/index.md Include the autocompletion extension in your CodeMirror configuration to enable basic input suggestions. Some language packages offer built-in support. ```typescript import {autocompletion} from "@codemirror/autocomplete" const editor = new EditorView({ state: EditorState.create({ doc: "

Hello World

", extensions: [ basicSetup, autocompletion(), html() ] }), parent: document.getElementById("editor-html") }) ``` -------------------------------- ### Custom Completion Source with Override Source: https://github.com/codemirror/website/blob/main/site/examples/autocompletion/index.md Provide a custom completion source by overriding the default behavior. This example uses `matchBefore` to find completable text and returns a list of options. ```typescript const editor = new EditorView({ state: EditorState.create({ doc: "", extensions: [ basicSetup, autocompletion({ override: [ (context: CompletionContext) => { const word = context.matchBefore(/\w*/) if (!word || (word.from == word.to && !context.explicit)) return null return { from: word.from, options: [ {label: "function", type: "keyword"}, {label: "variable", type: "variable"}, {label: "class", type: "keyword"}, {label: "interface", type: "keyword"}, {label: "enum", type: "keyword"} ] } } ] }) ] }), parent: document.getElementById("editor-override") }) ``` -------------------------------- ### Move Cursor to Document Start Source: https://github.com/codemirror/website/blob/main/site/examples/selection/index.md Dispatches a transaction to move the cursor to the beginning of the document. The `selection` property accepts a shorthand object. ```javascript view.dispatch({selection: {anchor: 0}}) ``` -------------------------------- ### Create Wired-Up Editor View Source: https://github.com/codemirror/website/blob/main/site/examples/collab/index.md Creates an EditorView instance with the necessary extensions for collaborative editing, including basic setup and the peer extension. ```typescript async function createPeer(connection: Connection) { let {version, doc} = await getDocument(connection) let state = EditorState.create({ doc, extensions: [basicSetup, peerExtension(version, connection)] }) return new EditorView({state}) } ``` -------------------------------- ### Enable Syntax Highlighting for JavaScript Source: https://github.com/codemirror/website/blob/main/site/docs/migration/index.md Add extensions for language support and syntax highlighting to the editor configuration. This example enables JavaScript highlighting and indentation using default styles. ```javascript import {syntaxHighlighting, defaultHighlightStyle} from "@codemirror/language" import {javascript} from "@codemirror/lang-javascript" // Add these extensions javascript(), syntaxHighlighting(defaultHighlightStyle), ``` -------------------------------- ### Basic RTL Editor Setup Source: https://github.com/codemirror/website/blob/main/site/examples/bidi/index.md To create a basic editor for Arabic or Hebrew text, style the editor or a parent document with `direction: rtl`. This sets the base direction for text rendering. ```html
``` -------------------------------- ### Insert Text at Document Start Source: https://github.com/codemirror/website/blob/main/site/examples/change/index.md Use the `dispatch` method with a `changes` object to insert text at a specific position, like the beginning of the document. ```javascript view.dispatch({ changes: {from: 0, insert: "#!/usr/bin/env node\n"} }) ``` -------------------------------- ### Keymaps and Commands in CodeMirror Source: https://context7.com/codemirror/website/llms.txt Define custom keybindings and commands using the `keymap` facet. This example includes a high-precedence binding for saving and a default binding for inserting a character. ```javascript import { EditorView, keymap } from "@codemirror/view" import { EditorState, Prec } from "@codemirror/state" import { defaultKeymap, history, historyKeymap, undo, redo } from "@codemirror/commands" const view = new EditorView({ extensions: [ history(), // High-precedence custom binding runs before the defaults Prec.high(keymap.of([{ key: "Mod-s", run(view) { console.log("Saved:", view.state.doc.toString()) return true } }])), keymap.of([ ...defaultKeymap, ...historyKeymap, { key: "Alt-c", run(view) { view.dispatch(view.state.replaceSelection("✓")) return true } } ]) ], parent: document.body }) // Invoke commands programmatically undo(view) redo(view) ``` -------------------------------- ### Linting with @codemirror/lint Source: https://context7.com/codemirror/website/llms.txt Implement inline diagnostics by providing a LintSource function to the linter. This example forbids the use of the `var` keyword and offers a 'Fix' action. ```javascript import { EditorView, basicSetup } from "codemirror" import { javascript } from "@codemirror/lang-javascript" import { linter, lintGutter, Diagnostic } from "@codemirror/lint" import { syntaxTree } from "@codemirror/language" // Lint source: forbid use of `var` const noVarLinter = linter(view => { const diagnostics: Diagnostic[] = [] syntaxTree(view.state).cursor().iterate(node => { if (node.name === "var") { diagnostics.push({ from: node.from, to: node.to, severity: "warning", message: "Use `let` or `const` instead of `var`.", actions: [{ name: "Fix", apply(view, from, to) { view.dispatch({ changes: { from, to, insert: "let" } }) } }] }) } }) return diagnostics }) const view = new EditorView({ doc: "var x = 1;\nlet y = 2;", extensions: [ basicSetup, javascript(), lintGutter(), noVarLinter ], parent: document.body }) // Press Ctrl-Shift-m / Cmd-Shift-m to open the diagnostic panel ``` -------------------------------- ### Decorations for Styling and Widgets Source: https://context7.com/codemirror/website/llms.txt Apply visual styling or insert DOM elements without altering the document content using Decorations. This example demonstrates underline marks and a custom widget. ```javascript import { EditorState, StateField, StateEffect, RangeSetBuilder } from "@codemirror/state" import { EditorView, Decoration, WidgetType } from "@codemirror/view" import { basicSetup } from "codemirror" import { javascript } from "@codemirror/lang-javascript" // Mark decoration: underline selected ranges const addUnderline = StateEffect.define() const clearUnderline = StateEffect.define() const underlineMark = Decoration.mark({ attributes: { style: "text-decoration: underline" } }) const underlineField = StateField.define({ create: () => Decoration.none, update(deco, tr) { deco = deco.map(tr.changes) for (const e of tr.effects) { if (e.is(addUnderline)) deco = deco.update({ add: e.value, sort: true }) else if (e.is(clearUnderline)) deco = deco.update({ filter: e.value }) } return deco }, provide: f => EditorView.decorations.from(f) }) const view = new EditorView({ doc: "Hello, CodeMirror!", extensions: [basicSetup, javascript(), underlineField], parent: document.body }) // Underline "Hello" view.dispatch({ effects: addUnderline.of([underlineMark.range(0, 5)]) }) // Widget decoration: insert a DOM element at position 5 class BannerWidget extends WidgetType { toDOM() { const el = document.createElement("span") el.textContent = "★" el.style.color = "gold" return el } eq(other) { return true } } const banner = Decoration.widget({ widget: new BannerWidget(), side: 1 }) // Provide it via a ViewPlugin or StateField in the same way ``` -------------------------------- ### Custom Autocompletion with @codemirror/autocomplete Source: https://context7.com/codemirror/website/llms.txt Provide custom suggestions to the autocompletion popup by supplying CompletionSource functions. This example offers a predefined list of array methods and built-in classes. ```javascript import { EditorView, basicSetup } from "codemirror" import { autocompletion, CompletionContext, CompletionResult } from "@codemirror/autocomplete" const myCompletions = [ { label: "forEach", type: "function", detail: "Array method", info: "Calls a function for each element" }, { label: "filter", type: "function", detail: "Array method", info: "Returns a filtered array" }, { label: "map", type: "function", detail: "Array method", info: "Maps array elements" }, { label: "Promise", type: "class", detail: "Built-in", info: "Asynchronous value holder" }, ] function myCompletionSource(context: CompletionContext): CompletionResult | null { const word = context.matchBefore(/\w+/) if (!word || (word.from === word.to && !context.explicit)) return null return { from: word.from, options: myCompletions, validFor: /^\w*$/ // reuse list while the user keeps typing word chars } } const view = new EditorView({ doc: "// Type 'fo' then Ctrl-Space", extensions: [ basicSetup, autocompletion({ override: [myCompletionSource] }) ], parent: document.body }) ``` -------------------------------- ### Configure Tab Indentation in CodeMirror Source: https://github.com/codemirror/website/blob/main/site/examples/tab/index.md This example configures CodeMirror to use the Tab key for indentation. It includes a script to load CodeMirror and the specific tab handling functionality. Ensure the 'tab.js' file contains the necessary keymap configuration. ```html
``` -------------------------------- ### Configure Indentation with indentNodeProp Source: https://github.com/codemirror/website/blob/main/site/examples/lang-package/index.md Associate indentation functions with node types using indentNodeProp. The function receives a context object and should return the desired indentation column. This example indents application nodes one unit beyond their start. ```typescript language.indentNodeProp.add({ "Application": (context) => { let base = context.base for ( let above ; above ; ) { let aboveType = context.nodeAt(above)?.type if ( aboveType && !aboveType.prop(language.indentNodeProp) && aboveType.name !== "SoftLineBreak" ) break above = context.nodeBefore(above) } let pos = context.pos if (above) pos = context.nodeStart(above) + context.line return context.column(pos) + context.unit } }) ``` -------------------------------- ### Initialize Editor with Compartments Source: https://github.com/codemirror/website/blob/main/site/examples/config/index.md Sets up an editor state with basic extensions and defines compartments for language and tab size. Use this to create a configurable editor instance. ```javascript import {basicSetup, EditorView} from "codemirror" import {EditorState, Compartment} from "@codemirror/state" import {python} from "@codemirror/lang-python" let language = new Compartment, tabSize = new Compartment let state = EditorState.create({ extensions: [ basicSetup, language.of(python()), tabSize.of(EditorState.tabSize.of(8)) ] }) let view = new EditorView({ state, parent: document.body }) ``` -------------------------------- ### Dynamic Configuration with Compartments Source: https://github.com/codemirror/website/blob/main/site/docs/migration/index.md Demonstrates how to dynamically change editor configuration, such as tab size, using Compartments and dispatching transactions. ```javascript let tabSize = new Compartment let view = new EditorView({ extensions: [ // ... tabSize.of(EditorState.tabSize.of(2)) ], // ... }) function setTabSize(size) { view.dispatch({ effects: tabSize.reconfigure(EditorState.tabSize.of(size)) }) } ``` -------------------------------- ### Word Counting Function Source: https://github.com/codemirror/website/blob/main/site/examples/panel/index.md A basic function to count words in a given string. This is a utility for the word-counting panel example. ```typescript function countWords(text: string): number { let count = 0 let inWord = false for (let i = 0; i < text.length; i++) { const isSpace = /\s/.test(text[i]) if (!isSpace && !inWord) { count++ inWord = true } else if (isSpace && inWord) { inWord = false } } return count } ``` -------------------------------- ### Underline Decoration Example Source: https://github.com/codemirror/website/blob/main/site/examples/decoration/index.md Applies an underline decoration to specific text ranges. This is a common use case for mark decorations. ```typescript import {Decoration, EditorView, RangeSet} from "@codemirror/view" import {StateField, EditorState} from "@codemirror/state" const underlineTheme = EditorView.baseTheme({ "& .cm-underline": { textDecoration: "underline" } }) const underlinePlugin = StateField.define>({ create(state) { return Decoration.none }, update(value, tr) { let decorations = value.map(tr.changes) // Add an underline to all occurrences of 'example' if (tr.docChanged) { for (let {from, to} of tr.newDoc.iterRanges(tr.changes)) { let text = tr.newDoc.sliceString(from, to) let match while ((match = /example/g.exec(text)) !== null) { let pos = from + match.index decorations = decorations.add({ from: pos, to: pos + 7, value: Decoration.mark({ class: "cm-underline" }) }) } } } return decorations }, provide: f => EditorView.decorations.from(f) }) const editor = new EditorView({ state: EditorState.create({ doc: "This is an example document with an example word.", extensions: [underlinePlugin, underlineTheme] }), parent: document.body }) ``` -------------------------------- ### Combine Help Panel Extension Source: https://github.com/codemirror/website/blob/main/site/examples/panel/index.md Bundles the state field, panel creation, and key binding into a single CodeMirror extension. This extension enables the help panel functionality. ```typescript const helpPanel = EditorView.domEventHandlers({ // ... other handlers }).provide(field => { return [ helpState, showPanel.of(createHelpPanel), keymap(helpKeymap.key, helpKeymap.run, helpKeymap.prev) ] }) ``` -------------------------------- ### Checkbox Widget Decoration Example Source: https://github.com/codemirror/website/blob/main/site/examples/decoration/index.md Inserts a checkbox widget into the editor content at specified positions. This demonstrates the use of widget decorations. ```typescript import {Decoration, EditorView, WidgetType, RangeSet} from "@codemirror/view" import {StateField, EditorState, StateEffect, Transaction} from "@codemirror/state" class CheckboxWidget extends WidgetType { constructor(readonly checked: boolean) { super() } eq(other: CheckboxWidget) { return other.checked === this.checked } toDOM() { let wrap = document.createElement("span") wrap.style.padding = "0 2px" let box = wrap.appendChild(document.createElement("input")) box.type = "checkbox" box.checked = this.checked box.onclick = () => { // This is a simplified example. In a real application, you'd want to // dispatch a transaction to update the editor state. console.log("Checkbox clicked:", box.checked) } return wrap } } const checkboxPlugin = StateField.define>({ create() { return Decoration.none }, update(value, tr) { // This is a simplified example. In a real application, you'd want to // update decorations based on the transaction's changes. return value.map(tr.changes) }, provide: f => EditorView.decorations.from(f) }) const editor = new EditorView({ state: EditorState.create({ doc: "A document with a checkbox: [ ] and another one: [ ]", extensions: [ checkboxPlugin, // Add a checkbox decoration at the start of the document EditorView.decorations.of(Decoration.widget({ widget: new CheckboxWidget(false), side: 1 // Position the widget after the text }).range(0)) ] }), parent: document.body }) ``` -------------------------------- ### Provide and Read Facet Values Source: https://github.com/codemirror/website/blob/main/site/docs/guide/index.md Demonstrates how to provide values for predefined facets like `EditorState.tabSize` and `EditorState.changeFilter`, and then read these values from the editor state. Ensure `@codemirror/state` is imported. ```javascript import {EditorState} from "@codemirror/state" let state = EditorState.create({ extensions: [ EditorState.tabSize.of(16), EditorState.changeFilter.of(() => true) ] }) console.log(state.facet(EditorState.tabSize)) // 16 console.log(state.facet(EditorState.changeFilter)) // [() => true] ``` -------------------------------- ### Run Rollup Command for Bundling Source: https://github.com/codemirror/website/blob/main/site/examples/bundle/index.md Execute the Rollup command to create a browser-compatible IIFE bundle from your main script. The node-resolve plugin is essential for handling module imports. ```shell node_modules/.bin/rollup editor.mjs -f iife -o editor.bundle.js \ -p @rollup/plugin-node-resolve ``` -------------------------------- ### Define Extension for Managing Decorations Source: https://github.com/codemirror/website/blob/main/site/docs/migration/index.md An example of a `StateField` extension that manages a set of decorations, allowing for adding and filtering marked text within the editor. ```javascript import {StateField, StateEffect} from "@codemirror/state" import {EditorView, Decoration} from "@codemirror/view" // Effects can be attached to transactions to communicate with the extension const addMarks = StateEffect.define(), filterMarks = StateEffect.define() // This value must be added to the set of extensions to enable this const markField = StateField.define({ // Start with an empty set of decorations create() { return Decoration.none }, // This is called whenever the editor updates—it computes the new set update(value, tr) { // Move the decorations to account for document changes value = value.map(tr.changes) // If this transaction adds or removes decorations, apply those changes for (let effect of tr.effects) { if (effect.is(addMarks)) value = value.update({add: effect.value, sort: true}) else if (effect.is(filterMarks)) value = value.update({filter: effect.value}) } return value }, // Indicate that this field provides a set of decorations provide: f => EditorView.decorations.from(f) }) ``` -------------------------------- ### Define a Custom Key Binding with a Command Source: https://github.com/codemirror/website/blob/main/site/docs/guide/index.md Create a custom key extension to bind a key combination to a command. The command function receives the `EditorView` and should return `true` if it executed successfully. ```javascript import {keymap} from "@codemirror/view" let myKeyExtension = keymap.of([ { key: "Alt-c", run: view => { view.dispatch(view.state.replaceSelection("?")) return true } } ]) ``` -------------------------------- ### Custom Line Number Formatting Source: https://github.com/codemirror/website/blob/main/site/examples/gutter/index.md Customizes the display of line numbers by providing a `formatNumber` function to the `lineNumbers` configuration. This example formats numbers as hexadecimal. ```typescript const hexLineNumbers = lineNumbers({ formatNumber: n => n.toString(16) }) ``` -------------------------------- ### Extension Precedence with Keymaps Source: https://github.com/codemirror/website/blob/main/site/docs/guide/index.md Demonstrates how to use `Prec.high` to set a higher precedence for an extension, ensuring it's evaluated before others with the same type. This is useful for keymaps where the order of evaluation matters. ```javascript import {keymap} from "@codemirror/view" import {EditorState, Prec} from "@codemirror/state" function dummyKeymap(tag) { return keymap.of([{ key: "Ctrl-Space", run() { console.log(tag); return true } }]) } let state = EditorState.create({extensions: [ dummyKeymap("A"), dummyKeymap("B"), Prec.high(dummyKeymap("C")) ]}) ``` -------------------------------- ### Basic Read-Only Editor Setup Source: https://github.com/codemirror/website/blob/main/site/examples/readonly/index.md Configure an editor to be completely non-interactive by setting both `readOnly` and `editable` to true. This disables typing, pasting, and browser-level focusability. ```typescript import {EditorState} from "@codemirror/state" import {EditorView, EditorSetup} from "@codemirror/view" let state = EditorState.create({ doc: "This is a read-only document.", extensions: [ EditorSetup.basicSetup, EditorView.editable.of(false), EditorState.readOnly.of(true) ] }) new EditorView({ state, parent: document.getElementById("editor_inert") as HTMLElement }) ``` -------------------------------- ### Add Autocompletion Source Source: https://github.com/codemirror/website/blob/main/site/examples/lang-package/index.md Extend the Language instance to include additional information like autocompletion sources. This example shows how to add a completion source for the language. ```typescript exampleLanguage.data.of({ autocomplete: exampleCompletions }) ``` -------------------------------- ### Editor DOM Structure Example Source: https://github.com/codemirror/website/blob/main/site/docs/guide/index.md Illustrates the typical HTML structure of a CodeMirror editor instance, including the main wrapper, scroller, content area, and line elements. ```html
Content goes here
...
``` -------------------------------- ### Enable Folding with foldNodeProp Source: https://github.com/codemirror/website/blob/main/site/examples/lang-package/index.md Use foldNodeProp to define folding behavior for node types. This example allows application nodes to be folded by hiding their content and only showing the delimiters. ```typescript language.foldNodeProp.add({ "Application": (open, close, inner) => inner.length ? { open, close, inner } : null }) ```