uiwjs / react-codemirror

CodeMirror 6 component for React. @codemirror https://uiwjs.github.io/react-codemirror/
https://uiwjs.github.io/react-codemirror/
MIT License
1.67k stars 132 forks source link

How to highlight a specific line? #475

Open interviewcrunch opened 1 year ago

interviewcrunch commented 1 year ago

Say there's a button on the page I can click which highlights the 4th line in the code editor to red. How do we configure this? And how would we un-highlight that line?

jaywcjlove commented 1 year ago

Add className Extensions

https://github.com/uiwjs/react-codemirror/blob/6968faf74121748c629ab9487d5172beec9de42e/extensions/classname/src/index.ts#L33-L50

To highlight a specific line in CodeMirror v6, you can use the decorations API provided by ViewPlugin. Here's an example of how to configure it:

import { ViewPlugin, Decoration } from "@codemirror/view";

// Get the line number you want to highlight
const lineToHighlight = 4;

// Create a decoration for that line
const lineDecoration = Decoration.line({
  attributes: {
    style: 'background-color: red;'
  },
  range: {
    anchor: lineToHighlight,
    head: lineToHighlight
  }
});

// Create a plugin to add the decoration to the view
const highlightLinePlugin = ViewPlugin.fromClass(class {
  constructor(view) {
    this.decorations = [lineDecoration];
    this.update = this.update.bind(this);
    this.decorationsPlugin = Decoration.plugin(this.decorations);
    this.decorationsPlugin(view);
  }

  update(update) {
    const oldRanges = this.decorations.map(d => d.range);
    const updatedRanges = update.state.doc.lines.map((_, i) => ({
      anchor: i,
      head: i
    }));
    const diff = Decoration.diff(oldRanges, updatedRanges);
    this.decorations = this.decorations
      .filter(d => !diff.deletions.includes(d))
      .concat(diff.additions.map(range => Decoration.line({
        attributes: {
          style: 'background-color: red;'
        },
        range
      })));
    this.decorationsPlugin.update({
      decorations: this.decorations
    });
  }
});

// To remove the decoration and un-highlight the line
highlightLinePlugin.decorations = [];
highlightLinePlugin.decorationsPlugin.update({
  decorations: []
});

<CodeMirror
  value="console.log('hello world!');"
  height="200px"
  extensions={[highlightLinePlugin]}
  onChange={onChange}
/>

This code creates a decoration object for the line you want to highlight, and adds it to a plugin that can be used with EditorView. When the plugin is added to the view, it will automatically highlight the specified line. To remove the decoration and un-highlight the line, you can simply set the decorations array of the plugin to an empty array and update the decorationsPlugin.

@interviewcrunch

KDKHD commented 11 months ago

I get Property 'plugin' does not exist on type 'typeof Decoration'.

estifanostolemariam commented 4 days ago

You can create a theme extension and set the background of your desired line like this:

import CodeMirror from '@uiw/react-codemirror';
import { EditorView } from 'codemirror';

const highLight = EditorView.theme({
    '.cm-line:nth-of-type(1)': {
      backgroundColor: 'blue'
    }
  });

export default function Page() {
    return (
    <CodeMirror
    extensions={[highLight]}
    />)
}