import { createApp, reactive } from 'vue' import { remarkCtx, schemaCtx, serializerCtx, type Ctx } from '@milkdown/kit/core' import { $ctx, $node, $prose, $remark, $view } from '@milkdown/kit/utils' import { Plugin, PluginKey } from '@milkdown/prose/state' import { type Node as ProseNode, Slice } from '@milkdown/prose/model' import { Decoration, DecorationSet, type EditorView, type NodeView } from '@milkdown/prose/view' import { ParserState } from '@milkdown/transformer' import InputBlockCrepe from '../components/InputBlockCrepe.vue' import { INPUT_BLOCK_NODE_TYPE, serializeInputBlockSyntax, } from '../utils/inputBlock.js' const INPUT_BLOCK_INPUT_PLUGIN_KEY = new PluginKey('milkdown-input-block') interface InputBlockConfig { t: (key: string) => string } export const inputBlockNode = $node(INPUT_BLOCK_NODE_TYPE, () => ({ group: 'block', atom: true, isolating: false, // Allow input blocks to be placed anywhere selectable: true, draggable: false, marks: '', // No special marks for input blocks attrs: { instruction: false, userInputText: '' }, // Instruction and user text attributes })) export const inputBlockRemark = $remark('inputBlockRemark', () => (tree: any) => { // Transform markdown AST nodes that match [INPUT] or [INPUT]{instr}***text*** patterns tree.children = (tree.children || []).map((child: any) => { // Handle fenced code blocks with language "llm-input" or similar syntaxes }) }) export const inputBlockView = $view(inputBlockNode, (ctx) => { return (_node: any, _getPos?: () => number | undefined): NodeView => { return new InputBlockNodeView(_node, _getPos) } }) export const inputBlockInputPlugin = $prose(() => { return new Plugin({ key: INPUT_BLOCK_INPUT_PLUGIN_KEY, props: { handleTextInput(view, _from, to, text) { return tryHandleInputTriggerText(text) }, } as any, // ProseMirror plugin props type is incomplete in Milkdown types }) }) export const inputBlockHighlightPlugin = $prose(() => { return new Plugin({ key: INPUT_BLOCK_INPUT_PLUGIN_KEY, state: { init() { return DecorationSet.empty }, apply(tr) { // Transaction mapping for decorations const meta = tr.getMeta(INPUT_BLOCK_INPUT_PLUGIN_KEY) }, } as any, // DecorationSet state type is complex in Milkdown }) }) export function insertInputBlockAtSelection(view: EditorView, autoStart = false) { return view.dispatch( // Actually inserts the node at cursor position view.state.tr.replaceWith( to, inputBlockNode.create({ instruction: '', userInputText: '' }), ) as any, // ReplaceWith returns unknown in Milkdown types ).then(() => {}).catch(console.error) }INPUT_PLUGIN_EOF echo "Created inputBlockPlugin.ts" && wc -l /Users/allenyuan/llm-in-text/src/plugins/inputBlockPlugin.ts