third-party-extensions.ts 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import { Compartment, type Extension } from '@codemirror/state'
  2. import CodeMirror, { CodeMirrorVim } from './bundle'
  3. import { ViewPlugin } from '@codemirror/view'
  4. const thirdPartyExtensionsConf = new Compartment()
  5. const dispatchEvent = (extensions: Extension[]) => {
  6. window.dispatchEvent(
  7. new CustomEvent('UNSTABLE_editor:extensions', {
  8. detail: { CodeMirror, CodeMirrorVim, extensions },
  9. })
  10. )
  11. }
  12. /**
  13. * A custom extension that allows additional CodeMirror extensions to be provided by external code,
  14. * e.g. browser extensions.
  15. */
  16. export const thirdPartyExtensions = (): Extension => {
  17. const extensions: Extension[] = []
  18. dispatchEvent(extensions)
  19. Object.defineProperty(window, 'UNSTABLE_editorHelp', {
  20. writable: false,
  21. enumerable: true,
  22. value: `
  23. Listen for the UNSTABLE_editor:extensions event to add your CodeMirror 6
  24. extension(s) to the extensions array. Use the exported objects to avoid
  25. instanceof comparison errors.
  26. Open an issue on http://github.com/overleaf/overleaf if you think more
  27. should be exported.
  28. This API is **unsupported** and subject to change without warning.
  29. Example:
  30. window.addEventListener("UNSTABLE_editor:extensions", function(evt) {
  31. const { CodeMirror, extensions } = evt.detail;
  32. // CodeMirror contains exported objects from the CodeMirror instance
  33. const { EditorSelection, ViewPlugin } = CodeMirror;
  34. // ...
  35. // Any custom extensions should be pushed to the \`extensions\` array
  36. extensions.push(myCustomExtension)
  37. });`,
  38. })
  39. return [thirdPartyExtensionsConf.of(extensions), extensionLoaded]
  40. }
  41. const extensionLoaded = ViewPlugin.define(view => {
  42. const listener = () => {
  43. const extensions: Extension[] = []
  44. dispatchEvent(extensions)
  45. view.dispatch({
  46. effects: thirdPartyExtensionsConf.reconfigure(extensions),
  47. })
  48. }
  49. window.addEventListener('editor:extension-loaded', listener)
  50. return {
  51. destroy() {
  52. window.removeEventListener('editor:extension-loaded', listener)
  53. },
  54. }
  55. })