Class: Ace::Git::Worktree::Atoms::SlugGenerator
- Inherits:
-
Object
- Object
- Ace::Git::Worktree::Atoms::SlugGenerator
- Defined in:
- lib/ace/git/worktree/atoms/slug_generator.rb
Overview
Slug generation atom
Converts task titles and other text into URL-safe slugs suitable for git branch names and directory names.
Constant Summary collapse
- DEFAULT_MAX_LENGTH =
Default maximum length for slugs
50- MIN_LENGTH =
Minimum length to avoid empty or too-short slugs
3- FORBIDDEN_CHARS =
Characters that are not allowed in git branch names
/[~\^*?\[\]:]/- SEPARATORS =
Characters to replace with hyphens
/[ ._\/\\()]+/- MULTIPLE_SEPARATORS =
Multiple consecutive non-word characters (but allow single hyphens)
/-{2,}|[^a-zA-Z0-9-]+/- TRIM_SEPARATORS =
Leading/trailing separators and hyphens
/^[-_]+|[-_]+$/
Class Method Summary collapse
-
.combined(task_id, title, max_length: DEFAULT_MAX_LENGTH) ⇒ String
Generate a combined slug from task ID and title.
-
.from_task_id(task_id) ⇒ String
Generate a slug for a task ID.
-
.from_title(title, max_length: DEFAULT_MAX_LENGTH, fallback: "task") ⇒ String
Generate a slug from a task title.
-
.sanitize(slug) ⇒ String
Sanitize an existing slug.
-
.to_directory_name(branch_name) ⇒ String
Convert a branch name to a safe directory name.
-
.valid?(slug) ⇒ Boolean
Check if a slug is valid for git branch names.
Class Method Details
.combined(task_id, title, max_length: DEFAULT_MAX_LENGTH) ⇒ String
Generate a combined slug from task ID and title
119 120 121 122 123 124 |
# File 'lib/ace/git/worktree/atoms/slug_generator.rb', line 119 def combined(task_id, title, max_length: DEFAULT_MAX_LENGTH) task_slug = from_task_id(task_id).gsub(/^task-/, "") title_slug = from_title(title, max_length: max_length - task_slug.length - 1) "#{task_slug}-#{title_slug}" end |
.from_task_id(task_id) ⇒ String
Generate a slug for a task ID
99 100 101 102 103 104 105 106 107 |
# File 'lib/ace/git/worktree/atoms/slug_generator.rb', line 99 def from_task_id(task_id) return "task" if task_id.nil? || task_id.empty? # Extract the numeric part from various task ID formats numeric_part = task_id.to_s.match(/(\d+)$/) return "task-#{task_id}" unless numeric_part "task-#{numeric_part[1]}" end |
.from_title(title, max_length: DEFAULT_MAX_LENGTH, fallback: "task") ⇒ String
Generate a slug from a task title
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 83 84 85 86 87 88 89 |
# File 'lib/ace/git/worktree/atoms/slug_generator.rb', line 52 def from_title(title, max_length: DEFAULT_MAX_LENGTH, fallback: "task") return fallback if title.nil? || title.empty? # Convert to string and strip whitespace title_str = title.to_s.strip # Remove forbidden characters that git doesn't allow in branch names cleaned = title_str.gsub(FORBIDDEN_CHARS, "") # Replace separators (spaces, dots, underscores, slashes) with hyphens normalized = cleaned.gsub(SEPARATORS, "-") # Remove any remaining non-alphanumeric characters except hyphens sanitized = normalized.gsub(MULTIPLE_SEPARATORS, "-") # Remove leading/trailing hyphens and underscores trimmed = sanitized.gsub(TRIM_SEPARATORS, "") # Convert to lowercase slug = trimmed.downcase # Handle empty or too-short result if slug.length < MIN_LENGTH slug = fallback end # Truncate to max length, avoiding cutting in the middle of a word if possible if slug.length > max_length slug = truncate_slug(slug, max_length) end # Final validation - ensure we still have a valid slug if slug.empty? || slug.length < MIN_LENGTH slug = fallback end slug end |
.sanitize(slug) ⇒ String
Sanitize an existing slug
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
# File 'lib/ace/git/worktree/atoms/slug_generator.rb', line 133 def sanitize(slug) return "task" if slug.nil? || slug.empty? slug_str = slug.to_s.strip # Remove forbidden characters cleaned = slug_str.gsub(FORBIDDEN_CHARS, "") # Replace separators with hyphens normalized = cleaned.gsub(SEPARATORS, "-") # Remove multiple consecutive separators sanitized = normalized.gsub(MULTIPLE_SEPARATORS, "-") # Trim leading/trailing separators trimmed = sanitized.gsub(TRIM_SEPARATORS, "") # Convert to lowercase slug = trimmed.downcase # Fallback if result is empty slug.empty? ? "task" : slug end |
.to_directory_name(branch_name) ⇒ String
Convert a branch name to a safe directory name
Sanitizes branch names for use as directory names by replacing characters that are not alphanumeric, hyphens, or underscores with hyphens. Also handles slash-separated branch names (e.g., “origin/feature/auth”).
177 178 179 180 181 182 |
# File 'lib/ace/git/worktree/atoms/slug_generator.rb', line 177 def to_directory_name(branch_name) return "worktree" if branch_name.nil? || branch_name.empty? # Replace slashes and any non-alphanumeric/hyphen/underscore with hyphens branch_name.to_s.tr("/", "-").gsub(/[^a-zA-Z0-9\-_]/, "-") end |
.valid?(slug) ⇒ Boolean
Check if a slug is valid for git branch names
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/ace/git/worktree/atoms/slug_generator.rb', line 192 def valid?(slug) return false if slug.nil? || slug.empty? return false if slug.length > 255 # Git branch name limit return false if slug.match?(FORBIDDEN_CHARS) return false if slug.start_with?("-") || slug.end_with?("-") return false if slug.include?(".") # Dots not allowed in git branch names return false if slug.include?(" ") # Spaces not allowed # Check for invalid git branch name patterns return false if slug == "HEAD" return false if slug.include?("..") return false if slug.include?("@") true end |