refactor(frontend): extract keybinding utilities
This commit is contained in:
@@ -1,44 +1,10 @@
|
||||
import fs from 'node:fs';
|
||||
import path from 'node:path';
|
||||
import test from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
|
||||
const projectRoot = path.resolve(import.meta.dirname, '..');
|
||||
const modelResolverSource = fs.readFileSync(
|
||||
path.join(projectRoot, 'web/resolver/model_resolver.js'),
|
||||
'utf8'
|
||||
);
|
||||
|
||||
function extractFunction(source, functionName) {
|
||||
const signature = new RegExp(`\\nfunction ${functionName}\\s*\\(`);
|
||||
const match = signature.exec(source);
|
||||
assert.ok(match, `Could not find ${functionName}`);
|
||||
const parenStart = source.indexOf('(', match.index);
|
||||
let parenDepth = 0;
|
||||
let parenEnd = -1;
|
||||
for (let i = parenStart; i < source.length; i += 1) {
|
||||
if (source[i] === '(') parenDepth += 1;
|
||||
if (source[i] === ')') parenDepth -= 1;
|
||||
if (parenDepth === 0) {
|
||||
parenEnd = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
const braceStart = source.indexOf('{', parenEnd);
|
||||
let braceDepth = 0;
|
||||
for (let i = braceStart; i < source.length; i += 1) {
|
||||
if (source[i] === '{') braceDepth += 1;
|
||||
if (source[i] === '}') braceDepth -= 1;
|
||||
if (braceDepth === 0) {
|
||||
return `function ${functionName}${source.slice(parenStart, parenEnd + 1)} ${source.slice(braceStart, i + 1)}`;
|
||||
}
|
||||
}
|
||||
throw new Error(`Could not parse ${functionName}`);
|
||||
}
|
||||
|
||||
const serializeKeybindingCombo = eval(`(${extractFunction(modelResolverSource, 'serializeKeybindingCombo')})`);
|
||||
const keybindingsEqual = eval(`(${extractFunction(modelResolverSource, 'keybindingsEqual')})`);
|
||||
const getComboLabel = eval(`(${extractFunction(modelResolverSource, 'getComboLabel')})`);
|
||||
import {
|
||||
serializeKeybindingCombo,
|
||||
keybindingsEqual,
|
||||
getComboLabel,
|
||||
} from '../web/resolver/utils/keybinding_utils.js';
|
||||
|
||||
test('keybinding serialization is stable for equivalent combos', () => {
|
||||
assert.equal(serializeKeybindingCombo({ key: 'k', ctrl: true, shift: false }), 'K:true:false:false');
|
||||
|
||||
@@ -6,6 +6,11 @@ import { logger as frontendLogger } from "../log_system/logger.js";
|
||||
import { loadStylesWhenNeeded } from "../utils/css_loader.js";
|
||||
import { ResolverManagerDialog } from "./resolver_dialog.js";
|
||||
import { showNotification } from "../utils/notification_utils.js";
|
||||
import {
|
||||
serializeKeybindingCombo,
|
||||
keybindingsEqual,
|
||||
getComboLabel,
|
||||
} from "./utils/keybinding_utils.js";
|
||||
import {
|
||||
buildModelResolverNodeMenu,
|
||||
getImmediateModelsForNode,
|
||||
@@ -52,51 +57,6 @@ function getKeybindingSetting(id) {
|
||||
}
|
||||
}
|
||||
|
||||
function serializeKeybindingCombo(combo = {}) {
|
||||
return [
|
||||
String(combo.key || "").toUpperCase(),
|
||||
String(Boolean(combo.ctrl)),
|
||||
String(Boolean(combo.alt)),
|
||||
String(Boolean(combo.shift)),
|
||||
].join(":");
|
||||
}
|
||||
|
||||
function keybindingsEqual(left, right) {
|
||||
return Boolean(
|
||||
left
|
||||
&& right
|
||||
&& left.commandId === right.commandId
|
||||
&& (left.targetElementId || "") === (right.targetElementId || "")
|
||||
&& serializeKeybindingCombo(left.combo) === serializeKeybindingCombo(right.combo)
|
||||
);
|
||||
}
|
||||
|
||||
function getComboLabel(combo = {}) {
|
||||
const parts = [];
|
||||
if (combo.ctrl) parts.push("Ctrl");
|
||||
if (combo.alt) parts.push("Alt");
|
||||
if (combo.shift) parts.push("Shift");
|
||||
|
||||
const keyLabels = {
|
||||
" ": "Space",
|
||||
ArrowUp: "Up",
|
||||
ArrowDown: "Down",
|
||||
ArrowLeft: "Left",
|
||||
ArrowRight: "Right",
|
||||
Backspace: "Backspace",
|
||||
Delete: "Delete",
|
||||
Enter: "Enter",
|
||||
Escape: "Esc",
|
||||
Tab: "Tab",
|
||||
};
|
||||
const key = String(combo.key || "").trim();
|
||||
if (key) {
|
||||
parts.push(keyLabels[key] || (key.length === 1 ? key.toUpperCase() : key));
|
||||
}
|
||||
|
||||
return parts.join("+");
|
||||
}
|
||||
|
||||
function applyStoredFrontendLoggingPreference() {
|
||||
const stored = localStorage.getItem('ModelResolver.frontendLogsEnabled');
|
||||
if (stored !== null) {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
export function serializeKeybindingCombo(combo = {}) {
|
||||
return [
|
||||
String(combo.key || "").toUpperCase(),
|
||||
String(Boolean(combo.ctrl)),
|
||||
String(Boolean(combo.alt)),
|
||||
String(Boolean(combo.shift)),
|
||||
].join(":");
|
||||
}
|
||||
|
||||
export function keybindingsEqual(left, right) {
|
||||
return Boolean(
|
||||
left
|
||||
&& right
|
||||
&& left.commandId === right.commandId
|
||||
&& (left.targetElementId || "") === (right.targetElementId || "")
|
||||
&& serializeKeybindingCombo(left.combo) === serializeKeybindingCombo(right.combo)
|
||||
);
|
||||
}
|
||||
|
||||
export function getComboLabel(combo = {}) {
|
||||
const parts = [];
|
||||
if (combo.ctrl) parts.push("Ctrl");
|
||||
if (combo.alt) parts.push("Alt");
|
||||
if (combo.shift) parts.push("Shift");
|
||||
|
||||
const keyLabels = {
|
||||
" ": "Space",
|
||||
ArrowUp: "Up",
|
||||
ArrowDown: "Down",
|
||||
ArrowLeft: "Left",
|
||||
ArrowRight: "Right",
|
||||
Backspace: "Backspace",
|
||||
Delete: "Delete",
|
||||
Enter: "Enter",
|
||||
Escape: "Esc",
|
||||
Tab: "Tab",
|
||||
};
|
||||
const key = String(combo.key || "").trim();
|
||||
if (key) {
|
||||
parts.push(keyLabels[key] || (key.length === 1 ? key.toUpperCase() : key));
|
||||
}
|
||||
|
||||
return parts.join("+");
|
||||
}
|
||||
Reference in New Issue
Block a user