594 lines
45 KiB
Markdown
594 lines
45 KiB
Markdown
<p align="center">
|
|
<a href="https://uiwjs.github.io/react-codemirror/">
|
|
<img alt="react-codemirror logo" src="https://user-images.githubusercontent.com/1680273/177491470-c31a6d7e-f676-4914-a027-2fbeebfeb5b4.svg">
|
|
</a>
|
|
</p>
|
|
|
|
# react-codemirror
|
|
|
|
[](https://jaywcjlove.github.io/#/sponsor)
|
|
[](https://www.npmjs.com/package/@uiw/react-codemirror)
|
|
[](https://github.com/uiwjs/react-codemirror/actions)
|
|
[](https://uiwjs.github.io/npm-unpkg/#/pkg/@uiw/react-codemirror/file/README.md)
|
|
[](https://www.npmjs.com/package/@uiw/react-codemirror)
|
|
[](https://uiwjs.github.io/react-codemirror/coverage/lcov-report/)
|
|
[](https://gitpod.io/#https://github.com/uiwjs/react-codemirror)
|
|
|
|
CodeMirror component for React. Demo Preview: [@uiwjs.github.io/react-codemirror](https://uiwjs.github.io/react-codemirror/)
|
|
|
|
<!--rehype:style=border-left: 8px solid #ffe564;background-color: #ffe56440;padding: 12px 16px;-->
|
|
|
|
**Features:**
|
|
|
|
🚀 Quickly and easily configure the API.
|
|
🌱 Versions after `@uiw/react-codemirror@v4`<!--rehype:style=background-color: #ffe564; padding: 1px 4px;--> use [codemirror 6](https://codemirror.net/). [#88](https://github.com/uiwjs/react-codemirror/issues/88#issuecomment-914185563).
|
|
⚛️ Support the features of React Hook(requires React 16.8+).
|
|
📚 Use Typescript to write, better code hints.
|
|
🌐 The bundled version supports use directly in the browser [#267](https://github.com/uiwjs/react-codemirror/issues/267#issuecomment-1041227592).
|
|
🌎 There are better [sample previews](https://uiwjs.github.io/react-codemirror).
|
|
🎨 Support [theme](https://uiwjs.github.io/react-codemirror/#/theme/data/dracula) customization, provide theme [editor](https://uiwjs.github.io/react-codemirror/#/editor/theme).
|
|
|
|
## Install
|
|
|
|
**Not dependent on uiw.**
|
|
|
|
```bash
|
|
npm install @uiw/react-codemirror --save
|
|
```
|
|
|
|
**All Packages**
|
|
|
|
| Name | NPM Version |
|
|
| :-------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| [`@uiw/react-codemirror`](https://uiwjs.github.io/react-codemirror) | [](https://www.npmjs.com/package/@uiw/react-codemirror) [](https://www.npmjs.com/package/@uiw/react-codemirror) |
|
|
| [`react-codemirror-merge`](https://uiwjs.github.io/react-codemirror/#/merge/document) | [](https://www.npmjs.com/package/react-codemirror-merge) [](https://www.npmjs.com/package/react-codemirror-merge) |
|
|
| [`@uiw/codemirror-extensions-basic-setup`](https://uiwjs.github.io/react-codemirror/#/extensions/basic-setup) | [](https://www.npmjs.com/package/@uiw/codemirror-extensions-basic-setup) [](https://www.npmjs.com/package/@uiw/codemirror-extensions-basic-setup) |
|
|
| [`@uiw/codemirror-extensions-color`](https://uiwjs.github.io/react-codemirror/#/extensions/color) | [](https://www.npmjs.com/package/@uiw/codemirror-extensions-color) [](https://www.npmjs.com/package/@uiw/codemirror-extensions-color) |
|
|
| [`@uiw/codemirror-extensions-classname`](https://uiwjs.github.io/react-codemirror/#/extensions/classname) | [](https://www.npmjs.com/package/@uiw/codemirror-extensions-classname) [](https://www.npmjs.com/package/@uiw/codemirror-extensions-classname) |
|
|
| [`@uiw/codemirror-extensions-events`](https://uiwjs.github.io/react-codemirror/#/extensions/events) | [](https://www.npmjs.com/package/@uiw/codemirror-extensions-events) [](https://www.npmjs.com/package/@uiw/codemirror-extensions-events) |
|
|
| [`@uiw/codemirror-extensions-hyper-link`](https://uiwjs.github.io/react-codemirror/#/extensions/hyper-link) | [](https://www.npmjs.com/package/@uiw/codemirror-extensions-hyper-link) [](https://www.npmjs.com/package/@uiw/codemirror-extensions-hyper-link) |
|
|
| [`@uiw/codemirror-extensions-langs`](https://uiwjs.github.io/react-codemirror/#/extensions/languages) | [](https://www.npmjs.com/package/@uiw/codemirror-extensions-langs) [](https://www.npmjs.com/package/@uiw/codemirror-extensions-langs) |
|
|
| [`@uiw/codemirror-extensions-line-numbers-relative`](https://uiwjs.github.io/react-codemirror/#/extensions/line-numbers-relative) | [](https://www.npmjs.com/package/@uiw/codemirror-extensions-line-numbers-relative) [](https://www.npmjs.com/package/@uiw/codemirror-extensions-line-numbers-relative) |
|
|
| [`@uiw/codemirror-extensions-mentions`](https://uiwjs.github.io/react-codemirror/#/extensions/mentions) | [](https://www.npmjs.com/package/@uiw/codemirror-extensions-mentions) [](https://www.npmjs.com/package/@uiw/codemirror-extensions-mentions) |
|
|
| [`@uiw/codemirror-extensions-zebra-stripes`](https://uiwjs.github.io/react-codemirror/#/extensions/zebra-stripes) | [](https://www.npmjs.com/package/@uiw/codemirror-extensions-zebra-stripes) [](https://www.npmjs.com/package/@uiw/codemirror-extensions-zebra-stripes) |
|
|
| [`@uiw/codemirror-themes`](https://uiwjs.github.io/react-codemirror/#/theme/doc) | [](https://www.npmjs.com/package/@uiw/codemirror-themes) [](https://www.npmjs.com/package/@uiw/codemirror-themes) |
|
|
|
|
| Name | NPM Version |
|
|
| :----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
| [`@uiw/codemirror-themes-all`](https://uiwjs.github.io/react-codemirror/#/theme/all) | [](https://www.npmjs.com/package/@uiw/codemirror-themes-all) [](https://www.npmjs.com/package/@uiw/codemirror-themes-all) |
|
|
| [`@uiw/codemirror-theme-abcdef`](https://uiwjs.github.io/react-codemirror/#/theme/data/abcdef) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-abcdef) [](https://www.npmjs.com/package/@uiw/codemirror-theme-abcdef) |
|
|
| [`@uiw/codemirror-theme-abyss`](https://uiwjs.github.io/react-codemirror/#/theme/data/abyss) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-abyss) [](https://www.npmjs.com/package/@uiw/codemirror-theme-abyss) |
|
|
| [`@uiw/codemirror-theme-androidstudio`](https://uiwjs.github.io/react-codemirror/#/theme/data/androidstudio) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-androidstudio) [](https://www.npmjs.com/package/@uiw/codemirror-theme-androidstudio) |
|
|
| [`@uiw/codemirror-theme-andromeda`](https://uiwjs.github.io/react-codemirror/#/theme/data/andromeda) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-andromeda) [](https://www.npmjs.com/package/@uiw/codemirror-theme-andromeda) |
|
|
| [`@uiw/codemirror-theme-atomone`](https://uiwjs.github.io/react-codemirror/#/theme/data/atomone) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-atomone) [](https://www.npmjs.com/package/@uiw/codemirror-theme-atomone) |
|
|
| [`@uiw/codemirror-theme-aura`](https://uiwjs.github.io/react-codemirror/#/theme/data/aura) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-aura) [](https://www.npmjs.com/package/@uiw/codemirror-theme-aura) |
|
|
| [`@uiw/codemirror-theme-basic`](https://uiwjs.github.io/react-codemirror/#/theme/data/bbedit) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-basic) [](https://www.npmjs.com/package/@uiw/codemirror-theme-basic) |
|
|
| [`@uiw/codemirror-theme-bbedit`](https://uiwjs.github.io/react-codemirror/#/theme/data/bbedit) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-bbedit) [](https://www.npmjs.com/package/@uiw/codemirror-theme-bbedit) |
|
|
| [`@uiw/codemirror-theme-bespin`](https://uiwjs.github.io/react-codemirror/#/theme/data/bespin) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-bespin) [](https://www.npmjs.com/package/@uiw/codemirror-theme-bespin) |
|
|
| [`@uiw/codemirror-theme-console`](https://uiwjs.github.io/react-codemirror/#/theme/data/console) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-console) [](https://www.npmjs.com/package/@uiw/codemirror-theme-console) |
|
|
| [`@uiw/codemirror-theme-copilot`](https://uiwjs.github.io/react-codemirror/#/theme/data/copilot) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-copilot) [](https://www.npmjs.com/package/@uiw/codemirror-theme-copilot) |
|
|
| [`@uiw/codemirror-theme-duotone`](https://uiwjs.github.io/react-codemirror/#/theme/data/duotone/light) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-duotone) [](https://www.npmjs.com/package/@uiw/codemirror-theme-duotone) |
|
|
| [`@uiw/codemirror-theme-dracula`](https://uiwjs.github.io/react-codemirror/#/theme/data/dracula) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-dracula) [](https://www.npmjs.com/package/@uiw/codemirror-theme-dracula) |
|
|
| [`@uiw/codemirror-theme-darcula`](https://uiwjs.github.io/react-codemirror/#/theme/data/darcula) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-darcula) [](https://www.npmjs.com/package/@uiw/codemirror-theme-darcula) |
|
|
| [`@uiw/codemirror-theme-eclipse`](https://uiwjs.github.io/react-codemirror/#/theme/data/eclipse) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-eclipse) [](https://www.npmjs.com/package/@uiw/codemirror-theme-eclipse) |
|
|
| [`@uiw/codemirror-theme-github`](https://uiwjs.github.io/react-codemirror/#/theme/data/github) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-github) [](https://www.npmjs.com/package/@uiw/codemirror-theme-github) |
|
|
| [`@uiw/codemirror-theme-gruvbox-dark`](https://uiwjs.github.io/react-codemirror/#/theme/data/gruvbox/dark) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-gruvbox-dark) [](https://www.npmjs.com/package/@uiw/codemirror-theme-gruvbox-dark) |
|
|
| [`@uiw/codemirror-theme-kimbie`](https://uiwjs.github.io/react-codemirror/#/theme/data/kimbie/dark) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-kimbie) [](https://www.npmjs.com/package/@uiw/codemirror-theme-kimbie) |
|
|
| [`@uiw/codemirror-theme-kimbie`](https://uiwjs.github.io/react-codemirror/#/theme/data/kimbie/dark) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-kimbie) [](https://www.npmjs.com/package/@uiw/codemirror-theme-kimbie) |
|
|
| [`@uiw/codemirror-theme-material`](https://uiwjs.github.io/react-codemirror/#/theme/data/material/dark) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-material) [](https://www.npmjs.com/package/@uiw/codemirror-theme-material) |
|
|
| [`@uiw/codemirror-theme-monokai`](https://uiwjs.github.io/react-codemirror/#/theme/data/monokai) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-monokai) [](https://www.npmjs.com/package/@uiw/codemirror-theme-monokai) |
|
|
| [`@uiw/codemirror-theme-noctis-lilac`](https://uiwjs.github.io/react-codemirror/#/theme/data/noctis-lilac) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-noctis-lilac) [](https://www.npmjs.com/package/@uiw/codemirror-theme-noctis-lilac) |
|
|
| [`@uiw/codemirror-theme-nord`](https://uiwjs.github.io/react-codemirror/#/theme/data/nord) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-nord) [](https://www.npmjs.com/package/@uiw/codemirror-theme-nord) |
|
|
| [`@uiw/codemirror-theme-okaidia`](https://uiwjs.github.io/react-codemirror/#/theme/data/okaidia) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-okaidia) [](https://www.npmjs.com/package/@uiw/codemirror-theme-okaidia) |
|
|
| [`@uiw/codemirror-theme-quietlight`](https://uiwjs.github.io/react-codemirror/#/theme/data/quietlight) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-quietlight) [](https://www.npmjs.com/package/@uiw/codemirror-theme-quietlight) |
|
|
| [`@uiw/codemirror-theme-red`](https://uiwjs.github.io/react-codemirror/#/theme/data/red) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-red) [](https://www.npmjs.com/package/@uiw/codemirror-theme-red) |
|
|
| [`@uiw/codemirror-theme-solarized`](https://uiwjs.github.io/react-codemirror/#/theme/data/solarized/dark) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-solarized) [](https://www.npmjs.com/package/@uiw/codemirror-theme-solarized) |
|
|
| [`@uiw/codemirror-theme-sublime`](https://uiwjs.github.io/react-codemirror/#/theme/data/sublime) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-sublime) [](https://www.npmjs.com/package/@uiw/codemirror-theme-sublime) |
|
|
| [`@uiw/codemirror-theme-tokyo-night`](https://uiwjs.github.io/react-codemirror/#/theme/data/tokyo-night) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-tokyo-night) [](https://www.npmjs.com/package/@uiw/codemirror-theme-tokyo-night) |
|
|
| [`@uiw/codemirror-theme-tokyo-night-storm`](https://uiwjs.github.io/react-codemirror/#/theme/data/tokyo-night-storm) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-tokyo-night-storm) [](https://www.npmjs.com/package/@uiw/codemirror-theme-tokyo-night-storm) |
|
|
| [`@uiw/codemirror-theme-tokyo-night-day`](https://uiwjs.github.io/react-codemirror/#/theme/data/tokyo-night-day) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-tokyo-night-day) [](https://www.npmjs.com/package/@uiw/codemirror-theme-tokyo-night-day) |
|
|
| [`@uiw/codemirror-theme-vscode`](https://uiwjs.github.io/react-codemirror/#/theme/data/vscode) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-vscode) [](https://www.npmjs.com/package/@uiw/codemirror-theme-vscode) |
|
|
| [`@uiw/codemirror-theme-white`](https://uiwjs.github.io/react-codemirror/#/theme/data/white/light) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-white) [](https://www.npmjs.com/package/@uiw/codemirror-theme-white) |
|
|
| [`@uiw/codemirror-theme-tomorrow-night-blue`](https://uiwjs.github.io/react-codemirror/#/theme/data/tomorrow-night-blue) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-tomorrow-night-blue) [](https://www.npmjs.com/package/@uiw/codemirror-theme-tomorrow-night-blue) |
|
|
| [`@uiw/codemirror-theme-xcode`](https://uiwjs.github.io/react-codemirror/#/theme/data/xcode) | [](https://www.npmjs.com/package/@uiw/codemirror-theme-xcode) [](https://www.npmjs.com/package/@uiw/codemirror-theme-xcode) |
|
|
|
|
<!--rehype:style=width: 100%; display: inline-table;-->
|
|
|
|
## Usage
|
|
|
|
[](https://codesandbox.io/embed/react-codemirror-example-codemirror-6-slvju?fontsize=14&hidenavigation=1&theme=dark)
|
|
|
|
```jsx mdx:preview
|
|
import React from 'react';
|
|
import CodeMirror from '@uiw/react-codemirror';
|
|
import { javascript } from '@codemirror/lang-javascript';
|
|
|
|
function App() {
|
|
const [value, setValue] = React.useState("console.log('hello world!');");
|
|
const onChange = React.useCallback((val, viewUpdate) => {
|
|
console.log('val:', val);
|
|
setValue(val);
|
|
}, []);
|
|
return <CodeMirror value={value} height="200px" extensions={[javascript({ jsx: true })]} onChange={onChange} />;
|
|
}
|
|
export default App;
|
|
```
|
|
|
|
## Support Language
|
|
|
|
[](https://codesandbox.io/embed/react-codemirror-example-codemirror-6-language-rz4rh?fontsize=14&hidenavigation=1&theme=dark)
|
|
|
|
```jsx
|
|
import CodeMirror from '@uiw/react-codemirror';
|
|
import { StreamLanguage } from '@codemirror/language';
|
|
import { go } from '@codemirror/legacy-modes/mode/go';
|
|
|
|
const goLang = `package main
|
|
import "fmt"
|
|
|
|
func main() {
|
|
fmt.Println("Hello, 世界")
|
|
}`;
|
|
|
|
export default function App() {
|
|
return <CodeMirror value={goLang} height="200px" extensions={[StreamLanguage.define(go)]} />;
|
|
}
|
|
```
|
|
|
|
- ~~`@codemirror/legacy-modes/mode/cpp`~~ => [`@codemirror/lang-cpp`](https://www.npmjs.com/package/@codemirror/lang-cpp)
|
|
- ~~`@codemirror/legacy-modes/mode/html`~~ => [`@codemirror/lang-html`](https://www.npmjs.com/package/@codemirror/lang-html)
|
|
- ~~`@codemirror/legacy-modes/mode/java`~~ => [`@codemirror/lang-java`](https://www.npmjs.com/package/@codemirror/lang-java)
|
|
- ~~`@codemirror/legacy-modes/mode/javascript`~~ => [`@codemirror/lang-javascript`](https://www.npmjs.com/package/@codemirror/lang-javascript)
|
|
- ~~`@codemirror/legacy-modes/mode/json`~~ => [`@codemirror/lang-json`](https://www.npmjs.com/package/@codemirror/lang-json)
|
|
- ~~`@codemirror/legacy-modes/mode/lezer`~~ => [`@codemirror/lang-lezer`](https://www.npmjs.com/package/@codemirror/lang-lezer)
|
|
- ~~`@codemirror/legacy-modes/mode/markdown`~~ => [`@codemirror/lang-markdown`](https://www.npmjs.com/package/@codemirror/lang-markdown)
|
|
- ~~`@codemirror/legacy-modes/mode/php`~~ => [`@codemirror/lang-php`](https://www.npmjs.com/package/@codemirror/lang-php)
|
|
- ~~`@codemirror/legacy-modes/mode/python`~~ => [`@codemirror/lang-python`](https://www.npmjs.com/package/@codemirror/lang-python)
|
|
- ~~`@codemirror/legacy-modes/mode/rust`~~ => [`@codemirror/lang-rust`](https://www.npmjs.com/package/@codemirror/lang-rust)
|
|
- ~~`@codemirror/legacy-modes/mode/sql`~~ => [`@codemirror/lang-sql`](https://www.npmjs.com/package/@codemirror/lang-sql)
|
|
- ~~`@codemirror/legacy-modes/mode/xml`~~ => [`@codemirror/lang-xml`](https://www.npmjs.com/package/@codemirror/lang-xml)
|
|
- ~~`@codemirror/legacy-modes/mode/css`~~ => [`@codemirror/lang-less`](https://www.npmjs.com/package/@codemirror/lang-less)
|
|
- ~~`@codemirror/legacy-modes/mode/sass`~~ => [`@codemirror/lang-sass`](https://www.npmjs.com/package/@codemirror/lang-sass)
|
|
- ~~`@codemirror/legacy-modes/mode/clojure`~~ => [`@nextjournal/lang-clojure`](https://www.npmjs.com/package/@nextjournal/lang-clojure)
|
|
- ~~`@codemirror/legacy-modes/mode/clike`~~ => [`@replit/codemirror-lang-csharp`](https://www.npmjs.com/package/@replit/codemirror-lang-csharp)
|
|
|
|
### Markdown Example
|
|
|
|
Markdown language code is automatically highlighted.
|
|
|
|
[](https://codesandbox.io/embed/react-codemirror-example-codemirror-6-markdown-auto-languages-iudnj?fontsize=14&hidenavigation=1&theme=dark)
|
|
|
|
```jsx
|
|
import CodeMirror from '@uiw/react-codemirror';
|
|
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
|
|
import { languages } from '@codemirror/language-data';
|
|
|
|
const code = `## Title
|
|
|
|
\`\`\`jsx
|
|
function Demo() {
|
|
return <div>demo</div>
|
|
}
|
|
\`\`\`
|
|
|
|
\`\`\`bash
|
|
# Not dependent on uiw.
|
|
npm install @codemirror/lang-markdown --save
|
|
npm install @codemirror/language-data --save
|
|
\`\`\`
|
|
|
|
[weisit ulr](https://uiwjs.github.io/react-codemirror/)
|
|
|
|
\`\`\`go
|
|
package main
|
|
import "fmt"
|
|
func main() {
|
|
fmt.Println("Hello, 世界")
|
|
}
|
|
\`\`\`
|
|
`;
|
|
|
|
export default function App() {
|
|
return <CodeMirror value={code} extensions={[markdown({ base: markdownLanguage, codeLanguages: languages })]} />;
|
|
}
|
|
```
|
|
|
|
## Codemirror Merge
|
|
|
|
A component that highlights the changes between two versions of a file in a side-by-side view, highlighting added, modified, or deleted lines of code.
|
|
|
|
```bash
|
|
npm install react-codemirror-merge --save
|
|
```
|
|
|
|
```jsx
|
|
import CodeMirrorMerge from 'react-codemirror-merge';
|
|
import { EditorView } from 'codemirror';
|
|
import { EditorState } from '@codemirror/state';
|
|
|
|
const Original = CodeMirrorMerge.Original;
|
|
const Modified = CodeMirrorMerge.Modified;
|
|
let doc = `one
|
|
two
|
|
three
|
|
four
|
|
five`;
|
|
|
|
export const Example = () => {
|
|
return (
|
|
<CodeMirrorMerge>
|
|
<Original value={doc} />
|
|
<Modified
|
|
value={doc.replace(/t/g, 'T') + 'Six'}
|
|
extensions={[EditorView.editable.of(false), EditorState.readOnly.of(true)]}
|
|
/>
|
|
</CodeMirrorMerge>
|
|
);
|
|
};
|
|
```
|
|
|
|
## Support Hook
|
|
|
|
[](https://codesandbox.io/embed/react-codemirror-example-codemirror-6-hook-yr4vg?fontsize=14&hidenavigation=1&theme=dark)
|
|
|
|
```jsx
|
|
import { useEffect, useMemo, useRef } from 'react';
|
|
import { useCodeMirror } from '@uiw/react-codemirror';
|
|
import { javascript } from '@codemirror/lang-javascript';
|
|
|
|
const code = "console.log('hello world!');\n\n\n";
|
|
// Define the extensions outside the component for the best performance.
|
|
// If you need dynamic extensions, use React.useMemo to minimize reference changes
|
|
// which cause costly re-renders.
|
|
const extensions = [javascript()];
|
|
|
|
export default function App() {
|
|
const editor = useRef();
|
|
const { setContainer } = useCodeMirror({
|
|
container: editor.current,
|
|
extensions,
|
|
value: code,
|
|
});
|
|
|
|
useEffect(() => {
|
|
if (editor.current) {
|
|
setContainer(editor.current);
|
|
}
|
|
}, [editor.current]);
|
|
|
|
return <div ref={editor} />;
|
|
}
|
|
```
|
|
|
|
## Using Theme
|
|
|
|
We have created a [`theme editor`](https://uiwjs.github.io/react-codemirror/#/editor/theme) where you can define your own theme. We have also defined [some themes](https://uiwjs.github.io/react-codemirror/#/theme/data/okaidia) ourselves, which can be installed and used directly. Below is a usage example:
|
|
|
|
```jsx
|
|
import CodeMirror from '@uiw/react-codemirror';
|
|
import { javascript } from '@codemirror/lang-javascript';
|
|
import { okaidia } from '@uiw/codemirror-theme-okaidia';
|
|
|
|
const extensions = [javascript({ jsx: true })];
|
|
|
|
export default function App() {
|
|
return (
|
|
<CodeMirror
|
|
value="console.log('hello world!');"
|
|
height="200px"
|
|
theme={okaidia}
|
|
extensions={[javascript({ jsx: true })]}
|
|
/>
|
|
);
|
|
}
|
|
```
|
|
|
|
## Using custom theme
|
|
|
|
```jsx
|
|
import CodeMirror from '@uiw/react-codemirror';
|
|
import { createTheme } from '@uiw/codemirror-themes';
|
|
import { javascript } from '@codemirror/lang-javascript';
|
|
import { tags as t } from '@lezer/highlight';
|
|
|
|
const myTheme = createTheme({
|
|
theme: 'light',
|
|
settings: {
|
|
background: '#ffffff',
|
|
backgroundImage: '',
|
|
foreground: '#75baff',
|
|
caret: '#5d00ff',
|
|
selection: '#036dd626',
|
|
selectionMatch: '#036dd626',
|
|
lineHighlight: '#8a91991a',
|
|
gutterBackground: '#fff',
|
|
gutterForeground: '#8a919966',
|
|
},
|
|
styles: [
|
|
{ tag: t.comment, color: '#787b8099' },
|
|
{ tag: t.variableName, color: '#0080ff' },
|
|
{ tag: [t.string, t.special(t.brace)], color: '#5c6166' },
|
|
{ tag: t.number, color: '#5c6166' },
|
|
{ tag: t.bool, color: '#5c6166' },
|
|
{ tag: t.null, color: '#5c6166' },
|
|
{ tag: t.keyword, color: '#5c6166' },
|
|
{ tag: t.operator, color: '#5c6166' },
|
|
{ tag: t.className, color: '#5c6166' },
|
|
{ tag: t.definition(t.typeName), color: '#5c6166' },
|
|
{ tag: t.typeName, color: '#5c6166' },
|
|
{ tag: t.angleBracket, color: '#5c6166' },
|
|
{ tag: t.tagName, color: '#5c6166' },
|
|
{ tag: t.attributeName, color: '#5c6166' },
|
|
],
|
|
});
|
|
const extensions = [javascript({ jsx: true })];
|
|
|
|
export default function App() {
|
|
const onChange = React.useCallback((value, viewUpdate) => {
|
|
console.log('value:', value);
|
|
}, []);
|
|
return (
|
|
<CodeMirror
|
|
value="console.log('hello world!');"
|
|
height="200px"
|
|
theme={myTheme}
|
|
extensions={extensions}
|
|
onChange={onChange}
|
|
/>
|
|
);
|
|
}
|
|
```
|
|
|
|
## Use `initialState` to restore state from JSON-serialized representation
|
|
|
|
CodeMirror allows to serialize editor state to JSON representation with [toJSON](https://codemirror.net/docs/ref/#state.EditorState.toJSON) function for persistency or other needs. This JSON representation can be later used to recreate ReactCodeMirror component with the same internal state.
|
|
|
|
For example, this is how undo history can be saved in the local storage, so that it remains after the page reloads
|
|
|
|
```jsx
|
|
import CodeMirror from '@uiw/react-codemirror';
|
|
import { historyField } from '@codemirror/commands';
|
|
|
|
// When custom fields should be serialized, you can pass them in as an object mapping property names to fields.
|
|
// See [toJSON](https://codemirror.net/docs/ref/#state.EditorState.toJSON) documentation for more details
|
|
const stateFields = { history: historyField };
|
|
|
|
export function EditorWithInitialState() {
|
|
const serializedState = localStorage.getItem('myEditorState');
|
|
const value = localStorage.getItem('myValue') || '';
|
|
|
|
return (
|
|
<CodeMirror
|
|
value={value}
|
|
initialState={
|
|
serializedState
|
|
? {
|
|
json: JSON.parse(serializedState || ''),
|
|
fields: stateFields,
|
|
}
|
|
: undefined
|
|
}
|
|
onChange={(value, viewUpdate) => {
|
|
localStorage.setItem('myValue', value);
|
|
|
|
const state = viewUpdate.state.toJSON(stateFields);
|
|
localStorage.setItem('myEditorState', JSON.stringify(state));
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
```
|
|
|
|
## Props
|
|
|
|
<!--rehype:style=background-color: #ffe564; display: inline-block; border-bottom: 0; padding: 3px 12px;-->
|
|
|
|
- `value?: string` value of the auto created model in the editor.
|
|
- `width?: string` width of editor. Defaults to `auto`.
|
|
- `height?: string` height of editor. Defaults to `auto`.
|
|
- `theme?`: `'light'` / `'dark'` / `Extension` Defaults to `'light'`.
|
|
|
|
```ts
|
|
import React from 'react';
|
|
import { EditorState, EditorStateConfig, Extension } from '@codemirror/state';
|
|
import { EditorView, ViewUpdate } from '@codemirror/view';
|
|
export * from '@codemirror/view';
|
|
export * from '@codemirror/basic-setup';
|
|
export * from '@codemirror/state';
|
|
export interface UseCodeMirror extends ReactCodeMirrorProps {
|
|
container?: HTMLDivElement | null;
|
|
}
|
|
export declare function useCodeMirror(props: UseCodeMirror): {
|
|
state: EditorState | undefined;
|
|
setState: import('react').Dispatch<import('react').SetStateAction<EditorState | undefined>>;
|
|
view: EditorView | undefined;
|
|
setView: import('react').Dispatch<import('react').SetStateAction<EditorView | undefined>>;
|
|
container: HTMLDivElement | null | undefined;
|
|
setContainer: import('react').Dispatch<import('react').SetStateAction<HTMLDivElement | null | undefined>>;
|
|
};
|
|
export interface ReactCodeMirrorProps
|
|
extends Omit<EditorStateConfig, 'doc' | 'extensions'>,
|
|
Omit<React.HTMLAttributes<HTMLDivElement>, 'onChange' | 'placeholder'> {
|
|
/** value of the auto created model in the editor. */
|
|
value?: string;
|
|
height?: string;
|
|
minHeight?: string;
|
|
maxHeight?: string;
|
|
width?: string;
|
|
minWidth?: string;
|
|
maxWidth?: string;
|
|
/** focus on the editor. */
|
|
autoFocus?: boolean;
|
|
/** Enables a placeholder—a piece of example content to show when the editor is empty. */
|
|
placeholder?: string | HTMLElement;
|
|
/**
|
|
* `light` / `dark` / `Extension` Defaults to `light`.
|
|
* @default light
|
|
*/
|
|
theme?: 'light' | 'dark' | Extension;
|
|
/**
|
|
* Whether to optional basicSetup by default
|
|
* @default true
|
|
*/
|
|
basicSetup?: boolean | BasicSetupOptions;
|
|
/**
|
|
* This disables editing of the editor content by the user.
|
|
* @default true
|
|
*/
|
|
editable?: boolean;
|
|
/**
|
|
* This disables editing of the editor content by the user.
|
|
* @default false
|
|
*/
|
|
readOnly?: boolean;
|
|
/**
|
|
* Controls whether pressing the `Tab` key inserts a tab character and indents the text (`true`)
|
|
* or behaves according to the browser's default behavior (`false`).
|
|
* @default true
|
|
*/
|
|
indentWithTab?: boolean;
|
|
/** Fired whenever a change occurs to the document. */
|
|
onChange?(value: string, viewUpdate: ViewUpdate): void;
|
|
/** Some data on the statistics editor. */
|
|
onStatistics?(data: Statistics): void;
|
|
/** The first time the editor executes the event. */
|
|
onCreateEditor?(view: EditorView, state: EditorState): void;
|
|
/** Fired whenever any state change occurs within the editor, including non-document changes like lint results. */
|
|
onUpdate?(viewUpdate: ViewUpdate): void;
|
|
/**
|
|
* Extension values can be [provided](https://codemirror.net/6/docs/ref/#state.EditorStateConfig.extensions) when creating a state to attach various kinds of configuration and behavior information.
|
|
* They can either be built-in extension-providing objects,
|
|
* such as [state fields](https://codemirror.net/6/docs/ref/#state.StateField) or [facet providers](https://codemirror.net/6/docs/ref/#state.Facet.of),
|
|
* or objects with an extension in its `extension` property. Extensions can be nested in arrays arbitrarily deep—they will be flattened when processed.
|
|
*/
|
|
extensions?: Extension[];
|
|
/**
|
|
* If the view is going to be mounted in a shadow root or document other than the one held by the global variable document (the default), you should pass it here.
|
|
* Originally from the [config of EditorView](https://codemirror.net/6/docs/ref/#view.EditorView.constructor%5Econfig.root)
|
|
*/
|
|
root?: ShadowRoot | Document;
|
|
/**
|
|
* Create a state from its JSON representation serialized with [toJSON](https://codemirror.net/docs/ref/#state.EditorState.toJSON) function
|
|
*/
|
|
initialState?: {
|
|
json: any;
|
|
fields?: Record<'string', StateField<any>>;
|
|
};
|
|
}
|
|
export interface ReactCodeMirrorRef {
|
|
editor?: HTMLDivElement | null;
|
|
state?: EditorState;
|
|
view?: EditorView;
|
|
}
|
|
declare const ReactCodeMirror: React.ForwardRefExoticComponent<
|
|
ReactCodeMirrorProps & React.RefAttributes<ReactCodeMirrorRef>
|
|
>;
|
|
export default ReactCodeMirror;
|
|
export interface BasicSetupOptions {
|
|
lineNumbers?: boolean;
|
|
highlightActiveLineGutter?: boolean;
|
|
highlightSpecialChars?: boolean;
|
|
history?: boolean;
|
|
foldGutter?: boolean;
|
|
drawSelection?: boolean;
|
|
dropCursor?: boolean;
|
|
allowMultipleSelections?: boolean;
|
|
indentOnInput?: boolean;
|
|
syntaxHighlighting?: boolean;
|
|
bracketMatching?: boolean;
|
|
closeBrackets?: boolean;
|
|
autocompletion?: boolean;
|
|
rectangularSelection?: boolean;
|
|
crosshairCursor?: boolean;
|
|
highlightActiveLine?: boolean;
|
|
highlightSelectionMatches?: boolean;
|
|
closeBracketsKeymap?: boolean;
|
|
defaultKeymap?: boolean;
|
|
searchKeymap?: boolean;
|
|
historyKeymap?: boolean;
|
|
foldKeymap?: boolean;
|
|
completionKeymap?: boolean;
|
|
lintKeymap?: boolean;
|
|
}
|
|
```
|
|
|
|
```ts
|
|
import { EditorSelection, SelectionRange } from '@codemirror/state';
|
|
import { ViewUpdate } from '@codemirror/view';
|
|
export interface Statistics {
|
|
/** Get the number of lines in the editor. */
|
|
lineCount: number;
|
|
/** total length of the document */
|
|
length: number;
|
|
/** Get the proper [line-break](https://codemirror.net/docs/ref/#state.EditorState^lineSeparator) string for this state. */
|
|
lineBreak: string;
|
|
/** Returns true when the editor is [configured](https://codemirror.net/6/docs/ref/#state.EditorState^readOnly) to be read-only. */
|
|
readOnly: boolean;
|
|
/** The size (in columns) of a tab in the document, determined by the [`tabSize`](https://codemirror.net/6/docs/ref/#state.EditorState^tabSize) facet. */
|
|
tabSize: number;
|
|
/** Cursor Position */
|
|
selection: EditorSelection;
|
|
/** Make sure the selection only has one range. */
|
|
selectionAsSingle: SelectionRange;
|
|
/** Retrieves a list of all current selections. */
|
|
ranges: readonly SelectionRange[];
|
|
/** Get the currently selected code. */
|
|
selectionCode: string;
|
|
/**
|
|
* The length of the given array should be the same as the number of active selections.
|
|
* Replaces the content of the selections with the strings in the array.
|
|
*/
|
|
selections: string[];
|
|
/** Return true if any text is selected. */
|
|
selectedText: boolean;
|
|
}
|
|
export declare const getStatistics: (view: ViewUpdate) => Statistics;
|
|
```
|
|
|
|
## Development
|
|
|
|
1. Install dependencies
|
|
|
|
```bash
|
|
$ npm install # Installation dependencies
|
|
$ npm run build # Compile all package
|
|
```
|
|
|
|
2. Development `@uiw/react-codemirror` package:
|
|
|
|
```bash
|
|
$ cd core
|
|
# listen to the component compile and output the .js file
|
|
# listen for compilation output type .d.ts file
|
|
$ npm run watch # Monitor the compiled package `@uiw/react-codemirror`
|
|
```
|
|
|
|
3. Launch documentation site
|
|
|
|
```bash
|
|
npm run start
|
|
```
|
|
|
|
## Related
|
|
|
|
- [@uiw/react-textarea-code-editor](https://github.com/uiwjs/react-textarea-code-editor): A simple code editor with syntax highlighting.
|
|
- [@uiw/react-md-editor](https://github.com/uiwjs/react-md-editor): A simple markdown editor with preview, implemented with React.js and TypeScript.
|
|
- [@uiw/react-monacoeditor](https://github.com/jaywcjlove/react-monacoeditor): Monaco Editor component for React.
|
|
- [@uiw/react-markdown-editor](https://github.com/uiwjs/react-markdown-editor): A markdown editor with preview, implemented with React.js and TypeScript.
|
|
- [@uiw/react-markdown-preview](https://github.com/uiwjs/react-markdown-preview): React component preview markdown text in web browser.
|
|
- [Online JSON Viewer](https://github.com/uiwjs/json-viewer) Online JSON Viewer, JSON Beautifier to beautify and tree view of JSON data - It works as JSON Pretty Print to pretty print JSON data.
|
|
|
|
## Contributors
|
|
|
|
As always, thanks to our amazing contributors!
|
|
|
|
<a href="https://github.com/uiwjs/react-codemirror/graphs/contributors">
|
|
<img src="https://uiwjs.github.io/react-codemirror/CONTRIBUTORS.svg" />
|
|
</a>
|
|
|
|
Made with [contributors](https://github.com/jaywcjlove/github-action-contributors).
|
|
|
|
## License
|
|
|
|
Licensed under the MIT License.
|