'use strict' const id = 'fixes-url' const github = new RegExp('^https://github\\.com/[\\w-]+/[\\w-]+/' + '(issues|pull)/\\d+(#issuecomment-\\d+|#discussion_r\\d+)?$' ) module.exports = { id: id, meta: { description: 'enforce format of Fixes URLs', recommended: true }, defaults: {}, options: {}, validate: (context, rule) => { const parsed = context.toJSON() if (!Array.isArray(parsed.fixes) || !parsed.fixes.length) { context.report({ id: id, message: 'skipping fixes-url', string: '', level: 'skip' }) return } // Allow GitHub issues with optional comment. // GitHub pull requests must reference a comment or discussion. for (const url of parsed.fixes) { const match = github.exec(url) if (url[0] === '#') { // See nodejs/node#2aa376914b621018c5784104b82c13e78ee51307 // for an example const { line, column } = findLineAndColumn(context.body, url) context.report({ id: id, message: 'Fixes must be a URL, not an issue number.', string: url, line: line, column: column, level: 'fail' }) } else if (match) { if (match[1] === 'pull' && match[2] === undefined) { const { line, column } = findLineAndColumn(context.body, url) context.report({ id: id, message: 'Pull request URL must reference a comment or discussion.', string: url, line: line, column: column, level: 'fail' }) } else { const { line, column } = findLineAndColumn(context.body, url) context.report({ id: id, message: 'Valid fixes URL.', string: url, line: line, column: column, level: 'pass' }) } } else { const { line, column } = findLineAndColumn(context.body, url) context.report({ id: id, message: 'Fixes must be a GitHub URL.', string: url, line: line, column: column, level: 'fail' }) } } } } function findLineAndColumn (body, str) { for (let i = 0; i < body.length; i++) { const l = body[i] if (~l.indexOf('Fixes')) { const idx = l.indexOf(str) if (idx !== -1) { return { line: i, column: idx } } } } return { line: -1, column: -1 } }