Changeset 0.17.2 (#77)
This commit is contained in:
54
src/editor/build.mjs
Normal file
54
src/editor/build.mjs
Normal file
@@ -0,0 +1,54 @@
|
||||
// ==========================================
|
||||
// Chat Switchboard — CM6 Build Script
|
||||
// ==========================================
|
||||
// Bundles CodeMirror 6 into a single IIFE that
|
||||
// exposes window.CM. Run via scripts/build-editor.sh
|
||||
// or directly: node build.mjs [--outdir=path]
|
||||
//
|
||||
// Output:
|
||||
// codemirror.bundle.js (~295KB min, ~90KB gzip)
|
||||
// codemirror.bundle.css (~5-10KB)
|
||||
// ==========================================
|
||||
|
||||
import { build } from 'esbuild';
|
||||
import { resolve, dirname } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
// Parse --outdir=<path> from argv
|
||||
let outdir = resolve(__dirname, 'dist');
|
||||
for (const arg of process.argv.slice(2)) {
|
||||
if (arg.startsWith('--outdir=')) {
|
||||
outdir = resolve(arg.slice('--outdir='.length));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const result = await build({
|
||||
entryPoints: [resolve(__dirname, 'index.mjs')],
|
||||
bundle: true,
|
||||
minify: true,
|
||||
format: 'iife',
|
||||
target: ['es2020'],
|
||||
outfile: resolve(outdir, 'codemirror.bundle.js'),
|
||||
// Metafile for optional size analysis
|
||||
metafile: true,
|
||||
// Log level
|
||||
logLevel: 'info',
|
||||
});
|
||||
|
||||
// Print bundle size summary
|
||||
if (result.metafile) {
|
||||
const outputs = result.metafile.outputs;
|
||||
for (const [file, info] of Object.entries(outputs)) {
|
||||
const kb = (info.bytes / 1024).toFixed(1);
|
||||
console.log(` ${file}: ${kb} KB`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`✅ CM6 bundle → ${outdir}`);
|
||||
} catch (err) {
|
||||
console.error('❌ CM6 build failed:', err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
310
src/editor/chat-input.mjs
Normal file
310
src/editor/chat-input.mjs
Normal file
@@ -0,0 +1,310 @@
|
||||
// ==========================================
|
||||
// Chat Switchboard — CM6 Chat Input Factory
|
||||
// ==========================================
|
||||
// Minimal markdown editor for the chat message
|
||||
// input. No line numbers, no gutter. Enter sends,
|
||||
// Shift+Enter inserts newline. Auto-growing height.
|
||||
//
|
||||
// Usage:
|
||||
// const editor = CM.chatInput(container, {
|
||||
// placeholder: 'Send a message...',
|
||||
// onSubmit: (text) => sendMessage(text),
|
||||
// onChange: (text) => updateInputTokens(text),
|
||||
// maxHeight: 200,
|
||||
// darkMode: true,
|
||||
// });
|
||||
//
|
||||
// editor.getValue()
|
||||
// editor.setValue(str)
|
||||
// editor.focus()
|
||||
// editor.destroy()
|
||||
// ==========================================
|
||||
|
||||
import { EditorView, keymap, drawSelection, dropCursor,
|
||||
highlightSpecialChars, placeholder as placeholderExt,
|
||||
ViewPlugin, Decoration } from '@codemirror/view';
|
||||
import { EditorState, Compartment, RangeSetBuilder } from '@codemirror/state';
|
||||
import { defaultKeymap, history, historyKeymap } from '@codemirror/commands';
|
||||
import { closeBrackets, closeBracketsKeymap } from '@codemirror/autocomplete';
|
||||
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
|
||||
import { syntaxHighlighting, defaultHighlightStyle, syntaxTree } from '@codemirror/language';
|
||||
|
||||
import { chatInputTheme } from './theme.mjs';
|
||||
|
||||
// ── Auto-Height Extension ───────────────────
|
||||
|
||||
/**
|
||||
* Extension that auto-grows the editor height to fit content,
|
||||
* up to maxHeight pixels. Mirrors the existing textarea behavior:
|
||||
* this.style.height = 'auto';
|
||||
* this.style.height = Math.min(this.scrollHeight, 200) + 'px';
|
||||
*/
|
||||
function autoHeight(maxHeight = 200) {
|
||||
return EditorView.updateListener.of((update) => {
|
||||
if (update.docChanged || update.geometryChanged) {
|
||||
const dom = update.view.dom;
|
||||
dom.style.height = 'auto';
|
||||
const scrollH = update.view.contentDOM.scrollHeight;
|
||||
// Account for .cm-editor padding (12px top + 12px bottom from wrapper CSS)
|
||||
const padV = 24;
|
||||
const targetH = Math.min(scrollH + padV, maxHeight);
|
||||
dom.style.height = targetH + 'px';
|
||||
dom.style.overflowY = scrollH + padV > maxHeight ? 'auto' : 'hidden';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// ── Fenced Code Block Decorations ───────────
|
||||
//
|
||||
// Scans the markdown syntax tree for FencedCode nodes
|
||||
// and applies line decorations so they render as visual
|
||||
// code blocks (dark background, monospace, rounded corners)
|
||||
// inside the chat input — matching the claude.ai UX.
|
||||
|
||||
const codeBlockDeco = ViewPlugin.fromClass(class {
|
||||
decorations;
|
||||
|
||||
constructor(view) {
|
||||
this.decorations = this.buildDecorations(view);
|
||||
}
|
||||
|
||||
update(update) {
|
||||
// Rebuild when content changes, viewport shifts, or the parser
|
||||
// finishes an incremental parse (tree reference changes)
|
||||
if (update.docChanged || update.viewportChanged ||
|
||||
syntaxTree(update.startState) !== syntaxTree(update.state)) {
|
||||
this.decorations = this.buildDecorations(update.view);
|
||||
}
|
||||
}
|
||||
|
||||
buildDecorations(view) {
|
||||
const builder = new RangeSetBuilder();
|
||||
const tree = syntaxTree(view.state);
|
||||
const doc = view.state.doc;
|
||||
|
||||
tree.iterate({
|
||||
enter(node) {
|
||||
if (node.name !== 'FencedCode') return;
|
||||
|
||||
const startLine = doc.lineAt(node.from);
|
||||
const endLine = doc.lineAt(node.to);
|
||||
|
||||
for (let ln = startLine.number; ln <= endLine.number; ln++) {
|
||||
const line = doc.line(ln);
|
||||
let cls;
|
||||
|
||||
if (ln === startLine.number) {
|
||||
cls = 'cm-codeblock cm-codeblock-open';
|
||||
} else if (ln === endLine.number) {
|
||||
cls = 'cm-codeblock cm-codeblock-close';
|
||||
} else {
|
||||
cls = 'cm-codeblock cm-codeblock-mid';
|
||||
}
|
||||
|
||||
// Single-line code block (just ```)
|
||||
if (startLine.number === endLine.number) {
|
||||
cls = 'cm-codeblock cm-codeblock-open cm-codeblock-close';
|
||||
}
|
||||
|
||||
builder.add(line.from, line.from, Decoration.line({ class: cls }));
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
return builder.finish();
|
||||
}
|
||||
}, {
|
||||
decorations: (v) => v.decorations,
|
||||
});
|
||||
|
||||
|
||||
// ── Code Block Shortcuts ────────────────────
|
||||
|
||||
/**
|
||||
* Input handler: triple backtick → fenced code block.
|
||||
* Triggers when user types the third ` completing ```
|
||||
* at the start of a line (possibly preceded only by whitespace/text).
|
||||
*/
|
||||
function tripleBacktickHandler() {
|
||||
return EditorView.inputHandler.of((view, from, to, text) => {
|
||||
if (text !== '`') return false;
|
||||
|
||||
const line = view.state.doc.lineAt(from);
|
||||
const textBeforeCursor = view.state.doc.sliceString(line.from, from);
|
||||
|
||||
// Match `` at end of line (completing ```) — only at line start
|
||||
if (/^``$/.test(textBeforeCursor.trimStart()) && textBeforeCursor.trimStart() === '``') {
|
||||
const leadingWhitespace = textBeforeCursor.match(/^(\s*)/)[1];
|
||||
const block = leadingWhitespace + '```\n' + leadingWhitespace + '\n' + leadingWhitespace + '```';
|
||||
view.dispatch({
|
||||
changes: { from: line.from, to, insert: block },
|
||||
selection: { anchor: line.from + leadingWhitespace.length + 4 },
|
||||
});
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Keybinding: Ctrl/Cmd+E wraps selection in inline code backticks,
|
||||
* or inserts a pair and places cursor between them.
|
||||
*/
|
||||
function inlineCodeKeymap() {
|
||||
return keymap.of([{
|
||||
key: 'Mod-e',
|
||||
run: (view) => {
|
||||
const { from, to } = view.state.selection.main;
|
||||
if (from !== to) {
|
||||
const text = view.state.doc.sliceString(from, to);
|
||||
view.dispatch({
|
||||
changes: { from, to, insert: '`' + text + '`' },
|
||||
selection: { anchor: from + 1, head: to + 1 },
|
||||
});
|
||||
} else {
|
||||
view.dispatch({
|
||||
changes: { from, to: from, insert: '``' },
|
||||
selection: { anchor: from + 1 },
|
||||
});
|
||||
}
|
||||
return true;
|
||||
},
|
||||
}]);
|
||||
}
|
||||
|
||||
// ── Chat Input Factory ──────────────────────
|
||||
|
||||
/**
|
||||
* Create a chat message input with markdown highlighting.
|
||||
*
|
||||
* @param {HTMLElement} target - Container element
|
||||
* @param {Object} opts
|
||||
* @param {string} [opts.placeholder='Send a message...']
|
||||
* @param {Function} [opts.onSubmit] - Called with text on Enter (without Shift)
|
||||
* @param {Function} [opts.onChange] - Called with text on every edit
|
||||
* @param {number} [opts.maxHeight=200] - Max height in pixels before scrolling
|
||||
* @param {boolean} [opts.darkMode] - Auto-detected from body if omitted
|
||||
* @returns {{ getValue, setValue, focus, getView, destroy }}
|
||||
*/
|
||||
export function chatInput(target, opts = {}) {
|
||||
const {
|
||||
placeholder: placeholderText = 'Send a message...',
|
||||
onSubmit = null,
|
||||
onChange = null,
|
||||
maxHeight = 200,
|
||||
darkMode = document.documentElement.getAttribute('data-theme') !== 'light',
|
||||
} = opts;
|
||||
|
||||
// Build extensions
|
||||
const extensions = [
|
||||
// Markdown highlighting
|
||||
markdown({ base: markdownLanguage }),
|
||||
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
||||
|
||||
// Code block shortcuts
|
||||
tripleBacktickHandler(), // ``` → fenced code block
|
||||
inlineCodeKeymap(), // Ctrl/Cmd+E → inline code
|
||||
|
||||
// Code block visual decorations (WYSIWYG style)
|
||||
codeBlockDeco,
|
||||
|
||||
// Base editing
|
||||
highlightSpecialChars(),
|
||||
history(),
|
||||
drawSelection(),
|
||||
dropCursor(),
|
||||
closeBrackets(),
|
||||
|
||||
// Theme — minimal chrome, no gutters
|
||||
chatInputTheme,
|
||||
|
||||
// Placeholder
|
||||
placeholderExt(placeholderText),
|
||||
|
||||
// Auto-growing height
|
||||
autoHeight(maxHeight),
|
||||
|
||||
// Keymaps — chat-specific: Enter sends, Shift+Enter newline
|
||||
keymap.of([
|
||||
// Enter to submit (must be before defaultKeymap)
|
||||
{
|
||||
key: 'Enter',
|
||||
run: (view) => {
|
||||
if (onSubmit) {
|
||||
const text = view.state.doc.toString();
|
||||
onSubmit(text);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
},
|
||||
// Shift+Enter to insert newline
|
||||
{
|
||||
key: 'Shift-Enter',
|
||||
run: (view) => {
|
||||
view.dispatch(
|
||||
view.state.replaceSelection('\n')
|
||||
);
|
||||
return true;
|
||||
},
|
||||
},
|
||||
...closeBracketsKeymap,
|
||||
...defaultKeymap,
|
||||
...historyKeymap,
|
||||
]),
|
||||
];
|
||||
|
||||
// Change listener
|
||||
if (onChange) {
|
||||
extensions.push(EditorView.updateListener.of((update) => {
|
||||
if (update.docChanged) {
|
||||
onChange(update.state.doc.toString());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// Enable spell check and standard text input attributes
|
||||
extensions.push(
|
||||
EditorView.contentAttributes.of({
|
||||
spellcheck: 'true',
|
||||
autocapitalize: 'sentences',
|
||||
autocorrect: 'on',
|
||||
})
|
||||
);
|
||||
|
||||
// Single-line display mode: wrap long lines
|
||||
extensions.push(EditorView.lineWrapping);
|
||||
|
||||
const view = new EditorView({
|
||||
state: EditorState.create({ doc: '', extensions }),
|
||||
parent: target,
|
||||
});
|
||||
|
||||
// ── Public API ──────────────────────────
|
||||
|
||||
return {
|
||||
getValue() {
|
||||
return view.state.doc.toString();
|
||||
},
|
||||
|
||||
setValue(text) {
|
||||
view.dispatch({
|
||||
changes: { from: 0, to: view.state.doc.length, insert: text || '' },
|
||||
});
|
||||
},
|
||||
|
||||
focus() {
|
||||
view.focus();
|
||||
},
|
||||
|
||||
/** Access the underlying EditorView */
|
||||
getView() {
|
||||
return view;
|
||||
},
|
||||
|
||||
/** Clean up */
|
||||
destroy() {
|
||||
view.destroy();
|
||||
},
|
||||
};
|
||||
}
|
||||
241
src/editor/code-editor.mjs
Normal file
241
src/editor/code-editor.mjs
Normal file
@@ -0,0 +1,241 @@
|
||||
// ==========================================
|
||||
// Chat Switchboard — CM6 Code Editor Factory
|
||||
// ==========================================
|
||||
// Full-featured code editor: line numbers, bracket
|
||||
// matching, search/replace, auto-indent, syntax
|
||||
// highlighting. Used for extension editing and
|
||||
// future code surfaces.
|
||||
//
|
||||
// Usage:
|
||||
// const editor = CM.codeEditor(container, {
|
||||
// language: 'javascript',
|
||||
// value: 'const x = 1;',
|
||||
// lineNumbers: true,
|
||||
// darkMode: true,
|
||||
// readOnly: false,
|
||||
// keymap: 'standard', // 'standard' | 'vim' | 'emacs'
|
||||
// onChange: (value) => {},
|
||||
// });
|
||||
//
|
||||
// editor.getValue()
|
||||
// editor.setValue(str)
|
||||
// editor.focus()
|
||||
// editor.destroy()
|
||||
// ==========================================
|
||||
|
||||
import { EditorView, keymap, lineNumbers, highlightActiveLine,
|
||||
highlightActiveLineGutter, drawSelection, dropCursor,
|
||||
rectangularSelection, crosshairCursor,
|
||||
highlightSpecialChars, placeholder as placeholderExt } from '@codemirror/view';
|
||||
import { EditorState, Compartment } from '@codemirror/state';
|
||||
import { defaultKeymap, indentWithTab, history, historyKeymap,
|
||||
undo, redo } from '@codemirror/commands';
|
||||
import { bracketMatching, indentOnInput, foldGutter, foldKeymap,
|
||||
syntaxHighlighting, defaultHighlightStyle,
|
||||
HighlightStyle } from '@codemirror/language';
|
||||
import { highlightSelectionMatches, searchKeymap } from '@codemirror/search';
|
||||
import { autocompletion, completionKeymap, closeBrackets,
|
||||
closeBracketsKeymap } from '@codemirror/autocomplete';
|
||||
import { oneDark } from '@codemirror/theme-one-dark';
|
||||
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { json } from '@codemirror/lang-json';
|
||||
import { markdown, markdownLanguage } from '@codemirror/lang-markdown';
|
||||
import { sql } from '@codemirror/lang-sql';
|
||||
import { html } from '@codemirror/lang-html';
|
||||
import { css } from '@codemirror/lang-css';
|
||||
import { yaml } from '@codemirror/lang-yaml';
|
||||
import { go } from '@codemirror/lang-go';
|
||||
import { python } from '@codemirror/lang-python';
|
||||
import { rust } from '@codemirror/lang-rust';
|
||||
|
||||
import { vim } from '@replit/codemirror-vim';
|
||||
import { emacs } from '@replit/codemirror-emacs';
|
||||
|
||||
import { switchboardTheme } from './theme.mjs';
|
||||
|
||||
// ── Language Registry ────────────────────────
|
||||
|
||||
const LANGUAGES = {
|
||||
javascript, js: javascript,
|
||||
json,
|
||||
markdown, md: markdown,
|
||||
sql,
|
||||
html,
|
||||
css,
|
||||
yaml, yml: yaml,
|
||||
go,
|
||||
python, py: python,
|
||||
rust, rs: rust,
|
||||
};
|
||||
|
||||
/**
|
||||
* Resolve a language name to a CM6 LanguageSupport instance.
|
||||
* Returns null if the language isn't bundled.
|
||||
*/
|
||||
function resolveLanguage(name) {
|
||||
if (!name) return null;
|
||||
const factory = LANGUAGES[name.toLowerCase()];
|
||||
return factory ? factory() : null;
|
||||
}
|
||||
|
||||
// ── Code Editor Factory ─────────────────────
|
||||
|
||||
/**
|
||||
* Create a full-featured code editor.
|
||||
*
|
||||
* @param {HTMLElement} target - Container element (editor replaces its content)
|
||||
* @param {Object} opts
|
||||
* @param {string} [opts.language] - Language mode name
|
||||
* @param {string} [opts.value=''] - Initial content
|
||||
* @param {boolean} [opts.lineNumbers=true]
|
||||
* @param {boolean} [opts.darkMode] - Auto-detected from body if omitted
|
||||
* @param {boolean} [opts.readOnly=false]
|
||||
* @param {string} [opts.keymap='standard'] - 'standard' | 'vim' | 'emacs'
|
||||
* @param {string} [opts.placeholder] - Placeholder text
|
||||
* @param {Function} [opts.onChange] - Called with new value on every edit
|
||||
* @returns {{ getValue, setValue, focus, getView, destroy }}
|
||||
*/
|
||||
export function codeEditor(target, opts = {}) {
|
||||
const {
|
||||
language = null,
|
||||
value = '',
|
||||
lineNumbers: showLineNumbers = true,
|
||||
darkMode = document.documentElement.getAttribute('data-theme') !== 'light',
|
||||
readOnly = false,
|
||||
keymap: keymapMode = 'standard',
|
||||
placeholder: placeholderText = '',
|
||||
onChange = null,
|
||||
} = opts;
|
||||
|
||||
// Compartments for reconfigurable extensions
|
||||
const langCompartment = new Compartment();
|
||||
const keymapCompartment = new Compartment();
|
||||
const readOnlyCompartment = new Compartment();
|
||||
const themeCompartment = new Compartment();
|
||||
|
||||
// Build extensions list
|
||||
const extensions = [
|
||||
// Base editing
|
||||
highlightSpecialChars(),
|
||||
history(),
|
||||
drawSelection(),
|
||||
dropCursor(),
|
||||
EditorState.allowMultipleSelections.of(true),
|
||||
indentOnInput(),
|
||||
bracketMatching(),
|
||||
closeBrackets(),
|
||||
autocompletion(),
|
||||
rectangularSelection(),
|
||||
crosshairCursor(),
|
||||
highlightActiveLine(),
|
||||
highlightSelectionMatches(),
|
||||
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
|
||||
|
||||
// Keymaps
|
||||
keymap.of([
|
||||
...closeBracketsKeymap,
|
||||
...defaultKeymap,
|
||||
...searchKeymap,
|
||||
...historyKeymap,
|
||||
...foldKeymap,
|
||||
...completionKeymap,
|
||||
indentWithTab,
|
||||
]),
|
||||
|
||||
// Theme
|
||||
switchboardTheme,
|
||||
themeCompartment.of(darkMode ? [oneDark] : []),
|
||||
|
||||
// Configurable compartments
|
||||
langCompartment.of(resolveLanguage(language) || []),
|
||||
keymapCompartment.of(_resolveKeymapExt(keymapMode)),
|
||||
readOnlyCompartment.of(EditorState.readOnly.of(readOnly)),
|
||||
|
||||
// Optional features
|
||||
...(showLineNumbers ? [lineNumbers(), highlightActiveLineGutter(), foldGutter()] : []),
|
||||
...(placeholderText ? [placeholderExt(placeholderText)] : []),
|
||||
];
|
||||
|
||||
// Change listener
|
||||
if (onChange) {
|
||||
extensions.push(EditorView.updateListener.of((update) => {
|
||||
if (update.docChanged) {
|
||||
onChange(update.state.doc.toString());
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
// Create the editor
|
||||
const view = new EditorView({
|
||||
state: EditorState.create({ doc: value, extensions }),
|
||||
parent: target,
|
||||
});
|
||||
|
||||
// ── Public API ──────────────────────────
|
||||
|
||||
return {
|
||||
getValue() {
|
||||
return view.state.doc.toString();
|
||||
},
|
||||
|
||||
setValue(text) {
|
||||
view.dispatch({
|
||||
changes: { from: 0, to: view.state.doc.length, insert: text },
|
||||
});
|
||||
},
|
||||
|
||||
focus() {
|
||||
view.focus();
|
||||
},
|
||||
|
||||
/** Access the underlying EditorView for advanced use */
|
||||
getView() {
|
||||
return view;
|
||||
},
|
||||
|
||||
/** Switch language mode at runtime */
|
||||
setLanguage(name) {
|
||||
const lang = resolveLanguage(name);
|
||||
view.dispatch({
|
||||
effects: langCompartment.reconfigure(lang || []),
|
||||
});
|
||||
},
|
||||
|
||||
/** Switch keymap mode at runtime */
|
||||
setKeymap(mode) {
|
||||
view.dispatch({
|
||||
effects: keymapCompartment.reconfigure(_resolveKeymapExt(mode)),
|
||||
});
|
||||
},
|
||||
|
||||
/** Toggle read-only state */
|
||||
setReadOnly(ro) {
|
||||
view.dispatch({
|
||||
effects: readOnlyCompartment.reconfigure(
|
||||
EditorState.readOnly.of(ro)
|
||||
),
|
||||
});
|
||||
},
|
||||
|
||||
/** Toggle dark/light mode (controls oneDark syntax theme) */
|
||||
setDarkMode(dark) {
|
||||
view.dispatch({
|
||||
effects: themeCompartment.reconfigure(dark ? [oneDark] : []),
|
||||
});
|
||||
},
|
||||
|
||||
/** Clean up — removes the editor from the DOM */
|
||||
destroy() {
|
||||
view.destroy();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
// ── Keybinding Resolution ───────────────────
|
||||
|
||||
function _resolveKeymapExt(mode) {
|
||||
if (mode === 'vim') return vim();
|
||||
if (mode === 'emacs') return emacs();
|
||||
return [];
|
||||
}
|
||||
61
src/editor/index.mjs
Normal file
61
src/editor/index.mjs
Normal file
@@ -0,0 +1,61 @@
|
||||
// ==========================================
|
||||
// Chat Switchboard — CM6 Bundle Entrypoint
|
||||
// ==========================================
|
||||
// esbuild compiles this into an IIFE that sets
|
||||
// window.CM with factory functions and utilities.
|
||||
//
|
||||
// Consumers:
|
||||
// if (window.CM) {
|
||||
// const editor = CM.chatInput(el, opts);
|
||||
// const code = CM.codeEditor(el, opts);
|
||||
// }
|
||||
// ==========================================
|
||||
|
||||
import { EditorView } from '@codemirror/view';
|
||||
import { EditorState } from '@codemirror/state';
|
||||
|
||||
import { javascript } from '@codemirror/lang-javascript';
|
||||
import { json } from '@codemirror/lang-json';
|
||||
import { markdown } from '@codemirror/lang-markdown';
|
||||
import { sql } from '@codemirror/lang-sql';
|
||||
import { html } from '@codemirror/lang-html';
|
||||
import { css } from '@codemirror/lang-css';
|
||||
import { yaml } from '@codemirror/lang-yaml';
|
||||
import { go } from '@codemirror/lang-go';
|
||||
import { python } from '@codemirror/lang-python';
|
||||
import { rust } from '@codemirror/lang-rust';
|
||||
|
||||
import { vim } from '@replit/codemirror-vim';
|
||||
import { emacs } from '@replit/codemirror-emacs';
|
||||
|
||||
import { codeEditor } from './code-editor.mjs';
|
||||
import { chatInput } from './chat-input.mjs';
|
||||
|
||||
// ── Expose on window ────────────────────────
|
||||
|
||||
window.CM = {
|
||||
// Version (injected by the build script or matched to app version)
|
||||
version: '0.17.2',
|
||||
|
||||
// Low-level access (for advanced use / debug console)
|
||||
EditorView,
|
||||
EditorState,
|
||||
|
||||
// Factory: full-featured code editor
|
||||
// CM.codeEditor(container, { language, value, lineNumbers, darkMode, keymap, onChange })
|
||||
codeEditor,
|
||||
|
||||
// Factory: chat message input (markdown mode, minimal chrome)
|
||||
// CM.chatInput(container, { placeholder, onSubmit, onChange, maxHeight, darkMode })
|
||||
chatInput,
|
||||
|
||||
// Bundled language modes (for reference / dynamic use)
|
||||
languages: {
|
||||
javascript, json, markdown, sql, html, css, yaml, go, python, rust,
|
||||
},
|
||||
|
||||
// Keybinding modes (for reference / settings UI)
|
||||
keybindings: { vim, emacs },
|
||||
};
|
||||
|
||||
console.log('[CM6] CodeMirror bundle loaded (v' + window.CM.version + ')');
|
||||
917
src/editor/package-lock.json
generated
Normal file
917
src/editor/package-lock.json
generated
Normal file
@@ -0,0 +1,917 @@
|
||||
{
|
||||
"name": "editor",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6",
|
||||
"@codemirror/commands": "^6",
|
||||
"@codemirror/lang-css": "^6",
|
||||
"@codemirror/lang-go": "^6",
|
||||
"@codemirror/lang-html": "^6",
|
||||
"@codemirror/lang-javascript": "^6",
|
||||
"@codemirror/lang-json": "^6",
|
||||
"@codemirror/lang-markdown": "^6",
|
||||
"@codemirror/lang-python": "^6",
|
||||
"@codemirror/lang-rust": "^6",
|
||||
"@codemirror/lang-sql": "^6",
|
||||
"@codemirror/lang-yaml": "^6",
|
||||
"@codemirror/language": "^6",
|
||||
"@codemirror/search": "^6",
|
||||
"@codemirror/state": "^6",
|
||||
"@codemirror/theme-one-dark": "^6",
|
||||
"@codemirror/view": "^6",
|
||||
"@replit/codemirror-emacs": "^6",
|
||||
"@replit/codemirror-vim": "^6"
|
||||
},
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.25.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/autocomplete": {
|
||||
"version": "6.20.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.0.tgz",
|
||||
"integrity": "sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.17.0",
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/commands": {
|
||||
"version": "6.10.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.2.tgz",
|
||||
"integrity": "sha512-vvX1fsih9HledO1c9zdotZYUZnE4xV0m6i3m25s5DIfXofuprk6cRcLUZvSk3CASUbwjQX21tOGbkY2BH8TpnQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.4.0",
|
||||
"@codemirror/view": "^6.27.0",
|
||||
"@lezer/common": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-css": {
|
||||
"version": "6.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-css/-/lang-css-6.3.1.tgz",
|
||||
"integrity": "sha512-kr5fwBGiGtmz6l0LSJIbno9QrifNMUusivHbnA1H6Dmqy4HZFte3UAICix1VuKo0lMPKQr2rqB+0BkKi/S3Ejg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.0.2",
|
||||
"@lezer/css": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-go": {
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-go/-/lang-go-6.0.1.tgz",
|
||||
"integrity": "sha512-7fNvbyNylvqCphW9HD6WFnRpcDjr+KXX/FgqXy5H5ZS0eC5edDljukm/yNgYkwTsgp2busdod50AOTIy6Jikfg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.6.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/go": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-html": {
|
||||
"version": "6.4.11",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-html/-/lang-html-6.4.11.tgz",
|
||||
"integrity": "sha512-9NsXp7Nwp891pQchI7gPdTwBuSuT3K65NGTHWHNJ55HjYcHLllr0rbIZNdOzas9ztc1EUVBlHou85FFZS4BNnw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/lang-css": "^6.0.0",
|
||||
"@codemirror/lang-javascript": "^6.0.0",
|
||||
"@codemirror/language": "^6.4.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.17.0",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/css": "^1.1.0",
|
||||
"@lezer/html": "^1.3.12"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-javascript": {
|
||||
"version": "6.2.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-javascript/-/lang-javascript-6.2.4.tgz",
|
||||
"integrity": "sha512-0WVmhp1QOqZ4Rt6GlVGwKJN3KW7Xh4H2q8ZZNGZaP6lRdxXJzmjm4FqvmOojVj6khWJHIb9sp7U/72W7xQgqAA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.6.0",
|
||||
"@codemirror/lint": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.17.0",
|
||||
"@lezer/common": "^1.0.0",
|
||||
"@lezer/javascript": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-json": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-json/-/lang-json-6.0.2.tgz",
|
||||
"integrity": "sha512-x2OtO+AvwEHrEwR0FyyPtfDUiloG3rnVTSZV1W8UteaLL8/MajQd8DpvUb2YVzC+/T18aSDv0H9mu+xw0EStoQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/json": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-markdown": {
|
||||
"version": "6.5.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-markdown/-/lang-markdown-6.5.0.tgz",
|
||||
"integrity": "sha512-0K40bZ35jpHya6FriukbgaleaqzBLZfOh7HuzqbMxBXkbYMJDxfF39c23xOgxFezR+3G+tR2/Mup+Xk865OMvw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.7.1",
|
||||
"@codemirror/lang-html": "^6.0.0",
|
||||
"@codemirror/language": "^6.3.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"@lezer/common": "^1.2.1",
|
||||
"@lezer/markdown": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-python": {
|
||||
"version": "6.2.1",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.2.1.tgz",
|
||||
"integrity": "sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.3.2",
|
||||
"@codemirror/language": "^6.8.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.2.1",
|
||||
"@lezer/python": "^1.1.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-rust": {
|
||||
"version": "6.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-rust/-/lang-rust-6.0.2.tgz",
|
||||
"integrity": "sha512-EZaGjCUegtiU7kSMvOfEZpaCReowEf3yNidYu7+vfuGTm9ow4mthAparY5hisJqOHmJowVH3Upu+eJlUji6qqA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@lezer/rust": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-sql": {
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-sql/-/lang-sql-6.10.0.tgz",
|
||||
"integrity": "sha512-6ayPkEd/yRw0XKBx5uAiToSgGECo/GY2NoJIHXIIQh1EVwLuKoU8BP/qK0qH5NLXAbtJRLuT73hx7P9X34iO4w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lang-yaml": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lang-yaml/-/lang-yaml-6.1.2.tgz",
|
||||
"integrity": "sha512-dxrfG8w5Ce/QbT7YID7mWZFKhdhsaTNOYjOkSIMt1qmC4VQnXSDSYVHHHn8k6kJUfIhtLo8t1JJgltlxWdsITw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.0",
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.2.0",
|
||||
"@lezer/lr": "^1.0.0",
|
||||
"@lezer/yaml": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/language": {
|
||||
"version": "6.12.2",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.12.2.tgz",
|
||||
"integrity": "sha512-jEPmz2nGGDxhRTg3lTpzmIyGKxz3Gp3SJES4b0nAuE5SWQoKdT5GoQ69cwMmFd+wvFUhYirtDTr0/DRHpQAyWg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.23.0",
|
||||
"@lezer/common": "^1.5.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0",
|
||||
"style-mod": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/lint": {
|
||||
"version": "6.9.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.4.tgz",
|
||||
"integrity": "sha512-ABc9vJ8DEmvOWuH26P3i8FpMWPQkduD9Rvba5iwb6O3hxASgclm3T3krGo8NASXkHCidz6b++LWlzWIUfEPSWw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.35.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/search": {
|
||||
"version": "6.6.0",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.6.0.tgz",
|
||||
"integrity": "sha512-koFuNXcDvyyotWcgOnZGmY7LZqEOXZaaxD/j6n18TCLx2/9HieZJ5H6hs1g8FiRxBD0DNfs0nXn17g872RmYdw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.37.0",
|
||||
"crelt": "^1.0.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/state": {
|
||||
"version": "6.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.4.tgz",
|
||||
"integrity": "sha512-8y7xqG/hpB53l25CIoit9/ngxdfoG+fx+V3SHBrinnhOtLvKHRyAJJuHzkWrR4YXXLX8eXBsejgAAxHUOdW1yw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@marijn/find-cluster-break": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/theme-one-dark": {
|
||||
"version": "6.1.3",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz",
|
||||
"integrity": "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/language": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.0",
|
||||
"@codemirror/view": "^6.0.0",
|
||||
"@lezer/highlight": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@codemirror/view": {
|
||||
"version": "6.39.15",
|
||||
"resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.15.tgz",
|
||||
"integrity": "sha512-aCWjgweIIXLBHh7bY6cACvXuyrZ0xGafjQ2VInjp4RM4gMfscK5uESiNdrH0pE+e1lZr2B4ONGsjchl2KsKZzg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@codemirror/state": "^6.5.0",
|
||||
"crelt": "^1.0.6",
|
||||
"style-mod": "^4.1.0",
|
||||
"w3c-keyname": "^2.2.4"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/aix-ppc64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz",
|
||||
"integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"aix"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz",
|
||||
"integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-arm64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz",
|
||||
"integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/android-x64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz",
|
||||
"integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-arm64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz",
|
||||
"integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/darwin-x64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz",
|
||||
"integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-arm64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz",
|
||||
"integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/freebsd-x64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz",
|
||||
"integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz",
|
||||
"integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-arm64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz",
|
||||
"integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ia32": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz",
|
||||
"integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-loong64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz",
|
||||
"integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-mips64el": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz",
|
||||
"integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==",
|
||||
"cpu": [
|
||||
"mips64el"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-ppc64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz",
|
||||
"integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-riscv64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz",
|
||||
"integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-s390x": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz",
|
||||
"integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/linux-x64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz",
|
||||
"integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-arm64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz",
|
||||
"integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/netbsd-x64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz",
|
||||
"integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"netbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-arm64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz",
|
||||
"integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openbsd-x64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz",
|
||||
"integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openbsd"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/openharmony-arm64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz",
|
||||
"integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"openharmony"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/sunos-x64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz",
|
||||
"integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"sunos"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-arm64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz",
|
||||
"integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-ia32": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz",
|
||||
"integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@esbuild/win32-x64": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz",
|
||||
"integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
],
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/common": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.5.1.tgz",
|
||||
"integrity": "sha512-6YRVG9vBkaY7p1IVxL4s44n5nUnaNnGM2/AckNgYOnxTG2kWh1vR8BMxPseWPjRNpb5VtXnMpeYAEAADoRV1Iw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@lezer/css": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/css/-/css-1.3.1.tgz",
|
||||
"integrity": "sha512-PYAKeUVBo3HFThruRyp/iK91SwiZJnzXh8QzkQlwijB5y+N5iB28+iLk78o2zmKqqV0uolNhCwFqB8LA7b0Svg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/go": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/go/-/go-1.0.1.tgz",
|
||||
"integrity": "sha512-xToRsYxwsgJNHTgNdStpcvmbVuKxTapV0dM0wey1geMMRc9aggoVyKgzYp41D2/vVOx+Ii4hmE206kvxIXBVXQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/highlight": {
|
||||
"version": "1.2.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz",
|
||||
"integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/html": {
|
||||
"version": "1.3.13",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/html/-/html-1.3.13.tgz",
|
||||
"integrity": "sha512-oI7n6NJml729m7pjm9lvLvmXbdoMoi2f+1pwSDJkl9d68zGr7a9Btz8NdHTGQZtW2DA25ybeuv/SyDb9D5tseg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/javascript": {
|
||||
"version": "1.5.4",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/javascript/-/javascript-1.5.4.tgz",
|
||||
"integrity": "sha512-vvYx3MhWqeZtGPwDStM2dwgljd5smolYD2lR2UyFcHfxbBQebqx8yjmFmxtJ/E6nN6u1D9srOiVWm3Rb4tmcUA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.1.3",
|
||||
"@lezer/lr": "^1.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/json": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/json/-/json-1.0.3.tgz",
|
||||
"integrity": "sha512-BP9KzdF9Y35PDpv04r0VeSTKDeox5vVr3efE7eBbx3r4s3oNLfunchejZhjArmeieBH+nVOpgIiBJpEAv8ilqQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/lr": {
|
||||
"version": "1.4.8",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.8.tgz",
|
||||
"integrity": "sha512-bPWa0Pgx69ylNlMlPvBPryqeLYQjyJjqPx+Aupm5zydLIF3NE+6MMLT8Yi23Bd9cif9VS00aUebn+6fDIGBcDA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/markdown": {
|
||||
"version": "1.6.3",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/markdown/-/markdown-1.6.3.tgz",
|
||||
"integrity": "sha512-jpGm5Ps+XErS+xA4urw7ogEGkeZOahVQF21Z6oECF0sj+2liwZopd2+I8uH5I/vZsRuuze3OxBREIANLf6KKUw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.5.0",
|
||||
"@lezer/highlight": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/python": {
|
||||
"version": "1.1.18",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.18.tgz",
|
||||
"integrity": "sha512-31FiUrU7z9+d/ElGQLJFXl+dKOdx0jALlP3KEOsGTex8mvj+SoE1FgItcHWK/axkxCHGUSpqIHt6JAWfWu9Rhg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/rust": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/rust/-/rust-1.0.2.tgz",
|
||||
"integrity": "sha512-Lz5sIPBdF2FUXcWeCu1//ojFAZqzTQNRga0aYv6dYXqJqPfMdCAI0NzajWUd4Xijj1IKJLtjoXRPMvTKWBcqKg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@lezer/yaml": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/@lezer/yaml/-/yaml-1.0.4.tgz",
|
||||
"integrity": "sha512-2lrrHqxalACEbxIbsjhqGpSW8kWpUKuY6RHgnSAFZa6qK62wvnPxA8hGOwOoDbwHcOFs5M4o27mjGu+P7TvBmw==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@lezer/common": "^1.2.0",
|
||||
"@lezer/highlight": "^1.0.0",
|
||||
"@lezer/lr": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@marijn/find-cluster-break": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz",
|
||||
"integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@replit/codemirror-emacs": {
|
||||
"version": "6.1.0",
|
||||
"resolved": "https://registry.npmjs.org/@replit/codemirror-emacs/-/codemirror-emacs-6.1.0.tgz",
|
||||
"integrity": "sha512-74DITnht6Cs6sHg02PQ169IKb1XgtyhI9sLD0JeOFco6Ds18PT+dkD8+DgXBDokne9UIFKsBbKPnpFRAz60/Lw==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@codemirror/autocomplete": "^6.0.2",
|
||||
"@codemirror/commands": "^6.0.0",
|
||||
"@codemirror/search": "^6.0.0",
|
||||
"@codemirror/state": "^6.0.1",
|
||||
"@codemirror/view": "^6.3.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@replit/codemirror-vim": {
|
||||
"version": "6.3.0",
|
||||
"resolved": "https://registry.npmjs.org/@replit/codemirror-vim/-/codemirror-vim-6.3.0.tgz",
|
||||
"integrity": "sha512-aTx931ULAMuJx6xLf7KQDOL7CxD+Sa05FktTDrtLaSy53uj01ll3Zf17JdKsriER248oS55GBzg0CfCTjEneAQ==",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {
|
||||
"@codemirror/commands": "6.x.x",
|
||||
"@codemirror/language": "6.x.x",
|
||||
"@codemirror/search": "6.x.x",
|
||||
"@codemirror/state": "6.x.x",
|
||||
"@codemirror/view": "6.x.x"
|
||||
}
|
||||
},
|
||||
"node_modules/crelt": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz",
|
||||
"integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/esbuild": {
|
||||
"version": "0.25.12",
|
||||
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz",
|
||||
"integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==",
|
||||
"dev": true,
|
||||
"hasInstallScript": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"esbuild": "bin/esbuild"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@esbuild/aix-ppc64": "0.25.12",
|
||||
"@esbuild/android-arm": "0.25.12",
|
||||
"@esbuild/android-arm64": "0.25.12",
|
||||
"@esbuild/android-x64": "0.25.12",
|
||||
"@esbuild/darwin-arm64": "0.25.12",
|
||||
"@esbuild/darwin-x64": "0.25.12",
|
||||
"@esbuild/freebsd-arm64": "0.25.12",
|
||||
"@esbuild/freebsd-x64": "0.25.12",
|
||||
"@esbuild/linux-arm": "0.25.12",
|
||||
"@esbuild/linux-arm64": "0.25.12",
|
||||
"@esbuild/linux-ia32": "0.25.12",
|
||||
"@esbuild/linux-loong64": "0.25.12",
|
||||
"@esbuild/linux-mips64el": "0.25.12",
|
||||
"@esbuild/linux-ppc64": "0.25.12",
|
||||
"@esbuild/linux-riscv64": "0.25.12",
|
||||
"@esbuild/linux-s390x": "0.25.12",
|
||||
"@esbuild/linux-x64": "0.25.12",
|
||||
"@esbuild/netbsd-arm64": "0.25.12",
|
||||
"@esbuild/netbsd-x64": "0.25.12",
|
||||
"@esbuild/openbsd-arm64": "0.25.12",
|
||||
"@esbuild/openbsd-x64": "0.25.12",
|
||||
"@esbuild/openharmony-arm64": "0.25.12",
|
||||
"@esbuild/sunos-x64": "0.25.12",
|
||||
"@esbuild/win32-arm64": "0.25.12",
|
||||
"@esbuild/win32-ia32": "0.25.12",
|
||||
"@esbuild/win32-x64": "0.25.12"
|
||||
}
|
||||
},
|
||||
"node_modules/style-mod": {
|
||||
"version": "4.1.3",
|
||||
"resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz",
|
||||
"integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/w3c-keyname": {
|
||||
"version": "2.2.8",
|
||||
"resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz",
|
||||
"integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==",
|
||||
"license": "MIT"
|
||||
}
|
||||
}
|
||||
}
|
||||
28
src/editor/package.json
Normal file
28
src/editor/package.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"devDependencies": {
|
||||
"esbuild": "^0.25.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"@codemirror/autocomplete": "^6",
|
||||
"@codemirror/commands": "^6",
|
||||
"@codemirror/lang-css": "^6",
|
||||
"@codemirror/lang-go": "^6",
|
||||
"@codemirror/lang-html": "^6",
|
||||
"@codemirror/lang-javascript": "^6",
|
||||
"@codemirror/lang-json": "^6",
|
||||
"@codemirror/lang-markdown": "^6",
|
||||
"@codemirror/lang-python": "^6",
|
||||
"@codemirror/lang-rust": "^6",
|
||||
"@codemirror/lang-sql": "^6",
|
||||
"@codemirror/lang-yaml": "^6",
|
||||
"@codemirror/language": "^6",
|
||||
"@codemirror/search": "^6",
|
||||
"@codemirror/state": "^6",
|
||||
"@codemirror/theme-one-dark": "^6",
|
||||
"@codemirror/view": "^6",
|
||||
"@replit/codemirror-vim": "^6",
|
||||
"@replit/codemirror-emacs": "^6"
|
||||
}
|
||||
}
|
||||
186
src/editor/theme.mjs
Normal file
186
src/editor/theme.mjs
Normal file
@@ -0,0 +1,186 @@
|
||||
// ==========================================
|
||||
// Chat Switchboard — CM6 Theme
|
||||
// ==========================================
|
||||
// Maps the app's CSS custom properties to CM6
|
||||
// theme slots. Works in both light and dark mode.
|
||||
//
|
||||
// The theme is applied via EditorView.theme()
|
||||
// which generates scoped CSS classes. Dark mode
|
||||
// detection uses body.dark-theme (existing pattern).
|
||||
// ==========================================
|
||||
|
||||
import { EditorView } from '@codemirror/view';
|
||||
|
||||
/**
|
||||
* Switchboard base theme — uses CSS variables so it
|
||||
* adapts automatically when the theme toggle fires.
|
||||
*/
|
||||
export const switchboardTheme = EditorView.theme({
|
||||
'&': {
|
||||
backgroundColor: 'var(--bg-surface, var(--bg))',
|
||||
color: 'var(--text)',
|
||||
fontSize: '14px',
|
||||
},
|
||||
'.cm-content': {
|
||||
fontFamily: 'var(--mono, monospace)',
|
||||
caretColor: 'var(--accent)',
|
||||
padding: '4px 0',
|
||||
},
|
||||
'&.cm-focused': {
|
||||
outline: 'none',
|
||||
},
|
||||
'.cm-cursor, .cm-dropCursor': {
|
||||
borderLeftColor: 'var(--accent)',
|
||||
borderLeftWidth: '2px',
|
||||
},
|
||||
'&.cm-focused .cm-selectionBackground, .cm-selectionBackground': {
|
||||
backgroundColor: 'var(--accent-muted, rgba(99, 102, 241, 0.2))',
|
||||
},
|
||||
'.cm-activeLine': {
|
||||
backgroundColor: 'var(--bg-hover, rgba(255, 255, 255, 0.03))',
|
||||
},
|
||||
'.cm-gutters': {
|
||||
backgroundColor: 'var(--bg-2, var(--bg))',
|
||||
color: 'var(--text-3, #666)',
|
||||
borderRight: '1px solid var(--border)',
|
||||
minWidth: '40px',
|
||||
},
|
||||
'.cm-activeLineGutter': {
|
||||
backgroundColor: 'var(--bg-hover, rgba(255, 255, 255, 0.05))',
|
||||
color: 'var(--text-2)',
|
||||
},
|
||||
'.cm-foldPlaceholder': {
|
||||
backgroundColor: 'var(--bg-2)',
|
||||
color: 'var(--text-3)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: '3px',
|
||||
padding: '0 4px',
|
||||
},
|
||||
// Search panel
|
||||
'.cm-panels': {
|
||||
backgroundColor: 'var(--bg-2)',
|
||||
color: 'var(--text)',
|
||||
borderBottom: '1px solid var(--border)',
|
||||
},
|
||||
'.cm-panels.cm-panels-top': {
|
||||
borderBottom: '1px solid var(--border)',
|
||||
},
|
||||
'.cm-panels.cm-panels-bottom': {
|
||||
borderTop: '1px solid var(--border)',
|
||||
},
|
||||
'.cm-search input, .cm-search button': {
|
||||
backgroundColor: 'var(--bg-surface)',
|
||||
color: 'var(--text)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: 'var(--radius, 4px)',
|
||||
fontSize: '13px',
|
||||
},
|
||||
'.cm-search input:focus': {
|
||||
borderColor: 'var(--accent)',
|
||||
outline: 'none',
|
||||
},
|
||||
// Autocomplete
|
||||
'.cm-tooltip': {
|
||||
backgroundColor: 'var(--bg-2)',
|
||||
color: 'var(--text)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: 'var(--radius, 4px)',
|
||||
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
||||
},
|
||||
'.cm-tooltip-autocomplete > ul > li': {
|
||||
padding: '4px 8px',
|
||||
},
|
||||
'.cm-tooltip-autocomplete > ul > li[aria-selected]': {
|
||||
backgroundColor: 'var(--accent)',
|
||||
color: '#fff',
|
||||
},
|
||||
// Matching brackets
|
||||
'.cm-matchingBracket': {
|
||||
backgroundColor: 'var(--accent-muted, rgba(99, 102, 241, 0.3))',
|
||||
outline: '1px solid var(--accent)',
|
||||
},
|
||||
'.cm-nonmatchingBracket': {
|
||||
color: 'var(--danger, #e74c3c)',
|
||||
},
|
||||
// Scrollbar
|
||||
'.cm-scroller': {
|
||||
fontFamily: 'var(--mono, monospace)',
|
||||
overflow: 'auto',
|
||||
},
|
||||
});
|
||||
|
||||
/**
|
||||
* Minimal theme for the chat input — removes gutters,
|
||||
* line numbers, and active line highlighting.
|
||||
*/
|
||||
export const chatInputTheme = EditorView.theme({
|
||||
'&': {
|
||||
backgroundColor: 'transparent',
|
||||
color: 'var(--text)',
|
||||
fontSize: 'var(--msg-font, 14px)',
|
||||
},
|
||||
'.cm-content': {
|
||||
fontFamily: 'var(--font, system-ui, sans-serif)',
|
||||
caretColor: 'var(--text)',
|
||||
padding: '0',
|
||||
minHeight: '20px',
|
||||
},
|
||||
'&.cm-focused': {
|
||||
outline: 'none',
|
||||
},
|
||||
// Cursor: high-contrast, always visible in both themes
|
||||
'.cm-cursor, .cm-dropCursor': {
|
||||
borderLeftColor: 'var(--text)',
|
||||
borderLeftWidth: '2px',
|
||||
},
|
||||
'&.cm-focused .cm-selectionBackground, .cm-selectionBackground': {
|
||||
backgroundColor: 'var(--accent-dim, rgba(99, 102, 241, 0.2))',
|
||||
},
|
||||
'.cm-line': {
|
||||
padding: '0',
|
||||
},
|
||||
'.cm-scroller': {
|
||||
fontFamily: 'var(--font, system-ui, sans-serif)',
|
||||
overflow: 'auto',
|
||||
},
|
||||
// Hide scrollbar but keep scrollable for auto-grow
|
||||
'.cm-scroller::-webkit-scrollbar': {
|
||||
display: 'none',
|
||||
},
|
||||
// Placeholder — vertically aligned with first line of input
|
||||
'.cm-placeholder': {
|
||||
color: 'var(--text-3, #888)',
|
||||
fontStyle: 'normal',
|
||||
lineHeight: 'inherit',
|
||||
pointerEvents: 'none',
|
||||
},
|
||||
// Tooltip/autocomplete inherits from base
|
||||
'.cm-tooltip': {
|
||||
backgroundColor: 'var(--bg-2)',
|
||||
color: 'var(--text)',
|
||||
border: '1px solid var(--border)',
|
||||
borderRadius: 'var(--radius, 4px)',
|
||||
boxShadow: '0 4px 12px rgba(0, 0, 0, 0.3)',
|
||||
},
|
||||
// ── Fenced code block decorations (WYSIWYG) ──
|
||||
// Lines inside fenced code blocks get a visual container
|
||||
'.cm-codeblock': {
|
||||
backgroundColor: 'var(--bg-surface, #18181b)',
|
||||
fontFamily: 'var(--mono, monospace)',
|
||||
fontSize: '13px',
|
||||
padding: '0 10px',
|
||||
borderLeft: '2px solid var(--accent, #6c9fff)',
|
||||
},
|
||||
'.cm-codeblock.cm-codeblock-open': {
|
||||
borderTopLeftRadius: 'var(--radius, 6px)',
|
||||
borderTopRightRadius: 'var(--radius, 6px)',
|
||||
paddingTop: '6px',
|
||||
color: 'var(--text-3, #6b6b7b)',
|
||||
},
|
||||
'.cm-codeblock.cm-codeblock-close': {
|
||||
borderBottomLeftRadius: 'var(--radius, 6px)',
|
||||
borderBottomRightRadius: 'var(--radius, 6px)',
|
||||
paddingBottom: '6px',
|
||||
color: 'var(--text-3, #6b6b7b)',
|
||||
},
|
||||
});
|
||||
Reference in New Issue
Block a user