{"id":13532822,"url":"https://github.com/riccardoperra/solid-codemirror","last_synced_at":"2025-03-16T15:33:29.929Z","repository":{"id":41244027,"uuid":"455813384","full_name":"riccardoperra/solid-codemirror","owner":"riccardoperra","description":"A library of SolidJS primitives to build code editors using CodeMirror 6 @codemirror ","archived":false,"fork":false,"pushed_at":"2023-12-10T07:27:45.000Z","size":831,"stargazers_count":62,"open_issues_count":2,"forks_count":6,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-03-10T18:03:00.471Z","etag":null,"topics":["codemirror","editor","ide","primitives","solid","solid-codemirror","solidjs","typescript"],"latest_commit_sha":null,"homepage":"https://www.npmjs.com/package/solid-codemirror","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/riccardoperra.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2022-02-05T08:14:35.000Z","updated_at":"2025-02-04T17:13:02.000Z","dependencies_parsed_at":"2024-01-14T02:03:21.148Z","dependency_job_id":null,"html_url":"https://github.com/riccardoperra/solid-codemirror","commit_stats":{"total_commits":94,"total_committers":5,"mean_commits":18.8,"dds":"0.17021276595744683","last_synced_commit":"1c8a5d4a3bf1651e344e5d6dce0e541b0990ce39"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riccardoperra%2Fsolid-codemirror","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riccardoperra%2Fsolid-codemirror/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riccardoperra%2Fsolid-codemirror/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/riccardoperra%2Fsolid-codemirror/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/riccardoperra","download_url":"https://codeload.github.com/riccardoperra/solid-codemirror/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243822310,"owners_count":20353498,"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","editor","ide","primitives","solid","solid-codemirror","solidjs","typescript"],"created_at":"2024-08-01T07:01:14.018Z","updated_at":"2025-03-16T15:33:29.617Z","avatar_url":"https://github.com/riccardoperra.png","language":"TypeScript","funding_links":[],"categories":["📦 Components \u0026 Libraries"],"sub_categories":["Frameworks \u0026 Component Libraries"],"readme":"\u003cp\u003e\n  \u003cimg width=\"100%\" src=\"https://assets.solidjs.com/banner?type=solid-codemirror\u0026project=solid-codemirror\" alt=\"solid-codemirror\"\u003e\n\u003c/p\u003e\n\n# solid-codemirror\n\n[![pnpm](https://img.shields.io/badge/maintained%20with-pnpm-cc00ff.svg?style=for-the-badge\u0026logo=pnpm)](https://pnpm.io/)\n[![NPM Downloads](https://img.shields.io/npm/dw/solid-codemirror?style=for-the-badge)](https://www.npmjs.com/package/solid-codemirror)\n[![npm version](https://img.shields.io/npm/v/solid-codemirror?style=for-the-badge)](https://www.npmjs.com/package/solid-codemirror)\n[![license](https://img.shields.io/npm/l/solid-codemirror?style=for-the-badge)](https://github.com/riccardoperra/solid-codemirror/blob/main/LICENSE)\n\n**solid-codemirror** provides a set of utilities to make **CodeMirror6** integration easier\nfor [SolidJS](https://github.com/solidjs/solid).\n\nThis library was initially born to be the entry of the SolidJS hackathon, but has become the core editor\nof [CodeImage](https://github.com/riccardoperra/codeimage).\n\n## Installation\n\n```bash\n# pnpm\n\u003e pnpm add solid-codemirror\n# or yarn\n\u003e yarn add solid-codemirror\n# or npm\n\u003e npm i solid-codemirror\n```\n\n\u003e **Note** This library depends on [@codemirror/state](https://github.com/codemirror/state)\n\u003e and [@codemirror/view](https://github.com/codemirror/state) v6.0.0. These libraries are flagged as **\n\u003e peerDependencies**.\n\u003e It's recommended to manually install both of them to have more control and flexibility for implementation\n\n### CodeMirror packages error fix\n\n\u003e **Warning** You may encounter this error using Vite\n\n```bash\nError: Unrecognized extension value in extension set ([object Object]). \nThis sometimes happens because multipleinstances of @codemirror/state are loaded, \nbreaking instanceof checks.\n```\n\nIf @codemirror/state and @codemirror/view are not working even if their version dont't mismatch, you can try to add the\nfollowing to your `vite.config.{js,ts}` file:\n\n```typescript \nexport default defineConfig({\n  // Your configuration\n  optimizeDeps: {\n    // Add both @codemirror/state and @codemirror/view to included deps to optimize\n    include: ['@codemirror/state', '@codemirror/view'],\n  }\n})\n```\n\n## Versions\n\n| solid-codemirror | @codemirror/state | @codemirror/view | solid-js |\n|------------------|-------------------|------------------|----------|\n| \\\u003e=1.3.0         | ^6.2.0            | ^6.12.0          | ^1.7.0   |\n| \\\u003e=1 \u003c 1.3.0     | ^6.0.0            | ^6.0.0           | ^1.6.0   |\n\n## Basic Usage\n\nFirst, we need to create a new CodeMirror instance through the `createCodeMirror` function. Next, the given `ref`\nobject must be attached to a DOM Element in order to initialize the `EditorView` instance with his own `EditorState`.\n\n```tsx\nimport { createCodeMirror } from \"solid-codemirror\";\nimport { createSignal, onMount } from \"solid-js\";\n\nexport const App = () =\u003e {\n  const { editorView, ref: editorRef } = createCodeMirror({\n    /**\n     * The initial value of the editor\n     */\n    value: \"console.log('hello world!')\",\n    /**\n     * Fired whenever the editor code value changes.\n     */\n    onValueChange: (value) =\u003e console.log(\"value changed\", value),\n    /**\n     * Fired whenever a change occurs to the document, every time the view updates.\n     */\n    onModelViewUpdate: (modelView) =\u003e console.log(\"modelView updated\", modelView),\n    /**\n     * Fired whenever a transaction has been dispatched to the view.\n     * Used to add external behavior to the transaction [dispatch function](https://codemirror.net/6/docs/ref/#view.EditorView.dispatch) for this editor view, which is the way updates get routed to the view\n     */\n    onTransactionDispatched: (tr: Transaction, view: EditorView) =\u003e console.log(\"Transaction\", tr)\n  });\n\n  return \u003cdiv ref={editorRef} /\u003e;\n};\n```\n\nThe `createCodeMirror` function is the main function of `solid-codemirror` to start creating your editor. It exposes the\nfollowing properties:\n\n| Property          | Description                                                                                                                                                                                      |\n|-------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| `ref`             | The HTMLElement object which will be attached to the EditorView instance                                                                                                                         |\n| `editorView`      | The current EditorView instance of CodeMirror. Will be `null` as default, and it will be valued when the given `ref` is mounted in the DOM                                                       |\n| `createExtension` | A function to create a new extension for CodeMirror using compartments. It's a shortand for the `createCompartmentExtension` helper which automatically attaches the right `EditorView` instance |\n\n## Modularity\n\n\u003e https://codemirror.net/docs/guide/ \\\n\u003e CodeMirror is set up as a collection of separate modules that, together, provide a full-featured text and code editor.\n\u003e On the bright side, this means that you can pick and choose which features you need, and even replace core\n\u003e functionality\n\u003e with a custom implementation if you need to. On the less bright side, this means that setting up an editor requires\n\u003e you\n\u003e to put together a bunch of pieces.\n\nAs the official documentation says, CodeMirror6 is modular.\n\nsolid-codemirror **will not be a replacement** for all the modules of\nCodeMirror6, but will try to provide only the primitives necessary to integrate them in SolidJS.\n\nEach extension which you need to develop your editor **must be** installed individually and integrated individually.\n\n## Extensions\n\n### Control editor focus and observe `focused` state changes\n\n```ts\nimport { createCodeMirror, createEditorFocus } from 'solid-codemirror';\nimport { createSignal } from 'solid-js';\n\nconst { editorView } = createCodeMirror();\nconst [readOnly, setReadOnly] = createSignal(true);\nconst {\n  focused,\n  setFocused\n} = createEditorFocus(editorView, (focused) =\u003e console.log('focus changed', focused));\n\n// Focus\nsetFocused(true);\n// Blur\nsetFocused(false);\n```\n\n### Update editor readonly state\n\nAfter the CodeMirror editor is mounted, you can update its readonly state using the\n`createReadonlyEditor` function that accept the editor view and the readOnly accessor.\n\u003e **Note** Updating the accessor, the editor readOnly state will be updated automatically;\n\n```typescript jsx\nimport { createCodeMirror, createEditorReadonly } from 'solid-codemirror';\nimport { createSignal } from 'solid-js';\n\nfunction App() {\n  const { ref, editorView } = createCodeMirror();\n  const [readOnly, setReadOnly] = createSignal(true);\n  createEditorReadonly(editorView, readonly);\n\n  return \u003cdiv ref={ref} /\u003e\n}\n```\n\n### Control editor code using signals\n\nAfter CodeMirror editor is mounted, you can control the code state using the\n`createEditorControlledValue`.\n\n\u003e **Note** The value of the editor is already memoized\n\n```typescript jsx\nimport { createCodeMirror, createEditorControlledValue } from 'solid-codemirror';\nimport { createSignal } from 'solid-js';\n\nfunction App() {\n  const [code, setCode] = createSignal(\"console.log('hello world!')\");\n  const { ref, editorView } = createCodeMirror({ onValueChange: setCode });\n  createEditorControlledValue(editorView, code);\n\n  // Update code after 2.5s\n  setTimeout(() =\u003e {\n    setCode(\"console.log('updated!')\");\n  }, 2500);\n\n  return \u003cdiv ref={ref} /\u003e\n}\n```\n\n### Handle custom extensions\n\nAfter CodeMirror editor is mounted, you can handle custom extensions thanks to the\n`createExtension` function. It both accept an `Extension` or `Accessor\u003cExtension | undefined\u003e` then\nit will be automatically reconfigured when the extension changes. Otherwise, you can manually reconfigure them using\nthe returned `reconfigure` function.\n\nFor more details, see the official documentation about [compartments](https://codemirror.net/examples/reconfigure).\n\n```typescript jsx\nimport { createCodeMirror } from 'solid-codemirror';\nimport { createSignal } from 'solid-js';\nimport { EditorView, lineNumbers } from '@codemirror/view';\n\nfunction App() {\n  const [code, setCode] = createSignal(\"console.log('hello world!')\");\n  const [showLineNumber, setShowLineNumber] = createSignal(true);\n  const { ref, createExtension } = createCodeMirror({ onValueChange: setCode });\n\n  const theme = EditorView.theme({\n    '\u0026': {\n      background: 'red'\n    }\n  });\n\n  // Add a static custom theme\n  createExtension(theme);\n\n  // Toggle extension\n  createExtension(() =\u003e showLineNumber() ? lineNumbers() : []);\n\n  // Remove line numbers after 2.5s\n  setTimeout(() =\u003e {\n    setShowLineNumber(false);\n  }, 2500);\n\n  return \u003cdiv ref={ref} /\u003e\n}\n```\n\n### Lazy loading extensions\n\nSometimes you may need to better split your custom extensions in order to reduce the initial bundle size.\nThis is the case where you need to use dynamic imports in order to resolve the module in lazy loading.\n\n```tsx\n// ✅ 1. Remove the static import\n// import { largeExtension } from './large-extension';\nimport { createLazyCompartmentExtension } from './createLazyCompartmentExtension';\nimport { Show } from 'solid-js';\n\nfunction App() {\n  const [code, setCode] = createSignal(\"console.log('hello world!')\");\n  const { ref, createExtension } = createCodeMirror({ onValueChange: setCode });\n\n  // ✅ 2. Call the helper providing a Promise\u003cExtension\u003e\n  // The extension will be configured only after the Promise resolves\n  const largeExt = createLazyCompartmentExtension(\n    () =\u003e import('./large-extension').then(res =\u003e res.largeExtension)\n  );\n\n  return (\n    \u003cdiv\u003e\n      \u003cdiv ref={ref} /\u003e\n      {/*✅ 3. You can read the pending state of the Promise*/}\n      \u003cShow when={largeExt.loading}\u003e\n        Loading...\n      \u003c/Show\u003e\n    \u003c/div\u003e\n  )\n}\n```\n\n## Demo\n\n// WIP\n\nYou can also view an advanced implementation of `solid-codemirror`\nthrough [CodeImage](https://github.com/riccardoperra/codeimage/blob/main/apps/codeimage/src/components/CustomEditor/CustomEditor.tsx)\nimplementation\n\n## Author\n\n- [Riccardo Perra](https://github.com/riccardoperra/solid-codemirror)\n\n## License\n\nLicensed under the [MIT License](./LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Friccardoperra%2Fsolid-codemirror","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Friccardoperra%2Fsolid-codemirror","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Friccardoperra%2Fsolid-codemirror/lists"}