@keylog-parser/core
v1.0.0
Published
Modular, plugin-based keylog parser library with infinite extensibility
Maintainers
Readme
🔐 Keylog Parser
A powerful, extensible keylog parser with plugin architecture for desktop and mobile platforms. Parse keystroke logs from any format into readable text with full TypeScript support.
Features
✅ Zero Configuration - Works immediately with sensible defaults ✅ Cross-Platform - Desktop (US QWERTY) & Mobile (Android) support ✅ Plugin Architecture - 5 plugin types for infinite extensibility ✅ International Input - IME, dead keys, accents (é, ñ, ä, ç) ✅ Full TypeScript - Complete type safety and IntelliSense ✅ Event-Driven - Real-time parsing events ✅ Cursor Tracking - Optional position and selection tracking ✅ High Performance - Built-in metrics and optimization
Installation
npm install @keylog-parser/coreQuick Start
import { parseKeylog } from '@keylog-parser/core';
// Parse keystroke logs to text - one line!
const text = parseKeylog("[SHIFT]hello[SHIFT][Space]world[Enter]");
// Returns: "Hello world\n"No configuration needed! Ready to use out of the box.
API
Simple API
import { parseKeylog, parseKeylogFull, getKeylogStats } from '@keylog-parser/core';
// Get text only
const text = parseKeylog("[A][B][C]");
// "abc"
// Get statistics only
const stats = getKeylogStats("[SHIFT]hello[SHIFT][Enter]");
// { totalKeys: 7, characters: 5, words: 1, lines: 2, ... }
// Get full result with text, stats, state, and performance
const result = parseKeylogFull("[SHIFT]hello[SHIFT][Enter]");
// {
// text: "Hello\n",
// stats: { totalKeys: 7, characters: 5, ... },
// state: { modifiers: {...}, cursor: {...}, ... },
// performance: { duration: 2.5, tokensProcessed: 7, ... }
// }Advanced Configuration
import { KeylogParser } from '@keylog-parser/core';
import {
bracketFormat,
usQwertyLayout,
androidQwertyLayout,
modifierHandler,
clipboardHandler,
basicKeysHandler
} from '@keylog-parser/core';
const parser = new KeylogParser()
.use(bracketFormat)
.use(usQwertyLayout) // Desktop keyboard
// .use(androidQwertyLayout) // Or mobile keyboard
.use(modifierHandler)
.use(clipboardHandler)
.use(basicKeysHandler)
.configure({
trackCursor: true,
extractMetadata: true,
enableDeadKeys: true,
debug: false,
});
const result = parser.parse(keylogData);Platform Support
Desktop (US QWERTY)
import { usQwertyLayout } from '@keylog-parser/core';
const parser = new KeylogParser().use(usQwertyLayout);
const text = parseKeylog("[SHIFT]h[SHIFT]ello");
// "Hello"Mobile (Android)
import { androidQwertyLayout } from '@keylog-parser/core';
const parser = new KeylogParser().use(androidQwertyLayout);
const text = parseKeylog("[SHIFT]h[SHIFT]ello[Space]world");
// "Hello world"Android virtual keyboard fully supported with identical shift mapping and special character handling.
Plugin System
Plugin Types
| Type | Purpose | Examples |
|------|---------|----------|
| Format | Tokenize raw input | [KEY], <KEY>, JSON |
| Layout | Map keys to characters | QWERTY, AZERTY, Android |
| Handler | Process special keys | Modifiers, clipboard, IME |
| Metadata | Extract metadata | Timestamps, window titles |
| Transform | Post-process output | Trim, uppercase, cleanup |
Built-in Plugins
Formats:
bracketFormat- Parse[KEY]format (default)
Layouts:
usQwertyLayout- US QWERTY desktop keyboardandroidQwertyLayout- Android virtual keyboard
Handlers:
modifierHandler- Shift, Ctrl, Alt, Meta/WinclipboardHandler- Copy, Cut, Paste operationsbasicKeysHandler- Space, Enter, Backspace, Tab, navigation keysletterKeyHandler- Single-letter key processingcursorTrackingHandler- Arrow keys and cursor positiondeadKeyHandler- Accent composition (é, ñ, ä)
Creating Custom Plugins
Format Plugin
import { FormatPlugin } from '@keylog-parser/core';
const angleFormat: FormatPlugin = {
name: 'angle-format',
version: '1.0.0',
type: 'format',
priority: 10,
tokenize(input: string, state: ParserState): Token[] {
// Parse <KEY> format
const regex = /<([^>]+)>/g;
const tokens: Token[] = [];
let match;
while ((match = regex.exec(input)) !== null) {
tokens.push({
type: 'key',
value: match[1],
raw: match[0]
});
}
return tokens;
},
canHandle(input: string): number {
// Return confidence 0-1
return input.includes('<') && input.includes('>') ? 0.9 : 0;
}
};
parser.use(angleFormat);Layout Plugin
import { LayoutPlugin } from '@keylog-parser/core';
const azertyLayout: LayoutPlugin = {
name: 'fr-azerty',
version: '1.0.0',
type: 'layout',
locale: 'fr-FR',
priority: 10,
mapKey(key: string, modifiers: ModifierState): string | null {
if (key.length === 1) {
if (modifiers.shift && key === '1') return '&';
if (modifiers.shift && key === 'a') return 'A';
return key;
}
return null;
},
getShiftChar(key: string): string | null {
const map: Record<string, string> = {
'1': '&', '2': 'é', '3': '"', '4': "'", '5': '(',
'6': '-', '7': 'è', '8': '_', '9': 'ç', '0': 'à'
};
return map[key] || null;
}
};
parser.use(azertyLayout);Handler Plugin
import { HandlerPlugin } from '@keylog-parser/core';
const emojiHandler: HandlerPlugin = {
name: 'emoji-handler',
version: '1.0.0',
type: 'handler',
priority: 60,
process(token: Token, state: ParserState): Token | null {
if (token.type === 'key' && token.value === 'Heart') {
return { ...token, type: 'text', value: '❤️' };
}
return token;
},
canProcess(token: Token): boolean {
return token.type === 'key' && token.value === 'Heart';
}
};
parser.use(emojiHandler);Transform Plugin
import { TransformPlugin } from '@keylog-parser/core';
const cleanupTransform: TransformPlugin = {
name: 'cleanup',
version: '1.0.0',
type: 'transform',
priority: 100,
transform(output: string, state: ParserState): string {
return output.trim().replace(/\s+/g, ' ');
}
};
parser.use(cleanupTransform);Advanced Features
Event System
parser
.on('parse:start', (data) => console.log('Parsing started'))
.on('parse:end', (result) => console.log('Parsing complete'))
.on('token:processed', ({ token, index }) => console.log('Token:', token))
.on('error', (error) => console.error('Error:', error));
const result = parser.parse(keylog);Clipboard Operations
const input = 'hello[Ctrl+C][Ctrl+V][Space]world';
const result = parseKeylog(input);
console.log(result);
// "hellohello world"Cursor Tracking
const result = parseKeylogFull('[A][B][C][Left][Left]', {
trackCursor: true
});
console.log(result.cursor);
// { line: 0, column: 1, absolute: 1 }Dead Key Composition
const input = "[´][e][~][n]"; // Accent + letter
const result = parseKeylog(input, { enableDeadKeys: true });
console.log(result);
// "éñ"Metadata Extraction
import { MetadataPlugin } from '@keylog-parser/core';
const timestampPlugin: MetadataPlugin = {
name: 'timestamp-parser',
version: '1.0.0',
type: 'metadata',
priority: 1,
extract(token: Token): Record<string, any> | null {
if (token.type === 'metadata' && token.value.startsWith('Timestamp:')) {
return {
timestamp: new Date(token.value.split(':')[1])
};
}
return null;
}
};
parser.use(timestampPlugin);
const result = parser.parse('[Timestamp:2024-01-01T12:00:00Z][A][B]', {
extractMetadata: true
});
console.log(result.metadata);
// { timestamp: Date(...) }Performance Metrics
const result = parseKeylogFull(largeKeylog);
console.log(result.performance);
// {
// duration: 42.5, // ms
// tokensProcessed: 15234,
// pluginsExecuted: 5
// }Configuration Options
interface ParserConfig {
trackCursor?: boolean; // Track cursor position
trackSelection?: boolean; // Track text selection
extractMetadata?: boolean; // Extract metadata
enableIME?: boolean; // IME composition support
enableDeadKeys?: boolean; // Dead key composition
strict?: boolean; // Strict error mode
debug?: boolean; // Debug logging
}Architecture
Parser Pipeline:
┌─────────┐ ┌────────────────┐ ┌──────────────────┐ ┌──────────────┐
│ Input │ -> │ Format Plugins │ -> │ Layout + Handler │ -> │ Transform │ -> Result
└─────────┘ └────────────────┘ └──────────────────┘ └──────────────┘
↓
┌──────────────────┐
│ Metadata Plugins │
└──────────────────┘- Format plugins tokenize raw input into structured tokens
- Layout plugins map keys to characters based on keyboard layout
- Handler plugins process special keys (modifiers, clipboard, etc.)
- Metadata plugins extract metadata in parallel
- Transform plugins post-process the final output
Plugin Priority Guidelines
- Format: 1-50 (lower runs first)
- Modifier handlers: 1-10
- Clipboard handlers: 10-20
- Letter/Basic handlers: 40-50
- Complex handlers (IME, Dead Keys): 80-100
- Transforms: 100+
Examples
Parse Real-World Keylog
const keylog = `
[SHIFT]h[SHIFT]ello[Space][SHIFT]w[SHIFT]orld[Enter]
[SHIFT]t[SHIFT]his[Space]is[Space]a[Space]test[Enter]
[Ctrl+C][Ctrl+V]
`;
const result = parseKeylogFull(keylog);
console.log(result.text);
// "Hello World\nThis is a test\nThis is a test"
console.log(result.stats);
// {
// totalKeys: 45,
// characters: 35,
// words: 8,
// lines: 3,
// ...
// }Multi-Platform Support
// Desktop parser
const desktopParser = new KeylogParser()
.use(bracketFormat)
.use(usQwertyLayout)
.use(modifierHandler)
.use(basicKeysHandler);
// Mobile parser
const mobileParser = new KeylogParser()
.use(bracketFormat)
.use(androidQwertyLayout) // Android keyboard
.use(modifierHandler)
.use(basicKeysHandler);
// Use appropriate parser
const platform = detectPlatform();
const parser = platform === 'android' ? mobileParser : desktopParser;
const result = parser.parse(keylog);Testing
This library includes 371 comprehensive tests covering:
- Core parser functionality
- All plugin types
- Format tokenization
- Layout mappings
- Handler processing
- Integration scenarios
- Real-world edge cases
npm test # Run all tests
npm run test:watch # Watch mode
npm run test:coverage # Coverage reportContributing
Contributions are welcome! Please follow these guidelines:
Creating Plugins:
- Implement the appropriate plugin interface
- Set proper priority (lower = earlier execution)
- Handle errors gracefully
- Document your plugin with examples
Code Quality:
- Write TypeScript with strict mode
- Add tests for new features
- Follow existing code style
- Update documentation
Pull Requests:
- Describe changes clearly
- Include test coverage
- Update README if needed
License
MIT © [Your Name]
Support
Changelog
1.0.0 (2025-01-18)
- Initial release
- Desktop (US QWERTY) support
- Android virtual keyboard support
- 5 plugin types (format, layout, handler, metadata, transform)
- 371 comprehensive tests
- Full TypeScript support
- Event-driven architecture
- Cursor tracking
- Dead key composition
- Clipboard operations
