Skip to content

Commit 966777e

Browse files
Copilotalexr00
andcommitted
Add YAML issue template support
Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com>
1 parent c46c104 commit 966777e

File tree

6 files changed

+150
-5
lines changed

6 files changed

+150
-5
lines changed
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
name: Test YAML Template
2+
description: A test YAML issue template for verification
3+
title: "[Test]: "
4+
labels: ["test"]
5+
body:
6+
- type: markdown
7+
attributes:
8+
value: |
9+
Thanks for reporting this test issue!
10+
- type: input
11+
id: contact
12+
attributes:
13+
label: Contact Details
14+
description: How can we get in touch with you if we need more info?
15+
placeholder: ex. email@example.com
16+
validations:
17+
required: false
18+
- type: textarea
19+
id: what-happened
20+
attributes:
21+
label: What happened?
22+
description: Also tell us, what did you expect to happen?
23+
placeholder: Tell us what you see!
24+
value: "A bug happened!"
25+
validations:
26+
required: true
27+
- type: dropdown
28+
id: version
29+
attributes:
30+
label: Version
31+
description: What version of our software are you running?
32+
options:
33+
- 1.0.0
34+
- 1.1.0
35+
- 1.2.0
36+
validations:
37+
required: true
38+
- type: checkboxes
39+
id: terms
40+
attributes:
41+
label: Code of Conduct
42+
description: By submitting this issue, you agree to follow our Code of Conduct
43+
options:
44+
- label: I agree to follow this project's Code of Conduct
45+
required: true

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4351,6 +4351,7 @@
43514351
"@shikijs/monaco": "^3.7.0",
43524352
"@types/chai": "^4.1.4",
43534353
"@types/glob": "7.1.3",
4354+
"@types/js-yaml": "^4.0.9",
43544355
"@types/lru-cache": "^5.1.0",
43554356
"@types/marked": "^0.7.2",
43564357
"@types/mocha": "^8.2.2",
@@ -4452,4 +4453,4 @@
44524453
"string_decoder": "^1.3.0"
44534454
},
44544455
"license": "MIT"
4455-
}
4456+
}

src/github/folderRepositoryManager.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,10 +1346,13 @@ export class FolderRepositoryManager extends Disposable {
13461346
}
13471347

13481348
async getIssueTemplates(): Promise<vscode.Uri[]> {
1349-
const pattern = '{docs,.github}/ISSUE_TEMPLATE/*.md';
1350-
return vscode.workspace.findFiles(
1351-
new vscode.RelativePattern(this._repository.rootUri, pattern), null
1352-
);
1349+
const mdPattern = '{docs,.github}/ISSUE_TEMPLATE/*.md';
1350+
const ymlPattern = '{docs,.github}/ISSUE_TEMPLATE/*.yml';
1351+
const [mdTemplates, ymlTemplates] = await Promise.all([
1352+
vscode.workspace.findFiles(new vscode.RelativePattern(this._repository.rootUri, mdPattern), null),
1353+
vscode.workspace.findFiles(new vscode.RelativePattern(this._repository.rootUri, ymlPattern), null)
1354+
]);
1355+
return [...mdTemplates, ...ymlTemplates];
13531356
}
13541357

13551358
async getPullRequestTemplateBody(owner: string): Promise<string | undefined> {

src/issues/issueFeatureRegistrar.ts

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
*--------------------------------------------------------------------------------------------*/
55

66
import { basename } from 'path';
7+
import * as yaml from 'js-yaml';
78
import * as vscode from 'vscode';
89
import { CurrentIssue } from './currentIssue';
910
import { IssueCompletionProvider } from './issueCompletionProvider';
@@ -56,6 +57,7 @@ import {
5657
PermalinkInfo,
5758
pushAndCreatePR,
5859
USER_EXPRESSION,
60+
YamlIssueTemplate,
5961
} from './util';
6062
import { truncate } from '../common/utils';
6163
import { OctokitCommon } from '../github/common';
@@ -1250,13 +1252,77 @@ ${options?.body ?? ''}\n
12501252
}
12511253

