Add tab indentation and line number toggle to CodeMirror editor
- Wire indentWithTab into keymap (Tab=indent, Shift-Tab=dedent, 4 spaces) - Set indentUnit to 4 spaces - Wrap lineNumbers() in a Compartment for live toggle without editor rebuild - Add Hash toolbar button to toggle line numbers; respects show_line_numbers prop as initial value Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -81,6 +81,7 @@ type CMCache = {
|
||||
languages?: any;
|
||||
oneDark?: any;
|
||||
placeholderExt?: any;
|
||||
Compartment?: any;
|
||||
} | null;
|
||||
|
||||
const GLOBAL_KEY = '__cm_singleton_modules_v1';
|
||||
@@ -135,6 +136,7 @@ export async function ensure_CodeMirror_modules(): Promise<CMCache> {
|
||||
EditorState_allowMultipleSelections:
|
||||
stateMod.EditorState.allowMultipleSelections,
|
||||
EditorState_readOnly: stateMod.EditorState.readOnly,
|
||||
Compartment: stateMod.Compartment,
|
||||
|
||||
markdown: markdownMod?.markdown,
|
||||
markdownLanguage: markdownMod?.markdownLanguage,
|
||||
|
||||
@@ -11,7 +11,7 @@ import { ensure_CodeMirror_modules } from './codemirror_modules';
|
||||
// import type { key_val } from '$lib/stores/ae_stores';
|
||||
|
||||
// Icons (Standardized to Lucide where possible, or FontAwesome placeholders)
|
||||
import { Bold, Code, Italic, List } from '@lucide/svelte';
|
||||
import { Bold, Code, Hash, Italic, List } from '@lucide/svelte';
|
||||
interface Props {
|
||||
content?: string | null;
|
||||
new_content?: string;
|
||||
@@ -42,6 +42,8 @@ let {
|
||||
|
||||
let editor_container: HTMLDivElement | undefined = $state();
|
||||
let cm: any = $state(); // CodeMirror modules cache
|
||||
let show_line_nums = $state(untrack(() => show_line_numbers));
|
||||
let ln_compartment: any = null;
|
||||
|
||||
async function create_editor() {
|
||||
if (!browser) return;
|
||||
@@ -55,6 +57,8 @@ async function create_editor() {
|
||||
editor_view = null;
|
||||
}
|
||||
|
||||
ln_compartment = new cm.Compartment();
|
||||
|
||||
const extensions = [
|
||||
cm.highlightSpecialChars(),
|
||||
cm.history(),
|
||||
@@ -70,8 +74,9 @@ async function create_editor() {
|
||||
cm.highlightActiveLine(),
|
||||
cm.highlightActiveLineGutter(),
|
||||
|
||||
// Keymaps
|
||||
// Keymaps — indentWithTab must come before defaultKeymap
|
||||
cm.keymap.of([
|
||||
cm.indentWithTab,
|
||||
...cm.defaultKeymap,
|
||||
...cm.searchKeymap,
|
||||
...cm.historyKeymap,
|
||||
@@ -80,6 +85,9 @@ async function create_editor() {
|
||||
...cm.lintKeymap
|
||||
]),
|
||||
|
||||
// 4-space indentation unit
|
||||
cm.indentUnit.of(' '),
|
||||
|
||||
// Language Support
|
||||
language === 'markdown'
|
||||
? cm.markdown({ base: cm.markdownLanguage })
|
||||
@@ -94,7 +102,7 @@ async function create_editor() {
|
||||
readonly
|
||||
? cm.EditorState.readOnly.of(true)
|
||||
: cm.EditorView.editable.of(true),
|
||||
show_line_numbers ? cm.lineNumbers() : null,
|
||||
ln_compartment.of(show_line_nums ? cm.lineNumbers() : []),
|
||||
wrap_lines ? cm.EditorView_lineWrapping : null,
|
||||
placeholder ? cm.placeholderExt(placeholder) : null,
|
||||
|
||||
@@ -144,6 +152,14 @@ $effect(() => {
|
||||
}
|
||||
});
|
||||
|
||||
// Toggle line numbers without rebuilding the editor
|
||||
$effect(() => {
|
||||
if (!editor_view || !ln_compartment || !cm) return;
|
||||
editor_view.dispatch({
|
||||
effects: ln_compartment.reconfigure(show_line_nums ? cm.lineNumbers() : [])
|
||||
});
|
||||
});
|
||||
|
||||
// *** Toolbar Helpers
|
||||
const wrap_selection = (before: string, after: string = before) => {
|
||||
if (!editor_view) return;
|
||||
@@ -244,6 +260,15 @@ const toggle_list = () => {
|
||||
</button>
|
||||
|
||||
<div class="ml-auto flex gap-1">
|
||||
<button
|
||||
type="button"
|
||||
class="btn btn-sm {show_line_nums
|
||||
? 'variant-filled-primary'
|
||||
: 'variant-soft'} hover:variant-filled-primary"
|
||||
onclick={() => (show_line_nums = !show_line_nums)}
|
||||
title="Toggle Line Numbers">
|
||||
<Hash size="14" />
|
||||
</button>
|
||||
<span
|
||||
class="mr-2 self-center text-[10px] font-bold uppercase opacity-50"
|
||||
>{language}</span>
|
||||
|
||||
Reference in New Issue
Block a user