Skip to content

Commit 025e79c

Browse files
authored
Merge pull request #19 from LonoxX/develop
fix: Escape YAML special characters in issue/PR titles #18
2 parents 65ddd86 + 667ed83 commit 025e79c

8 files changed

Lines changed: 26 additions & 8 deletions

src/file-manager.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
createPullRequestTemplateData,
1212
processFilenameTemplate,
1313
processContentTemplate,
14-
extractNumberFromFilename
14+
extractNumberFromFilename,
15+
escapeYamlString
1516
} from "./util/templateUtils";
1617

1718
export class FileManager {
@@ -599,7 +600,7 @@ export class FileManager {
599600

600601
// Fallback to default template
601602
return `---
602-
title: "${escapeBody(issue.title, this.settings.escapeMode)}"
603+
title: "${escapeYamlString(issue.title)}"
603604
status: "${issue.state}"
604605
created: "${
605606
this.settings.dateFormat !== ""
@@ -655,7 +656,7 @@ ${this.formatComments(comments, this.settings.escapeMode)}
655656

656657
// Fallback to default template
657658
return `---
658-
title: "${escapeBody(pr.title, this.settings.escapeMode)}"
659+
title: "${escapeYamlString(pr.title)}"
659660
status: "${pr.state}"
660661
created: "${
661662
this.settings.dateFormat !== ""

src/util/escapeUtils.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,3 +48,13 @@ export function escapeBody(
4848
.replace(/{{/g, "((")
4949
.replace(/}}/g, "))");
5050
}
51+
52+
/**
53+
* Escape a string for use in YAML double-quoted strings
54+
* @param str The string to escape
55+
* @returns The escaped string
56+
*/
57+
export function escapeYamlString(str: string): string {
58+
// In YAML double-quoted strings, we need to escape backslashes and double quotes
59+
return str.replace(/\\/g, '\\\\').replace(/"/g, '\\"');
60+
}

src/util/templateUtils.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,14 @@
33
*/
44

55
import { format } from "date-fns";
6-
import { escapeBody } from "./escapeUtils";
6+
import { escapeBody , escapeYamlString} from "./escapeUtils";
77

88
/**
99
* Represents the data available for template replacement
1010
*/
1111
interface TemplateData {
1212
title: string;
13+
title_yaml: string;
1314
number: number;
1415
status: string;
1516
author: string;
@@ -128,6 +129,7 @@ export function processTemplate(
128129
// Available template variables:
129130
const replacements: Record<string, string> = {
130131
"{title}": data.title || "Untitled",
132+
"{title_yaml}": data.title_yaml || "Untitled",
131133
"{number}": data.number.toString(),
132134
"{status}": data.status || "unknown",
133135
"{state}": data.state || data.status || "unknown",
@@ -300,6 +302,7 @@ export function createIssueTemplateData(
300302

301303
return {
302304
title: issue.title || "Untitled",
305+
title_yaml: escapeYamlString(issue.title || "Untitled"),
303306
number: issue.number,
304307
status: issue.state || "unknown",
305308
state: issue.state || "unknown",
@@ -344,6 +347,7 @@ export function createPullRequestTemplateData(
344347

345348
return {
346349
title: pr.title || "Untitled",
350+
title_yaml: escapeYamlString(pr.title || "Untitled"),
347351
number: pr.number,
348352
status: pr.state || "unknown",
349353
state: pr.state || "unknown",
@@ -383,6 +387,7 @@ export function getTemplateHelp(): string {
383387
384388
Basic Information:
385389
• {title} - Issue/PR title
390+
• {title_yaml} - Issue/PR title (YAML-escaped for use in frontmatter)
386391
• {number} - Issue/PR number
387392
• {status} / {state} - Current status (open, closed, etc.)
388393
• {author} - Username who created the issue/PR
@@ -454,6 +459,7 @@ export function extractNumberFromFilename(filename: string, template: string): s
454459
// Replace template variables with regex patterns
455460
pattern = pattern.replace(/\\?\{number\}/g, '(\\d+)');
456461
pattern = pattern.replace(/\\?\{title\}/g, '.*?');
462+
pattern = pattern.replace(/\\?\{title_yaml\}/g, '.*?');
457463
pattern = pattern.replace(/\\?\{status\}/g, '\\w+');
458464
pattern = pattern.replace(/\\?\{author\}/g, '[^\\s]+');
459465
pattern = pattern.replace(/\\?\{assignee\}/g, '[^\\s]*');

templates/Template Variables Reference.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
| Variable | Description | Example |
66
|----------|-------------|---------|
77
| `{title}` | Issue/PR title | "Fix login bug" |
8+
| `{title_yaml}` | Issue/PR title (YAML-escaped) | "Fix \"login\" bug" |
89
| `{number}` | Issue/PR number | "123" |
910
| `{status}` | Current status | "open", "closed" |
1011
| `{state}` | Synonym for status | "open", "closed" |

templates/default-issue-template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: "{title}"
2+
title: "{title_yaml}"
33
status: "{status}"
44
created: "{created}"
55
url: "{url}"

templates/default-pr-template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: "{title}"
2+
title: "{title_yaml}"
33
status: "{status}"
44
created: "{created}"
55
url: "{url}"

templates/detailed-template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: "{title}"
2+
title: "{title_yaml}"
33
status: "{status}"
44
type: "{type}"
55
repository: "{repository}"

templates/minimal-template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
title: "{title}"
2+
title: "{title_yaml}"
33
status: "{status}"
44
created: "{created}"
55
url: "{url}"

0 commit comments

Comments
 (0)