feat: enhance auto mode service and UI components for branch handling and verification

- Added a new function to retrieve the current branch name in the auto mode service, improving branch management.
- Updated the `getRunningCountForWorktree` method to utilize the current branch name for accurate feature counting.
- Modified UI components to include a toggle for skipping verification in auto mode, enhancing user control.
- Refactored various hooks and components to ensure consistent handling of branch names across the application.
- Introduced a new utility file for string operations, providing common functions for text manipulation.
This commit is contained in:
webdevcody
2026-01-20 13:39:38 -05:00
parent 2ab78dd590
commit 8facdc66a9
10 changed files with 337 additions and 94 deletions

View File

@@ -0,0 +1,178 @@
/**
* String utility functions for common text operations
*/
/**
* Truncate a string to a maximum length, adding an ellipsis if truncated
* @param str - The string to truncate
* @param maxLength - Maximum length of the result (including ellipsis)
* @param ellipsis - The ellipsis string to use (default: '...')
* @returns The truncated string
*/
export function truncate(str: string, maxLength: number, ellipsis: string = '...'): string {
if (maxLength < ellipsis.length) {
throw new Error(
`maxLength (${maxLength}) must be at least the length of ellipsis (${ellipsis.length})`
);
}
if (str.length <= maxLength) {
return str;
}
return str.slice(0, maxLength - ellipsis.length) + ellipsis;
}
/**
* Convert a string to kebab-case (e.g., "Hello World" -> "hello-world")
* @param str - The string to convert
* @returns The kebab-case string
*/
export function toKebabCase(str: string): string {
return str
.replace(/([a-z])([A-Z])/g, '$1-$2') // camelCase -> camel-Case
.replace(/[\s_]+/g, '-') // spaces and underscores -> hyphens
.replace(/[^a-zA-Z0-9-]/g, '') // remove non-alphanumeric (except hyphens)
.replace(/-+/g, '-') // collapse multiple hyphens
.replace(/^-|-$/g, '') // remove leading/trailing hyphens
.toLowerCase();
}
/**
* Convert a string to camelCase (e.g., "hello-world" -> "helloWorld")
* @param str - The string to convert
* @returns The camelCase string
*/
export function toCamelCase(str: string): string {
return str
.replace(/[^a-zA-Z0-9\s_-]/g, '') // remove special characters
.replace(/[-_\s]+(.)?/g, (_, char) => (char ? char.toUpperCase() : ''))
.replace(/^[A-Z]/, (char) => char.toLowerCase());
}
/**
* Convert a string to PascalCase (e.g., "hello-world" -> "HelloWorld")
* @param str - The string to convert
* @returns The PascalCase string
*/
export function toPascalCase(str: string): string {
const camel = toCamelCase(str);
return camel.charAt(0).toUpperCase() + camel.slice(1);
}
/**
* Capitalize the first letter of a string
* @param str - The string to capitalize
* @returns The string with first letter capitalized
*/
export function capitalize(str: string): string {
if (str.length === 0) {
return str;
}
return str.charAt(0).toUpperCase() + str.slice(1);
}
/**
* Remove duplicate whitespace from a string, preserving single spaces
* @param str - The string to clean
* @returns The string with duplicate whitespace removed
*/
export function collapseWhitespace(str: string): string {
return str.replace(/\s+/g, ' ').trim();
}
/**
* Check if a string is empty or contains only whitespace
* @param str - The string to check
* @returns True if the string is blank
*/
export function isBlank(str: string | null | undefined): boolean {
return str === null || str === undefined || str.trim().length === 0;
}
/**
* Check if a string is not empty and contains non-whitespace characters
* @param str - The string to check
* @returns True if the string is not blank
*/
export function isNotBlank(str: string | null | undefined): boolean {
return !isBlank(str);
}
/**
* Safely parse a string to an integer, returning a default value on failure
* @param str - The string to parse
* @param defaultValue - The default value if parsing fails (default: 0)
* @returns The parsed integer or the default value
*/
export function safeParseInt(str: string | null | undefined, defaultValue: number = 0): number {
if (isBlank(str)) {
return defaultValue;
}
const parsed = parseInt(str!, 10);
return isNaN(parsed) ? defaultValue : parsed;
}
/**
* Generate a slug from a string (URL-friendly identifier)
* @param str - The string to convert to a slug
* @param maxLength - Optional maximum length for the slug
* @returns The slugified string
*/
export function slugify(str: string, maxLength?: number): string {
let slug = str
.toLowerCase()
.normalize('NFD') // Normalize unicode characters
.replace(/[\u0300-\u036f]/g, '') // Remove diacritics
.replace(/[^a-z0-9\s-]/g, '') // Remove non-alphanumeric
.replace(/\s+/g, '-') // Replace spaces with hyphens
.replace(/-+/g, '-') // Collapse multiple hyphens
.replace(/^-|-$/g, ''); // Remove leading/trailing hyphens
if (maxLength !== undefined && slug.length > maxLength) {
// Truncate at word boundary if possible
slug = slug.slice(0, maxLength);
const lastHyphen = slug.lastIndexOf('-');
if (lastHyphen > maxLength * 0.5) {
slug = slug.slice(0, lastHyphen);
}
slug = slug.replace(/-$/g, ''); // Remove trailing hyphen after truncation
}
return slug;
}
/**
* Escape special regex characters in a string
* @param str - The string to escape
* @returns The escaped string safe for use in a RegExp
*/
export function escapeRegex(str: string): string {
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
/**
* Pluralize a word based on count
* @param word - The singular form of the word
* @param count - The count to base pluralization on
* @param pluralForm - Optional custom plural form (default: word + 's')
* @returns The word in singular or plural form
*/
export function pluralize(word: string, count: number, pluralForm?: string): string {
if (count === 1) {
return word;
}
return pluralForm || `${word}s`;
}
/**
* Format a count with its associated word (e.g., "1 item", "3 items")
* @param count - The count
* @param singular - The singular form of the word
* @param plural - Optional custom plural form
* @returns Formatted string with count and word
*/
export function formatCount(count: number, singular: string, plural?: string): string {
return `${count} ${pluralize(singular, count, plural)}`;
}