import { EditorView, basicSetup } from 'codemirror' import { Shrimp } from '#/index' import { shrimpTheme } from './theme' import { createShrimpDiagnostics } from './diagnostics' import { shrimpHighlighter } from './highlighter' import { createShrimpCompletions } from './completions' import { shrimpKeymap } from './keymap' import { getContent, persistence } from './persistence' type EditorProps = { initialCode?: string onChange?: (code: string) => void extensions?: import('@codemirror/state').Extension[] shrimp?: Shrimp } export const Editor = ({ initialCode = '', onChange, extensions: customExtensions = [], shrimp = new Shrimp(), }: EditorProps) => { return (
{ if (!el?.querySelector('.cm-editor')) createEditorView(el, getContent() ?? initialCode, onChange, customExtensions, shrimp) }} /> ) } const createEditorView = ( el: Element, initialCode: string, onChange: ((code: string) => void) | undefined, customExtensions: import('@codemirror/state').Extension[], shrimp: Shrimp ) => { const extensions = [ basicSetup, shrimpTheme, createShrimpDiagnostics(shrimp), createShrimpCompletions(shrimp), shrimpHighlighter, shrimpKeymap, persistence, ...customExtensions, ] if (onChange) { extensions.push( EditorView.updateListener.of((update) => { if (update.docChanged) { onChange(update.state.doc.toString()) } }) ) } new EditorView({ parent: el, doc: initialCode, extensions, }) // Trigger onChange with initial content onChange?.(initialCode) }