-
-
Notifications
You must be signed in to change notification settings - Fork 279
Expand file tree
/
Copy pathstringUtils.ts
More file actions
82 lines (72 loc) · 3.01 KB
/
Copy pathstringUtils.ts
File metadata and controls
82 lines (72 loc) · 3.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
/**
* String utilities for display formatting and ID generation.
*/
/**
* Generates a UUID v4.
*
* Prefers `crypto.randomUUID()` (available in secure contexts, i.e. in HTTPS or localhost).
* Falls back to `crypto.getRandomValues()` for non-secure contexts.
*/
export function generateUUID(): string {
if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {
return crypto.randomUUID();
}
// UUID v4 via getRandomValues - available in non-secure contexts
const bytes = new Uint8Array(16);
crypto.getRandomValues(bytes);
bytes[6] = (bytes[6] & 0x0f) | 0x40; // version 4
bytes[8] = (bytes[8] & 0x3f) | 0x80; // variant bits
const hex = Array.from(bytes, (b) => b.toString(16).padStart(2, '0'));
return `${hex.slice(0, 4).join('')}-${hex.slice(4, 6).join('')}-${hex.slice(6, 8).join('')}-${hex.slice(8, 10).join('')}-${hex.slice(10).join('')}`;
}
/**
* Capitalizes the first character of a string, leaving the rest unchanged.
* Used for tool-name display labels so server tools like `advisor` render as `Advisor`
* while already-PascalCase names (Bash, Read, …) are unaffected.
*
* @example capitalize('advisor') → 'Advisor'
* @example capitalize('Bash') → 'Bash'
*/
export function capitalize(text: string): string {
if (!text) return text;
return text.charAt(0).toUpperCase() + text.slice(1);
}
const isMacPlatform =
typeof window !== 'undefined' && window.navigator.userAgent.includes('Macintosh');
/** Returns '⌘' on macOS, 'Ctrl' on Windows/Linux. */
export const modKey = isMacPlatform ? '⌘' : 'Ctrl+';
/** Returns '⇧' on macOS, 'Shift+' on Windows/Linux. */
export const shiftKey = isMacPlatform ? '⇧' : 'Shift+';
/**
* Formats a keyboard shortcut for the current platform.
* @example formatShortcut('R') → '⌘R' on Mac, 'Ctrl+R' on Windows/Linux
* @example formatShortcut('W', { shift: true }) → '⇧⌘W' on Mac, 'Ctrl+Shift+W' on Windows/Linux
*/
export function formatShortcut(key: string, opts?: { shift?: boolean }): string {
if (opts?.shift) {
return isMacPlatform ? `${shiftKey}${modKey}${key}` : `${modKey}${shiftKey}${key}`;
}
return `${modKey}${key}`;
}
/**
* Truncates a string in the middle to preserve both the beginning and end.
* Useful for branch names where the unique identifier is often at the end.
*
* @example
* truncateMiddle("feature/very-long-branch-name-with-ticket-12345", 25)
* // Returns: "feature/ver...ticket-12345"
*
* @param text - The string to truncate
* @param maxLen - Maximum length of the resulting string (default: 25)
* @returns The truncated string with "..." in the middle, or original if short enough
*/
export function truncateMiddle(text: string, maxLen: number = 25): string {
if (!text || text.length <= maxLen) return text;
// Account for the 3-character ellipsis
const availableChars = maxLen - 3;
const startLen = Math.ceil(availableChars / 2);
const endLen = Math.floor(availableChars / 2);
const start = text.slice(0, startLen);
const end = text.slice(-endLen);
return `${start}...${end}`;
}