Files
fiddle/public/js/keybindings.js
root e41c3e7dc4 Add browse dashboard, tags, visibility control, export, QR sharing, and embed mode
- Browse dashboard at / with search, framework filter, tag pills, and pagination
- Tags system with autocomplete datalist and per-fiddle tag management
- Listed/unlisted toggle for visibility control (unlisted still accessible via direct URL)
- Export standalone HTML with inlined CSS/JS and framework CDN tags
- QR code modal for sharing fiddle URLs
- Embed mode at /embed/:id for minimal preview-only rendering
- Extract shared loadScript() utility from 4 files into utils.js
- Database schema: listed column, tags and fiddle_tags tables with index
2026-02-26 14:19:52 -06:00

98 lines
2.5 KiB
JavaScript

import { getPref, setPref } from './preferences.js';
import { getActiveEditor, setOnTabSwitch, setOnModeChange } from './editors.js';
import { loadScript } from './utils.js';
let currentMode = 'default'; // 'default' | 'vim' | 'emacs'
let activeAdapter = null; // vim or emacs adapter instance
let vimLoaded = false;
let emacsLoaded = false;
const statusBar = () => document.getElementById('vim-status-bar');
async function ensureVim() {
if (vimLoaded) return;
window.monaco = monaco;
await loadScript('https://unpkg.com/monaco-vim@0.4.2/dist/monaco-vim.js');
vimLoaded = true;
}
async function ensureEmacs() {
if (emacsLoaded) return;
window.monaco = monaco;
await loadScript('https://unpkg.com/monaco-emacs/dist/monaco-emacs.js');
emacsLoaded = true;
}
function disposeAdapter() {
if (activeAdapter) {
activeAdapter.dispose();
activeAdapter = null;
}
const bar = statusBar();
if (bar) {
bar.style.display = 'none';
bar.textContent = '';
}
}
async function attachToEditor(editor) {
if (!editor) return;
disposeAdapter();
if (currentMode === 'vim') {
await ensureVim();
const bar = statusBar();
if (bar) bar.style.display = 'block';
activeAdapter = MonacoVim.initVimMode(editor, bar);
} else if (currentMode === 'emacs') {
await ensureEmacs();
const EmacsExtension = MonacoEmacs.EmacsExtension;
activeAdapter = new EmacsExtension(editor);
activeAdapter.start();
}
}
export async function setKeybindingMode(mode) {
disposeAdapter();
currentMode = mode;
setPref('keybindings', mode);
if (mode === 'default') return;
const editor = getActiveEditor();
if (editor) await attachToEditor(editor);
}
export function initKeybindings() {
currentMode = getPref('keybindings') || 'default';
const select = document.getElementById('keybinding-mode');
if (select) {
select.value = currentMode;
select.addEventListener('change', (e) => setKeybindingMode(e.target.value));
}
// Reattach on tab switch
setOnTabSwitch((_tabId, editor) => {
if (currentMode !== 'default' && editor) {
attachToEditor(editor);
}
});
// Reattach on mode change
setOnModeChange(() => {
if (currentMode !== 'default') {
setTimeout(() => {
const editor = getActiveEditor();
if (editor) attachToEditor(editor);
}, 50);
}
});
// Initial attach if non-default
if (currentMode !== 'default') {
const editor = getActiveEditor();
if (editor) attachToEditor(editor);
}
}