{"id":13632718,"url":"https://github.com/outline/rich-markdown-editor","last_synced_at":"2025-09-29T00:32:19.433Z","repository":{"id":43405262,"uuid":"122811745","full_name":"outline/rich-markdown-editor","owner":"outline","description":"The open source React and Prosemirror based markdown editor that powers Outline. Want to try it out? Create an account:","archived":true,"fork":false,"pushed_at":"2022-01-17T09:00:09.000Z","size":3418,"stargazers_count":2922,"open_issues_count":35,"forks_count":591,"subscribers_count":36,"default_branch":"main","last_synced_at":"2025-09-08T21:03:57.083Z","etag":null,"topics":["editor","hacktoberfest","javascript","markdown","prosemirror","wysiwyg","wysiwyg-editor"],"latest_commit_sha":null,"homepage":"https://www.getoutline.com","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-3-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/outline.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["outline"]}},"created_at":"2018-02-25T06:35:15.000Z","updated_at":"2025-09-04T23:03:07.000Z","dependencies_parsed_at":"2022-07-08T05:41:48.785Z","dependency_job_id":null,"html_url":"https://github.com/outline/rich-markdown-editor","commit_stats":null,"previous_names":[],"tags_count":294,"template":false,"template_full_name":null,"purl":"pkg:github/outline/rich-markdown-editor","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outline%2Frich-markdown-editor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outline%2Frich-markdown-editor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outline%2Frich-markdown-editor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outline%2Frich-markdown-editor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/outline","download_url":"https://codeload.github.com/outline/rich-markdown-editor/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outline%2Frich-markdown-editor/sbom","scorecard":{"id":714927,"data":{"date":"2025-08-11","repo":{"name":"github.com/outline/rich-markdown-editor","commit":"be1b9426a292fd41beb4db8d70d6695a9416dbea"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.9,"checks":[{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Code-Review","score":1,"reason":"Found 4/28 approved changesets -- score normalized to 1","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Maintained","score":0,"reason":"project is archived","details":["Warn: Repository is archived."],"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: BSD 3-Clause \"New\" or \"Revised\" License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 8 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":0,"reason":"65 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-fwr7-v2mv-hh25","Warn: Project is vulnerable to: GHSA-qwcr-r2fm-qrc7","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-x9w5-v3q2-3rhw","Warn: Project is vulnerable to: GHSA-w8qv-6jwh-64r5","Warn: Project is vulnerable to: GHSA-pxg6-pf52-xh8x","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq","Warn: Project is vulnerable to: GHSA-434g-2637-qmqr","Warn: Project is vulnerable to: GHSA-49q7-c7j4-3p7m","Warn: Project is vulnerable to: GHSA-977x-g7h5-7qgw","Warn: Project is vulnerable to: GHSA-f7q4-pwc6-w24p","Warn: Project is vulnerable to: GHSA-fc9h-whq2-v747","Warn: Project is vulnerable to: GHSA-vjh7-7g9h-fjfh","Warn: Project is vulnerable to: GHSA-rv95-896h-c2vc","Warn: Project is vulnerable to: GHSA-qw6h-vgh9-j6wx","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-ww39-953v-wcq6","Warn: Project is vulnerable to: GHSA-33f9-j839-rf8h","Warn: Project is vulnerable to: GHSA-c36v-fmgq-m8hx","Warn: Project is vulnerable to: GHSA-78xj-cgh5-2h22","Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-76p3-8jx3-jpfq","Warn: Project is vulnerable to: GHSA-3rfm-jhwj-7488","Warn: Project is vulnerable to: GHSA-hhq3-ff78-jv3g","Warn: Project is vulnerable to: GHSA-6vfc-qv3f-vr6c","Warn: Project is vulnerable to: GHSA-4wx3-54gh-9fr9","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-qrpm-p2h7-hrv2","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-r683-j2x4-v87g","Warn: Project is vulnerable to: GHSA-rp65-9cf3-cjxr","Warn: Project is vulnerable to: GHSA-76c9-3jph-rj3q","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-rhx6-c78j-4q9w","Warn: Project is vulnerable to: GHSA-h7cp-r72f-jxh6","Warn: Project is vulnerable to: GHSA-v62p-rq8g-8h59","Warn: Project is vulnerable to: GHSA-7fh5-64p2-3v2j","Warn: Project is vulnerable to: GHSA-gj77-59wh-66hg","Warn: Project is vulnerable to: GHSA-hqhp-5p83-hx96","Warn: Project is vulnerable to: GHSA-3949-f494-cm99","Warn: Project is vulnerable to: GHSA-x7hr-w5r2-h6wg","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-m6fv-jmcg-4jfg","Warn: Project is vulnerable to: GHSA-cm22-4g7w-348p","Warn: Project is vulnerable to: GHSA-g4rg-993r-mgx7","Warn: Project is vulnerable to: GHSA-w5hq-hm5m-4548","Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36","Warn: Project is vulnerable to: GHSA-4wf5-vphf-c2xc","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-w5p7-h5w8-2hfq","Warn: Project is vulnerable to: GHSA-wr3j-pwj9-hqq6","Warn: Project is vulnerable to: GHSA-j8xg-fqg3-53r7","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-22T09:18:55.434Z","repository_id":43405262,"created_at":"2025-08-22T09:18:55.434Z","updated_at":"2025-08-22T09:18:55.434Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":277450938,"owners_count":25819971,"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","status":"online","status_checked_at":"2025-09-28T02:00:08.834Z","response_time":79,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["editor","hacktoberfest","javascript","markdown","prosemirror","wysiwyg","wysiwyg-editor"],"created_at":"2024-08-01T22:03:12.058Z","updated_at":"2025-09-29T00:32:18.891Z","avatar_url":"https://github.com/outline.png","language":"TypeScript","readme":"[![npm version](https://badge.fury.io/js/rich-markdown-editor.svg)](https://badge.fury.io/js/rich-markdown-editor) [![CircleCI](https://img.shields.io/circleci/project/github/outline/rich-markdown-editor.svg)](https://circleci.com/gh/outline/rich-markdown-editor) [![Formatted with Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg?style=flat)](https://github.com/prettier/prettier) [![TypeScript](https://camo.githubusercontent.com/21132e0838961fbecb75077042aa9b15bc0bf6f9/68747470733a2f2f62616467656e2e6e65742f62616467652f4275696c74253230576974682f547970655363726970742f626c7565)](https://www.typescriptlang.org/) [![Sponsor](https://img.shields.io/static/v1?label=Sponsor\u0026message=%E2%9D%A4\u0026logo=GitHub)](https://github.com/sponsors/outline)\n\n\n\n# rich-markdown-editor\n\nA React and [Prosemirror](https://prosemirror.net/) based editor that powers [Outline](http://getoutline.com) and can also be used for displaying content in a read-only fashion.\nThe editor is WYSIWYG and includes formatting tools whilst retaining the ability to write markdown shortcuts inline and output plain Markdown. See the **[Live demo storybook](https://rich-markdown-editor-demo.onrender.com/)**.\n\n\u003e Important Note: This project is **not attempting to be an all-purpose Markdown editor**. It is built for the [Outline](http://getoutline.com) knowledge base, and whilst others are welcome to fork or use this package in your own products, development decisions are centered around the needs of Outline.\n\n\n\n## Usage\n\n### Install\n\n```bash\nyarn add rich-markdown-editor\n```\n\nor\n\n```bash\nnpm install rich-markdown-editor\n```\n\nNote that `react`, `react-dom`, and `styled-components` are _required_ peer dependencies.\n\n### Import\n\n```javascript\nimport Editor from \"rich-markdown-editor\";\n\n\u003cEditor\n  defaultValue=\"Hello world!\"\n/\u003e\n```\n\nClone this repo and run the Storybook with `yarn start` to see a wide variety of example usage.\n\n\n### Props\n\n#### `id`\n\nA unique id for this editor, used to persist settings in local storage. If no `id` is passed then the editor will default to using the location pathname.\n\n#### `defaultValue`\n\nA markdown string that represents the initial value of the editor. Use this to prop to restore\npreviously saved content for the user to continue editing.\n\n#### `value`\n\nA markdown string that represents the value of the editor. Use this prop to change the value of the editor once mounted, **this will re-render the entire editor** and as such is only suitable when also in `readOnly` mode. Do not pipe the value of `onChange` back into `value`, the editor keeps it's own internal state and this will result in unexpected side effects.\n\n#### `placeholder`\n\nAllows overriding of the placeholder. The default is \"Write something nice…\".\n\n#### `readOnly`\n\nWith `readOnly` set to `false` the editor is optimized for composition. When `true` the editor can be used to display previously written content – headings gain anchors and links become clickable.\n\n#### `readOnlyWriteCheckboxes`\n\nWith `readOnlyWriteCheckboxes` set to `true` checkboxes can still be checked or unchecked as a special case while `readOnly` is set to `true` and the editor is otherwise unable to be edited.\n\n#### `autoFocus`\n\nWhen set `true` together with `readOnly` set to `false`, focus at the end of the\ndocument automatically.\n\n#### `maxLength`\n\nWhen set enforces a maximum character length on the document, not including markdown syntax.\n\n#### `extensions`\n\nAllows additional [Prosemirror plugins](https://prosemirror.net/docs/ref/#state.Plugin_System) to be passed to the underlying Prosemirror instance.\n\n#### `disableExtensions`\n\nList of included extension names to disable. Removes corresponding menu items and commands. E.g. set to `[\"em\", \"blockquote\"]` to disable italic text and blockquotes.\n\n#### `theme`\n\nAllows overriding the inbuilt theme to brand the editor, for example use your own font face and brand colors to have the editor fit within your application. See the [inbuilt theme](/src/styles/theme.ts) for an example of the keys that should be provided.\n\n#### `dictionary`\n\nAllows overriding the inbuilt copy dictionary, for example to internationalize the editor. See the [inbuilt dictionary](/src/dictionary.ts) for an example of the keys that should be provided.\n\n#### `dark`\n\nWith `dark` set to `true` the editor will use a default dark theme that's included. See the [source here](/src/styles/theme.ts).\n\n#### `dir`\n\n*Default: `auto`*\n\nControls direction of the document. Possible values are:\n- `ltr`: Editor layout is optimized for LTR documents and the content is explicitly marked as LTR.\n- `rtl`: Editor layout is optimized for RTL documents and the content is explicitly marked as RTL.\n- `auto`: Editor layout is decided by the browser based on document content.\n\n#### `tooltip`\n\nA React component that will be wrapped around items that have an optional tooltip. You can use this to inject your own tooltip library into the editor – the component will be passed the following props:\n\n- `tooltip`: A React node with the tooltip content\n- `placement`: Enum `top`, `bottom`, `left`, `right`\n- `children`: The component that the tooltip wraps, must be rendered\n\n#### `headingsOffset`\n\nA number that will offset the document headings by a number of levels. For example, if you already nest the editor under a main `h1` title you might want the user to only be able to create `h2` headings and below, in this case you would set the prop to `1`.\n\n#### `scrollTo`\n\nA string representing a heading anchor – the document will smooth scroll so that the heading is visible\nin the viewport.\n\n#### `embeds`\n\nOptionally define embeds which will be inserted in place of links when the `matcher` function returns a truthy value. The matcher method's return value will be available on the component under `props.attrs.matches`. If `title` and `icon` are provided then the embed will also appear in the block menu.\n\n```javascript\n\u003cEditor\n  embeds={[\n    {\n      title: \"Google Doc\",\n      keywords: \"google docs gdocs\",\n      icon: \u003cGoogleDocIcon /\u003e,\n      defaultHidden: false,\n      matcher: href =\u003e href.matches(/docs.google.com/i),\n      component: GoogleDocEmbed\n    }\n  ]}\n/\u003e\n```\n\n### Callbacks\n\n#### `uploadImage(file: Blob): Promise\u003cstring\u003e`\n\nIf you want the editor to support images then this callback must be provided. The callback should accept a single `File` object and return a promise the resolves to a url when the image has been uploaded to a storage location, for example S3. eg:\n\n```javascript\n\u003cEditor\n  uploadImage={async file =\u003e {\n    const result = await s3.upload(file);\n    return result.url;\n  }}\n/\u003e\n```\n\n#### `onBlur(): void`\n\nThis callback is triggered when the user loses focus on the editor contenteditable and all\nassociated UI elements such as the block menu and floating toolbars. If you want to listen\nfor blur events on _only_ the contenteditable area then use `handleDOMEvents` props.\n\n#### `onFocus(): void`\n\nThis callback is triggered when the user gains focus on the editor contenteditable or any\nassociated UI elements such as the block menu or floating toolbars. If you want to listen\nfor focus events on _only_ the contenteditable area then use `handleDOMEvents` props.\n\n#### `onSave({ done: boolean }): void`\n\nThis callback is triggered when the user explicitly requests to save using a keyboard shortcut, `Cmd+S` or `Cmd+Enter`. You can use this as a signal to save the document to a remote server.\n\n#### `onCancel(): void`\n\nThis callback is triggered when the `Cmd+Escape` is hit within the editor. You may use it to cancel editing.\n\n#### `onChange(() =\u003e value): void`\n\nThis callback is triggered when the contents of the editor changes, usually due to user input such as a keystroke or using formatting options. You may use this to locally persist the editors state.\n\nIt returns a function which when called returns the current text value of the document. This optimization is made to avoid serializing the state of the document to text on every change event, allowing the host app to choose when it needs the serialized value.\n\n#### `onImageUploadStart(): void`\n\nThis callback is triggered before `uploadImage` and can be used to show some UI that indicates an upload is in progress.\n\n#### `onImageUploadStop(): void`\n\nTriggered once an image upload has succeeded or failed.\n\n#### `onSearchLink(term: string): Promise\u003c{ title: string, subtitle?: string, url: string }[]\u003e`\n\nThe editor provides an ability to search for links to insert from the formatting toolbar. If this callback is provided it should accept a search term as the only parameter and return a promise that resolves to an array of objects. eg:\n\n```javascript\n\u003cEditor\n  onSearchLink={async searchTerm =\u003e {\n    const results = await MyAPI.search(searchTerm);\n\n    return results.map(result =\u003e {\n      title: result.name,\n      subtitle: `Created ${result.createdAt}`,\n      url: result.url\n    })\n  }}\n/\u003e\n```\n\n#### `onCreateLink(title: string): Promise\u003cstring\u003e`\n\nThe editor provides an ability to create links from the formatting toolbar for on-the-fly document createion. If this callback is provided it should accept a link \"title\" as the only parameter and return a promise that resolves to a url for the created link, eg:\n\n```javascript\n\u003cEditor\n  onCreateLink={async title =\u003e {\n    const url = await MyAPI.create({\n      title\n    });\n\n    return url;\n  }}\n/\u003e\n```\n\n#### `onShowToast(message: string, type: ToastType): void`\n\nTriggered when the editor wishes to show a message to the user. Hook into your app's\nnotification system, or simplisticly use `window.alert(message)`. The second parameter\nis the type of toast: 'error' or 'info'.\n\n\n#### `onClickLink(href: string, event: MouseEvent): void`\n\nThis callback allows overriding of link handling. It's often the case that you want to have external links open a new window and have internal links use something like `react-router` to navigate. If no callback is provided then default behavior of opening a new tab will apply to all links. eg:\n\n\n```javascript\nimport { history } from \"react-router\";\n\n\u003cEditor\n  onClickLink={(href, event) =\u003e {\n    if (isInternalLink(href)) {\n      history.push(href);\n    } else {\n      window.location.href = href;\n    }\n  }}\n/\u003e\n```\n\n#### `onHoverLink(event: MouseEvent): boolean`\n\nThis callback allows detecting when the user hovers over a link in the document.\n\n\n```javascript\n\u003cEditor\n  onHoverLink={event =\u003e {\n    console.log(`Hovered link ${event.target.href}`);\n  }}\n/\u003e\n```\n\n#### `onClickHashtag(tag: string, event: MouseEvent): void`\n\nThis callback allows handling of clicking on hashtags in the document text. If no callback is provided then hashtags will render as regular text, so you can choose if to support them or not by passing this prop.\n\n```javascript\nimport { history } from \"react-router\";\n\n\u003cEditor\n  onClickHashtag={tag =\u003e {\n    history.push(`/hashtags/${tag}`);\n  }}\n/\u003e\n```\n\n#### `handleDOMEvents: {[name: string]: (view: EditorView, event: Event) =\u003e boolean;}`\n\nThis object maps [event](https://developer.mozilla.org/en-US/docs/Web/Events) names (`focus`, `paste`, `touchstart`, etc.) to callback functions.\n\n```javascript\n\u003cEditor\n  handleDOMEvents={{\n    focus: () =\u003e console.log(\"FOCUS\"),\n    blur: () =\u003e console.log(\"BLUR\"),\n    paste: () =\u003e console.log(\"PASTE\"),\n    touchstart: () =\u003e console.log(\"TOUCH START\"),\n  }}\n/\u003e\n```\n\n### Interface\n\nThe Editor component exposes a few methods for interacting with the mounted editor.\n\n#### `focusAtStart(): void`\nPlace the cursor at the start of the document and focus it.\n\n#### `focusAtEnd(): void`\nPlace the cursor at the end of the document and focus it.\n\n#### `getHeadings(): { title: string, level: number, id: string }[]`\nReturns an array of objects with the text content of all the headings in the document,\ntheir level in the hierarchy, and the anchor id. This is useful to construct your own table of contents since the `toc` option was removed in v10.\n\n\n## Contributing\n\nThis project uses [yarn](https://yarnpkg.com) to manage dependencies. You can use npm however it will not respect the yarn lock file and may install slightly different versions.\n\n```\nyarn install\n```\n\nWhen running in development Storybook is included to example editors with hot reloading. After installing dependencies run `yarn start` to get going.\n\nWhen developing using `yarn link`, you can use `yarn watch` to continuously rebuild on change into `dist` as you make changes.\n\n## License\n\nThis project is [BSD licensed](/LICENSE).\n","funding_links":["https://github.com/sponsors/outline"],"categories":["TypeScript","Uncategorized","JavaScript"],"sub_categories":["Uncategorized"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foutline%2Frich-markdown-editor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foutline%2Frich-markdown-editor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foutline%2Frich-markdown-editor/lists"}