|
4 | 4 | *--------------------------------------------------------------------------------------------*/ |
5 | 5 |
|
6 | 6 | import { basename } from 'path'; |
| 7 | +import * as yaml from 'js-yaml'; |
7 | 8 | import * as vscode from 'vscode'; |
8 | 9 | import { CurrentIssue } from './currentIssue'; |
9 | 10 | import { IssueCompletionProvider } from './issueCompletionProvider'; |
@@ -57,6 +58,7 @@ import { |
57 | 58 | PermalinkInfo, |
58 | 59 | pushAndCreatePR, |
59 | 60 | USER_EXPRESSION, |
| 61 | + YamlIssueTemplate, |
60 | 62 | } from './util'; |
61 | 63 | import { truncate } from '../common/utils'; |
62 | 64 | import { OctokitCommon } from '../github/common'; |
@@ -1281,13 +1283,78 @@ ${options?.body ?? ''}\n |
1281 | 1283 | } |
1282 | 1284 |
|
1283 | 1285 | private getDataFromTemplate(template: string): IssueTemplate { |
| 1286 | + // Try to parse as YAML first (YAML templates have a different structure) |
| 1287 | + try { |
| 1288 | + const parsed = yaml.load(template); |
| 1289 | + // Check if it looks like a YAML issue template (has name and body fields) |
| 1290 | + if (parsed && typeof parsed === 'object' && (parsed as YamlIssueTemplate).name && (parsed as YamlIssueTemplate).body) { |
| 1291 | + // This is a YAML template |
| 1292 | + return this.parseYamlTemplate(parsed as YamlIssueTemplate); |
| 1293 | + } |
| 1294 | + } catch (e) { |
| 1295 | + // Not a valid YAML, continue to Markdown parsing |
| 1296 | + } |
| 1297 | + |
| 1298 | + // Parse as Markdown frontmatter template |
1284 | 1299 | const title = template.match(/title:\s*(.*)/)?.[1]?.replace(/^["']|["']$/g, ''); |
1285 | 1300 | const name = template.match(/name:\s*(.*)/)?.[1]?.replace(/^["']|["']$/g, ''); |
1286 | 1301 | const about = template.match(/about:\s*(.*)/)?.[1]?.replace(/^["']|["']$/g, ''); |
1287 | 1302 | const body = template.match(/---([\s\S]*)---([\s\S]*)/)?.[2]; |
1288 | 1303 | return { title, name, about, body }; |
1289 | 1304 | } |
1290 | 1305 |
|
| 1306 | + private parseYamlTemplate(parsed: YamlIssueTemplate): IssueTemplate { |
| 1307 | + const name = parsed.name; |
| 1308 | + const about = parsed.description || parsed.about; |
| 1309 | + const title = parsed.title; |
| 1310 | + |
| 1311 | + // Convert YAML body fields to markdown |
| 1312 | + let body = ''; |
| 1313 | + if (parsed.body && Array.isArray(parsed.body)) { |
| 1314 | + for (const field of parsed.body) { |
| 1315 | + if (field.type === 'markdown' && field.attributes?.value) { |
| 1316 | + body += field.attributes.value + '\n\n'; |
| 1317 | + } else if (field.type === 'textarea' && field.attributes?.label) { |
| 1318 | + body += `## ${field.attributes.label}\n\n`; |
| 1319 | + if (field.attributes.description) { |
| 1320 | + body += `${field.attributes.description}\n\n`; |
| 1321 | + } |
| 1322 | + if (field.attributes.placeholder) { |
| 1323 | + body += `${field.attributes.placeholder}\n\n`; |
| 1324 | + } else if (field.attributes.value) { |
| 1325 | + body += `${field.attributes.value}\n\n`; |
| 1326 | + } |
| 1327 | + } else if (field.type === 'input' && field.attributes?.label) { |
| 1328 | + body += `## ${field.attributes.label}\n\n`; |
| 1329 | + if (field.attributes.description) { |
| 1330 | + body += `${field.attributes.description}\n\n`; |
| 1331 | + } |
| 1332 | + if (field.attributes.placeholder) { |
| 1333 | + body += `${field.attributes.placeholder}\n\n`; |
| 1334 | + } |
| 1335 | + } else if (field.type === 'dropdown' && field.attributes?.label) { |
| 1336 | + body += `## ${field.attributes.label}\n\n`; |
| 1337 | + if (field.attributes.description) { |
| 1338 | + body += `${field.attributes.description}\n\n`; |
| 1339 | + } |
| 1340 | + if (field.attributes.options && Array.isArray(field.attributes.options)) { |
| 1341 | + body += field.attributes.options.map((opt: string | { label?: string }) => typeof opt === 'string' ? `- ${opt}` : `- ${opt.label || ''}`).join('\n') + '\n\n'; |
| 1342 | + } |
| 1343 | + } else if (field.type === 'checkboxes' && field.attributes?.label) { |
| 1344 | + body += `## ${field.attributes.label}\n\n`; |
| 1345 | + if (field.attributes.description) { |
| 1346 | + body += `${field.attributes.description}\n\n`; |
| 1347 | + } |
| 1348 | + if (field.attributes.options && Array.isArray(field.attributes.options)) { |
| 1349 | + body += field.attributes.options.map((opt: { label?: string } | string) => `- [ ] ${typeof opt === 'string' ? opt : opt.label || ''}`).join('\n') + '\n\n'; |
| 1350 | + } |
| 1351 | + } |
| 1352 | + } |
| 1353 | + } |
| 1354 | + |
| 1355 | + return { title, name, about, body: body.trim() || undefined }; |
| 1356 | + } |
| 1357 | + |
1291 | 1358 | private async doCreateIssue( |
1292 | 1359 | document: vscode.TextDocument | undefined, |
1293 | 1360 | newIssue: NewIssue | undefined, |
|
0 commit comments