Skip to content

Commit 2fe1001

Browse files
Copilotpelikhan
andcommitted
refactor: extract fastParseTitle function and add tests
Co-authored-by: pelikhan <4175913+pelikhan@users.noreply.github.com>
1 parent 1b80894 commit 2fe1001

File tree

2 files changed

+134
-15
lines changed

2 files changed

+134
-15
lines changed

pkg/cli/commands_utils_test.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,113 @@ func TestExtractWorkflowNameFromFile_NonExistentFile(t *testing.T) {
113113
}
114114
}
115115

116+
func TestFastParseTitle(t *testing.T) {
117+
tests := []struct {
118+
name string
119+
content string
120+
expected string
121+
expectError bool
122+
}{
123+
{
124+
name: "H1 after frontmatter",
125+
content: `---
126+
title: Test
127+
---
128+
129+
# My Workflow Title
130+
131+
Some content.`,
132+
expected: "My Workflow Title",
133+
},
134+
{
135+
name: "H1 with trailing spaces",
136+
content: `---
137+
engine: copilot
138+
---
139+
140+
# Weekly Research
141+
142+
Content here.`,
143+
expected: "Weekly Research",
144+
},
145+
{
146+
name: "H1 without frontmatter",
147+
content: `# Simple Title
148+
149+
No frontmatter here.`,
150+
expected: "Simple Title",
151+
},
152+
{
153+
name: "H1 is first line (no frontmatter)",
154+
content: `# Inline Title`,
155+
expected: "Inline Title",
156+
},
157+
{
158+
name: "no H1 header",
159+
content: "Just some text without headers.",
160+
expected: "",
161+
},
162+
{
163+
name: "only H2 headers",
164+
content: `---
165+
engine: copilot
166+
---
167+
168+
## Not an H1`,
169+
expected: "",
170+
},
171+
{
172+
name: "empty content",
173+
content: "",
174+
expected: "",
175+
},
176+
{
177+
name: "unclosed frontmatter returns error",
178+
content: `---
179+
title: Oops
180+
`,
181+
expectError: true,
182+
},
183+
{
184+
name: "dash in middle of content is not frontmatter",
185+
content: `Some text
186+
187+
---
188+
189+
# Not Skipped`,
190+
expected: "Not Skipped",
191+
},
192+
{
193+
name: "H1 inside frontmatter is ignored",
194+
content: `---
195+
# not a header
196+
---
197+
198+
# Real Title`,
199+
expected: "Real Title",
200+
},
201+
}
202+
203+
for _, tt := range tests {
204+
t.Run(tt.name, func(t *testing.T) {
205+
got, err := fastParseTitle(tt.content)
206+
if tt.expectError {
207+
if err == nil {
208+
t.Errorf("fastParseTitle(%q) expected error, got nil", tt.content)
209+
}
210+
return
211+
}
212+
if err != nil {
213+
t.Errorf("fastParseTitle(%q) unexpected error: %v", tt.content, err)
214+
return
215+
}
216+
if got != tt.expected {
217+
t.Errorf("fastParseTitle(%q) = %q, want %q", tt.content, got, tt.expected)
218+
}
219+
})
220+
}
221+
}
222+
116223
func TestIsGitRepo(t *testing.T) {
117224
// Test in current directory (should be a git repo based on project setup)
118225
result := isGitRepo()

pkg/cli/workflows.go

Lines changed: 27 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -282,24 +282,18 @@ func getMarkdownWorkflowFiles(workflowDir string) ([]string, error) {
282282
return mdFiles, nil
283283
}
284284

285-
// extractWorkflowNameFromFile extracts the workflow name from a file's H1 header
286-
func extractWorkflowNameFromFile(filePath string) (string, error) {
287-
content, err := os.ReadFile(filePath)
288-
if err != nil {
289-
return "", err
290-
}
291-
292-
// Scan lines directly: skip frontmatter block (between --- delimiters) without
293-
// YAML parsing, then find the first H1 header. This avoids the cost of a full
294-
// yaml.Unmarshal which is unnecessary when we only need the H1 title.
295-
//
296-
// Frontmatter is only recognised when "---" appears on the very first line,
297-
// matching the behaviour of ExtractFrontmatterFromContent.
298-
lines := strings.SplitSeq(string(content), "\n")
285+
// fastParseTitle scans markdown content for the first H1 header, skipping an
286+
// optional frontmatter block, without performing a full YAML parse.
287+
//
288+
// Frontmatter is recognised only when "---" appears on the very first line
289+
// (matching the behaviour of ExtractFrontmatterFromContent). Returns the H1
290+
// title text, or ("", nil) when no H1 header is present. Returns an error if
291+
// frontmatter is opened but never closed.
292+
func fastParseTitle(content string) (string, error) {
299293
firstLine := true
300294
inFrontmatter := false
301295
pastFrontmatter := false
302-
for line := range lines {
296+
for line := range strings.SplitSeq(content, "\n") {
303297
trimmed := strings.TrimSpace(line)
304298
if firstLine {
305299
firstLine = false
@@ -325,6 +319,24 @@ func extractWorkflowNameFromFile(filePath string) (string, error) {
325319
return "", errors.New("frontmatter not properly closed")
326320
}
327321

322+
return "", nil
323+
}
324+
325+
// extractWorkflowNameFromFile extracts the workflow name from a file's H1 header
326+
func extractWorkflowNameFromFile(filePath string) (string, error) {
327+
content, err := os.ReadFile(filePath)
328+
if err != nil {
329+
return "", err
330+
}
331+
332+
title, err := fastParseTitle(string(content))
333+
if err != nil {
334+
return "", err
335+
}
336+
if title != "" {
337+
return title, nil
338+
}
339+
328340
// No H1 header found, generate default name from filename
329341
baseName := filepath.Base(filePath)
330342
baseName = strings.TrimSuffix(baseName, filepath.Ext(baseName))

0 commit comments

Comments
 (0)