{"id":28749040,"url":"https://github.com/mukeshsoni/deepnotes-editor","last_synced_at":"2025-06-16T19:32:49.160Z","repository":{"id":43032452,"uuid":"287890234","full_name":"mukeshsoni/deepnotes-editor","owner":"mukeshsoni","description":"workflowy like editor built with draft-js. Used in https://deepnotes.in.","archived":false,"fork":false,"pushed_at":"2021-11-03T10:42:11.000Z","size":1645,"stargazers_count":132,"open_issues_count":1,"forks_count":14,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-05-31T09:17:17.128Z","etag":null,"topics":["draftjs","editor","reactjs","reactjs-components","rich-text-editor","workflowy"],"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/mukeshsoni.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}},"created_at":"2020-08-16T06:49:35.000Z","updated_at":"2025-05-17T07:18:35.000Z","dependencies_parsed_at":"2022-09-08T21:11:23.014Z","dependency_job_id":null,"html_url":"https://github.com/mukeshsoni/deepnotes-editor","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/mukeshsoni/deepnotes-editor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mukeshsoni%2Fdeepnotes-editor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mukeshsoni%2Fdeepnotes-editor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mukeshsoni%2Fdeepnotes-editor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mukeshsoni%2Fdeepnotes-editor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mukeshsoni","download_url":"https://codeload.github.com/mukeshsoni/deepnotes-editor/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mukeshsoni%2Fdeepnotes-editor/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260223995,"owners_count":22977327,"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":["draftjs","editor","reactjs","reactjs-components","rich-text-editor","workflowy"],"created_at":"2025-06-16T19:32:01.788Z","updated_at":"2025-06-16T19:32:49.134Z","avatar_url":"https://github.com/mukeshsoni.png","language":"TypeScript","readme":"`deepnotes-editor` is the editor used in [deepnotes.in](https://deepnotes.in).\nIt's a clone of the [workflowy.com](https://workflowy.com) editor written in\n[draft-js](https://draftjs.org/). `deepnotes-editor` can be used as a react\ncomponent.\n\nHere's a gif of how it works - \n\n![deepnotes editor demo](deepnotes-editor-demo.gif)\n\nWhy `deepnotes-editor`?\n\n- Supports infinitely nested lists\n- Every list item can be zoomed into. Therefore every list item can be thought\n  of as a document in itself\n- Nested lists can be collapsed to reduce clutter\n- Powerful keyboard shortcuts so that you don't have to remove your hands from\n  the keyboard when navigating the documents\n- Supports hashtags, automatic link detection and inline code block formatting\n- Bookmarking of any list item\n\n### Desktop only\n`deepnotes-editor` doesn't work well on mobile browsers. That's because\n`draft-js` itself does not work well on mobile browsers.\n\nUsage -\n\nInstall `deepnoter-editor`\n\n```shell\nnpm install deepnotes-editor # or yarn add deepnotes-editor\n```\n\nUse anywhere in your react codebase\n\n```\nimport Editor from 'deepnotes-editor';\n\n// it will look like it's not working without the css\nimport 'deepnotes-editor/dist/deepnotes-editor.css';\n\n// inside your dom heirarchy somewhere\n\u003cdiv\u003e\n  \u003cEditor onChange={editorState =\u003e saveToDb(editorState)} /\u003e\n\u003c/div\u003e\n```\n\n## How to save editor state?\nYou can use draft-js utilities to convert the `EditorState` returned from\n`onChange` prop. The prop returned is an [immutable-js](https://immutable-js.github.io/immutable-js/) value.\n\n\n```\nimport { convertToRaw } from 'draft-js'\n\nfunction saveToDb(editorState) {\n  const contentState = JSON.stringify(convertToRaw(contentState)),\n\n  saveToDbOrLocalStorage(contentState);\n}\n```\n\n## How to get back editor state from the saved content state?\nYou can use `convertFromRaw` utility from `draft-js` to convert the content\nstate json back to immutable-js `EditorState`. You have to use the\n`createDecorators` function which comes with `deepnotes-editor` so that the\nhashtags, links and code are highlighted properly.\n\n\n```\nimport DeepnotesEditor, { createDecorators} from 'deepnotes-editor';\nimport 'deepnotes-editor/dist/deepnotes-editor.css';\n\nconst contentState = convertFromRaw(JSON.parse(backupContent));\nconst editorState = EditorState.createWithContent(\n  contentState,\n  createDecorators()\n);\n\n// inside your render function\nreturn \u003cdiv\u003e\n  \u003cDeepnotesEditor\n    initialEditorState={editorState}\n    onChange={(changedEditorState) =\u003e saveToDb(changedEditorState)}}\n  /\u003e\n\u003c/div\u003e\n```\n\n### Customization or configuration\nThese are the props `deepnotes-editor` accepts\n\n#### initialEditorState\nThis prop can be used to initialize the editor with some saved state. The state\nis of the type `EditorState` from `draft-js`. See `draft-js` documentation for\nmore details - https://draftjs.org/docs/quickstart-api-basics#controlling-rich-text\n\nP. S. - This component is not a controlled component. The state of the editor is\nmaintained inside the component. If you change the zoomedInItemId, the editor\nwill zoom into that item. But changing the initialEditorState between renders\nwill not change the content of the editor to the new value of\ninitialEditorState.\n\n#### initialZoomedInItemId\nIf we want the editor to open zoomed in on some item. Very useful if you map the\nzoomedin items with urls and then if a user pastes or goes to a particular item\ndirectly, the editor can be also zoomed in to that item.\n\n#### searchText\nIf you want to filter the items by some text\n\n#### onChange\n`onChange` is a function which is called with the new `EditorState` on every\nchange. This can be used to save the new `EditorState` to local storage or to\nsome persistent database.\n\n#### onRootChange\nThis prop is called if the user zooms into a particular item. Please checkout\nworkflowy.com to understand what zoom in means.\n\n#### onBookmarkClick\nIf a user wants to bookmarks a particular zoomed in item. This can be used to\nbuild a bookmarking feature where the user can zoom to any of the bookmarked\nitem.\n\n### withToolbar\nIf you don't want the menu/toolbar which shows up above the editor, you can set\nwithToolbar to false.\n\n## Development\nInstall dependencies and start the build for the Editor component\n\n```bash\nnpm install # or yarn install\nnpm start # or yarn start\n```\n\nThis builds to `/dist` and runs the project in watch mode so any edits you save inside `src` causes a rebuild to `/dist`.\n\nThis does not start a server. It only watches your files and builds and puts them in dist folder when any file in src directory changes. To view the editor in action, you need to ru na server inside the example directory.\n\nThen run the example inside another:\n\n```bash\ncd example\nnpm i # or yarn to install dependencies\nnpm start # or yarn start\n```\n\nThe example is served on http://localhost:1234. If that port is busy, parcel might try starting the server on some other port.\n\nThe default example imports and live reloads whatever is in `/dist`, so if you are seeing an out of date component, make sure TSDX is running in watch mode like we recommend above. **No symlinking required**, [we use Parcel's aliasing](https://github.com/palmerhq/tsdx/pull/88/files).\n\nTo do a one-off build, use `npm run build` or `yarn build`.\n\nTo run tests, use `npm test` or `yarn test`.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmukeshsoni%2Fdeepnotes-editor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmukeshsoni%2Fdeepnotes-editor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmukeshsoni%2Fdeepnotes-editor/lists"}