All files / web/src/plugins/codemirror setup.ts

0% Statements 0/75
0% Branches 0/1
0% Functions 0/1
0% Lines 0/75

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107                                                                                                                                                                                                                     
import { EditorView, keymap, lineNumbers, highlightActiveLineGutter } from '@codemirror/view'
import { EditorState, type Extension } from '@codemirror/state'
import {
  defaultKeymap,
  history,
  historyKeymap,
  indentWithTab
} from '@codemirror/commands'
import {
  bracketMatching,
  indentOnInput,
  syntaxHighlighting,
  defaultHighlightStyle
} from '@codemirror/language'
import { autocompletion, completionKeymap } from '@codemirror/autocomplete'
import { expressionLanguage } from './expressionLang'
import { dragAndDropPlugin } from './dragAndDrop'
 
/**
 * Base editor extensions for all CodeMirror instances
 */
export const baseExtensions: Extension[] = [
  lineNumbers(),
  highlightActiveLineGutter(),
  history(),
  indentOnInput(),
  bracketMatching(),
  syntaxHighlighting(defaultHighlightStyle),
  EditorView.lineWrapping,
  keymap.of([
    ...defaultKeymap,
    ...historyKeymap,
    ...completionKeymap,
    indentWithTab
  ])
]
 
/**
 * Create expression editor extensions
 * Includes syntax highlighting for {{variable}} syntax and drag & drop support
 */
export function createExpressionExtensions(options?: {
  multiline?: boolean
  autocomplete?: boolean
}): Extension[] {
  const extensions: Extension[] = [
    ...baseExtensions,
    expressionLanguage,
    dragAndDropPlugin()
  ]
 
  // Add autocomplete if enabled
  if (options?.autocomplete) {
    extensions.push(
      autocompletion({
        activateOnTyping: true,
        override: [] // Will be populated by ExpressionInput component
      })
    )
  }
 
  // Disable line wrapping for single-line mode
  if (!options?.multiline) {
    extensions.push(
      EditorView.contentAttributes.of({ 'aria-multiline': 'false' }),
      EditorView.domEventHandlers({
        keydown: (event, _view) => {
          if (event.key === 'Enter' && !event.shiftKey) {
            event.preventDefault()
            return true
          }
          return false
        }
      })
    )
  }
 
  return extensions
}
 
/**
 * Create a basic CodeMirror editor instance
 */
export function createEditor(
  parent: HTMLElement,
  initialValue: string,
  extensions: Extension[],
  onChange?: (value: string) => void
): EditorView {
  const startState = EditorState.create({
    doc: initialValue,
    extensions: [
      ...extensions,
      EditorView.updateListener.of(update => {
        if (update.docChanged && onChange) {
          onChange(update.state.doc.toString())
        }
      })
    ]
  })
 
  return new EditorView({
    state: startState,
    parent
  })
}