{"id":15646311,"url":"https://github.com/sachinraja/rodemirror","last_synced_at":"2025-04-05T13:05:01.773Z","repository":{"id":39660945,"uuid":"381781405","full_name":"sachinraja/rodemirror","owner":"sachinraja","description":"React component for CodeMirror 6","archived":false,"fork":false,"pushed_at":"2025-02-07T17:30:20.000Z","size":3635,"stargazers_count":49,"open_issues_count":9,"forks_count":5,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-29T12:03:58.766Z","etag":null,"topics":["codemirror","codemirror-6","codemirror-next","codemirror6","editor","react"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/sachinraja.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"sachinraja"}},"created_at":"2021-06-30T17:22:50.000Z","updated_at":"2024-07-16T15:59:44.000Z","dependencies_parsed_at":"2024-10-03T12:14:50.313Z","dependency_job_id":"c43c2257-5155-482a-9f24-996e70f4f2b8","html_url":"https://github.com/sachinraja/rodemirror","commit_stats":{"total_commits":261,"total_committers":6,"mean_commits":43.5,"dds":"0.46743295019157083","last_synced_commit":"2990944e1e89ec2a111a728d4062f9d7ca6c32af"},"previous_names":[],"tags_count":17,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sachinraja%2Frodemirror","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sachinraja%2Frodemirror/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sachinraja%2Frodemirror/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sachinraja%2Frodemirror/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sachinraja","download_url":"https://codeload.github.com/sachinraja/rodemirror/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247339154,"owners_count":20923014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["codemirror","codemirror-6","codemirror-next","codemirror6","editor","react"],"created_at":"2024-10-03T12:12:23.739Z","updated_at":"2025-04-05T13:05:01.748Z","avatar_url":"https://github.com/sachinraja.png","language":"TypeScript","funding_links":["https://github.com/sponsors/sachinraja"],"categories":[],"sub_categories":[],"readme":"# rodemirror\n\nReact component for [CodeMirror 6](https://codemirror.net/6/)\n\n## Features\n\n- Lightweight, 829B minified + gzipped\n- Simple, wraps CodeMirror's view and state and gets out of your way\n- Efficient, only renders when necessary and uses [`StateEffect`](https://codemirror.net/6/docs/ref/#state.StateEffect) to update the editor state on prop changes. The view and state are **never** recreated.\n\n## Installation\n\n```shell\nnpm install rodemirror @codemirror/state @codemirror/view\n```\n\n## Usage\n\nUse the `CodeMirror` component:\n\n```tsx\nimport { basicSetup } from 'codemirror'\nimport { javascript } from '@codemirror/lang-javascript'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { useMemo } from 'react'\nimport CodeMirror from 'rodemirror'\n\nconst Editor = () =\u003e {\n  const extensions = useMemo(() =\u003e [basicSetup, oneDark, javascript()], [])\n\n  return \u003cCodeMirror extensions={extensions} /\u003e\n}\n```\n\nThe `useMemo` is so that the extensions are not recreated each time, which would cause unnecessary editor transactions. You'll want to do the same with the `selection` prop.\n\n### Uncontrolled\n\nCreate an uncontrolled component for reading values.\n\n```tsx\nimport { basicSetup } from 'codemirror'\nimport { javascript } from '@codemirror/lang-javascript'\nimport { Extension } from '@codemirror/state'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { useMemo, useState } from 'react'\nimport CodeMirror from 'rodemirror'\n\nconst Editor = () =\u003e {\n  const extensions = useMemo\u003cExtension[]\u003e(\n    () =\u003e [basicSetup, oneDark, javascript()],\n    [],\n  )\n\n  const defaultValue = \"console.log('Hello world!')\"\n  // remove if you do not need the value\n  const [value, setValue] = useState(defaultValue)\n\n  return (\n    \u003cCodeMirror\n      value={defaultValue}\n      onUpdate={(v) =\u003e {\n        if (v.docChanged) {\n          setValue(v.state.doc.toString())\n        }\n      }}\n      extensions={extensions}\n    /\u003e\n  )\n}\n```\n\n### Controlled/Separate Reading and Writing\n\nA truly controlled value is not recommended as you will be overwriting the entire document on each input and the editor will become very slow. This also does not work with features such as autocomplete. If you must pass in a controlled value, you can separate the reading and writing values and only update when necessary:\n\n```tsx\nimport { useMemo, useState, useEffect } from 'react'\nimport CodeMirror from 'rodemirror'\nimport type { Extension } from '@codemirror/state'\nimport { basicSetup } from 'codemirror'\nimport { oneDark } from '@codemirror/theme-one-dark'\nimport { javascript } from '@codemirror/lang-javascript'\n\nconst Editor = ({ shouldAddLogOnChange }) =\u003e {\n  const Editor = ({\n    shouldAddLogOnChange,\n  }: {\n    shouldAddLogOnChange: boolean\n  }) =\u003e {\n    const extensions = useMemo\u003cExtension[]\u003e(\n      () =\u003e [basicSetup, oneDark, javascript()],\n      []\n    )\n\n    const defaultValue = \"console.log('Hello world!')\"\n    const [readValue, setReadValue] = useState(defaultValue)\n    const [writeValue, setWriteValue] = useState(defaultValue)\n\n    // example\n    useEffect(() =\u003e {\n      setWriteValue(`${readValue}\\nconsole.log('hello world')`)\n    }, [shouldAddLogOnChange])\n\n    return (\n      \u003cCodeMirror\n        value={writeValue}\n        onUpdate={(v) =\u003e {\n          if (v.docChanged) {\n            setReadValue(v.state.doc.toString())\n          }\n        }}\n        extensions={extensions}\n      /\u003e\n    )\n  }\n```\n\n### [EditorView](https://codemirror.net/6/docs/ref/#view.EditorView) and [EditorState](https://codemirror.net/6/docs/ref/#state.EditorState) (Complex Use Cases)\n\nUnless you are performing complex actions, you likely do not need this. You can use callbacks to keep `EditorView` and `EditorState`. You can keep the `EditorView` in a `useState` like so:\n\n```tsx\nimport { EditorView } from '@codemirror/view'\n\nconst Editor = () =\u003e {\n  const extensions = useMemo(() =\u003e [basicSetup, oneDark, javascript()], [])\n\n  const [editorView, setEditorView] = useState\u003cEditorView | null\u003e(null)\n\n  return (\n    \u003cCodeMirror\n      extensions={extensions}\n      onEditorViewChange={(editorView) =\u003e setEditorView(editorView)}\n    /\u003e\n  )\n}\n```\n\nThe same applies to `EditorState`, though it can also be accessed from `EditorView.state`.\n\n## Examples\n\nSee the [examples](https://github.com/sachinraja/rodemirror/tree/main/examples) for how the editor can be used.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsachinraja%2Frodemirror","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsachinraja%2Frodemirror","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsachinraja%2Frodemirror/lists"}