Skip to main content
Glama
index.ts3.53 kB
/** * Script loader for webview injection scripts * * These scripts are loaded at build time and injected into the webview at runtime. * Each script is an IIFE that accepts a params object. */ import { readFileSync } from 'fs'; import { dirname, join } from 'path'; import { fileURLToPath } from 'url'; const currentDir = dirname(fileURLToPath(import.meta.url)); function loadScript(name: string): string { return readFileSync(join(currentDir, `${name}.js`), 'utf-8'); } // Load scripts once at module initialization export const SCRIPTS = { interact: loadScript('interact'), swipe: loadScript('swipe'), keyboard: loadScript('keyboard'), waitFor: loadScript('wait-for'), getStyles: loadScript('get-styles'), focus: loadScript('focus'), findElement: loadScript('find-element'), } as const; /** * Build a script invocation with parameters * The script should be an IIFE that accepts a params object */ export function buildScript(script: string, params: Record<string, unknown>): string { return `(${script})(${JSON.stringify(params)})`; } /** * Build a script for typing text (uses the keyboard script's typeText function) */ export function buildTypeScript(selector: string, text: string): string { const escapedText = text.replace(/\\/g, '\\\\').replace(/'/g, "\\'"); return ` (function() { const selector = '${selector}'; const text = '${escapedText}'; const element = document.querySelector(selector); if (!element) { throw new Error('Element not found: ' + selector); } element.focus(); element.value = text; element.dispatchEvent(new Event('input', { bubbles: true })); element.dispatchEvent(new Event('change', { bubbles: true })); return 'Typed "' + text + '" into ' + selector; })() `; } /** * Build a script for key events (press, down, up) */ export function buildKeyEventScript( action: string, key: string, modifiers: string[] = [] ): string { return ` (function() { const action = '${action}'; const key = '${key}'; const modifiers = ${JSON.stringify(modifiers)}; const eventOptions = { key: key, code: key, bubbles: true, cancelable: true, ctrlKey: modifiers.includes('Control'), altKey: modifiers.includes('Alt'), shiftKey: modifiers.includes('Shift'), metaKey: modifiers.includes('Meta'), }; const activeElement = document.activeElement || document.body; if (action === 'press') { activeElement.dispatchEvent(new KeyboardEvent('keydown', eventOptions)); activeElement.dispatchEvent(new KeyboardEvent('keypress', eventOptions)); activeElement.dispatchEvent(new KeyboardEvent('keyup', eventOptions)); return 'Pressed key: ' + key + (modifiers.length ? ' with ' + modifiers.join('+') : ''); } else if (action === 'down') { activeElement.dispatchEvent(new KeyboardEvent('keydown', eventOptions)); return 'Key down: ' + key + (modifiers.length ? ' with ' + modifiers.join('+') : ''); } else if (action === 'up') { activeElement.dispatchEvent(new KeyboardEvent('keyup', eventOptions)); return 'Key up: ' + key + (modifiers.length ? ' with ' + modifiers.join('+') : ''); } throw new Error('Unknown action: ' + action); })() `; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/hypothesi/mcp-server-tauri'

If you have feedback or need assistance with the MCP directory API, please join our Discord server