12521254
private getDataFromTemplate(template: string): IssueTemplate {
1255+
// Try to parse as YAML first (YAML templates have a different structure)
1256+
try {
1257+
const parsed = yaml.load(template);
1258+
if (parsed && typeof parsed === 'object' && (parsed as YamlIssueTemplate).name) {
1259+
// This is a YAML template
1260+
return this.parseYamlTemplate(parsed as YamlIssueTemplate);
1261+
}
1262+
} catch (e) {
1263+
// Not a valid YAML, continue to Markdown parsing
1264+
}
1265+
1266+
// Parse as Markdown frontmatter template
12531267
const title = template.match(/title:\s*(.*)/)?.[1]?.replace(/^["']|["']$/g, '');
12541268
const name = template.match(/name:\s*(.*)/)?.[1]?.replace(/^["']|["']$/g, '');
12551269
const about = template.match(/about:\s*(.*)/)?.[1]?.replace(/^["']|["']$/g, '');
12561270
const body = template.match(/---([\s\S]*)---([\s\S]*)/)?.[2];
12571271
return { title, name, about, body };
12581272
}
12591273

1274+
private parseYamlTemplate(parsed: YamlIssueTemplate): IssueTemplate {
1275+
const name = parsed.name;
1276+
const about = parsed.description || parsed.about;
1277+
const title = parsed.title;
1278+
1279+
// Convert YAML body fields to markdown
1280+
let body = '';
1281+
if (parsed.body && Array.isArray(parsed.body)) {
1282+
for (const field of parsed.body) {
1283+
if (field.type === 'markdown' && field.attributes?.value) {
1284+
body += field.attributes.value + '\n\n';
1285+
} else if (field.type === 'textarea' && field.attributes?.label) {
1286+
body += `## ${field.attributes.label}\n\n`;
1287+
if (field.attributes.description) {
1288+
body += `${field.attributes.description}\n\n`;
1289+
}
1290+
if (field.attributes.placeholder) {
1291+
body += `${field.attributes.placeholder}\n\n`;
1292+
} else if (field.attributes.value) {
1293+
body += `${field.attributes.value}\n\n`;
1294+
}
1295+
} else if (field.type === 'input' && field.attributes?.label) {
1296+
body += `## ${field.attributes.label}\n\n`;
1297+
if (field.attributes.description) {
1298+
body += `${field.attributes.description}\n\n`;
1299+
}
1300+
if (field.attributes.placeholder) {
1301+
body += `${field.attributes.placeholder}\n\n`;
1302+
}
1303+
} else if (field.type === 'dropdown' && field.attributes?.label) {
1304+
body += `## ${field.attributes.label}\n\n`;
1305+
if (field.attributes.description) {
1306+
body += `${field.attributes.description}\n\n`;
1307+
}
1308+
if (field.attributes.options && Array.isArray(field.attributes.options)) {
1309+
body += field.attributes.options.map((opt: string) => `- ${opt}`).join('\n') + '\n\n';
1310+
}
1311+
} else if (field.type === 'checkboxes' && field.attributes?.label) {
1312+
body += `## ${field.attributes.label}\n\n`;
1313+
if (field.attributes.description) {
1314+
body += `${field.attributes.description}\n\n`;
1315+
}
1316+
if (field.attributes.options && Array.isArray(field.attributes.options)) {
1317+
body += field.attributes.options.map((opt: { label?: string } | string) => `- [ ] ${typeof opt === 'string' ? opt : opt.label || ''}`).join('\n') + '\n\n';
1318+
}
1319+
}
1320+
}
1321+
}
1322+
1323+
return { title, name, about, body: body.trim() || undefined };
1324+
}
1325+
12601326
private async doCreateIssue(
12611327
document: vscode.TextDocument | undefined,
12621328
newIssue: NewIssue | undefined,

src/issues/util.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,31 @@ export interface IssueTemplate {
9494
body: string | undefined
9595
}
9696

97+
export interface YamlIssueTemplate {
98+
name?: string;
99+
description?: string;
100+
about?: string;
101+
title?: string;
102+
labels?: string[];
103+
assignees?: string[];
104+
body?: YamlTemplateField[];
105+
}
106+
107+
export interface YamlTemplateField {
108+
type: 'markdown' | 'textarea' | 'input' | 'dropdown' | 'checkboxes';
109+
id?: string;
110+
attributes?: {
111+
label?: string;
112+
description?: string;
113+
placeholder?: string;
114+
value?: string;
115+
options?: (string | { label?: string; required?: boolean })[];
116+
};
117+
validations?: {
118+
required?: boolean;
119+
};
120+
}
121+
97122
const HEAD = 'HEAD';
98123
const UPSTREAM = 1;
99124
const UPS = 2;

yarn.lock

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -885,6 +885,11 @@
885885
"@types/istanbul-lib-coverage" "*"
886886
"@types/istanbul-lib-report" "*"
887887

888+
"@types/js-yaml@^4.0.9":
889+
version "4.0.9"
890+
resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.9.tgz#cd82382c4f902fed9691a2ed79ec68c5898af4c2"
891+
integrity sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==
892+
888893
"@types/json-schema@^7.0.15":
889894
version "7.0.15"
890895
resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841"

0 commit comments

Comments
 (0)