From 7f31d5f2c521437b43fceddaff42e1c703145bf7 Mon Sep 17 00:00:00 2001 From: Marcos Caceres Date: Mon, 4 May 2026 11:03:18 +1000 Subject: [PATCH 1/2] fix(core/github): edDraftURI opt-out and custom newIssuesURL Closes #5103 Closes #4317 --- src/core/github.js | 32 ++++++++++++++++++++++++-- tests/spec/core/github-spec.js | 41 ++++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 2 deletions(-) diff --git a/src/core/github.js b/src/core/github.js index e2fe2c0f45..ef933fbced 100644 --- a/src/core/github.js +++ b/src/core/github.js @@ -49,6 +49,11 @@ const localizationStrings = { file_a_bug: "Nota un bug", participate: "Participe:", }, + fr: { + file_a_bug: "Signaler un problème", + participate: "Participer :", + commit_history: "Historique des modifications", + }, de: { commit_history: "Revisionen", file_a_bug: "Fehler melden", @@ -100,7 +105,27 @@ export async function run(conf) { } const branch = ghConf.branch || "gh-pages"; const issueBase = new URL("./issues/", ghURL).href; - const newIssuesURL = new URL("./new/choose", issueBase).href; + let newIssuesURL; + if ( + typeof conf.github === "object" && + conf.github.hasOwnProperty("newIssuesURL") + ) { + try { + const url = new URL(String(conf.github.newIssuesURL)); + if (url.protocol !== "https:") { + const msg = docLink`${"[github.newIssuesURL]"} must use HTTPS. (${String(conf.github.newIssuesURL)}).`; + rejectGithubPromise(msg); + return; + } + newIssuesURL = url.href; + } catch { + const msg = docLink`${"[github.newIssuesURL]"} is not a valid URL. (${String(conf.github.newIssuesURL)}).`; + rejectGithubPromise(msg); + return; + } + } else { + newIssuesURL = new URL("./new/choose", issueBase).href; + } // Allow custom pullsURL and commitHistoryURL for monorepo scenarios let pullsURL; @@ -166,8 +191,8 @@ export async function run(conf) { } } + /** @type {Record} */ const newProps = { - edDraftURI: `https://${org.toLowerCase()}.github.io/${repo}/`, githubToken: undefined, githubUser: undefined, issueBase, @@ -176,6 +201,9 @@ export async function run(conf) { pullBase: pullsURL, shortName: repo, }; + if (!conf.hasOwnProperty("edDraftURI")) { + newProps.edDraftURI = `https://${org.toLowerCase()}.github.io/${repo}/`; + } // Assign new properties, but retain existing ones let githubAPI = "https://respec.org/github"; if (conf.githubAPI) { diff --git a/tests/spec/core/github-spec.js b/tests/spec/core/github-spec.js index 8698fde2a5..9b2a5e66c4 100644 --- a/tests/spec/core/github-spec.js +++ b/tests/spec/core/github-spec.js @@ -81,6 +81,47 @@ describe("Core - Github", () => { const doc = await makeRSDoc(opts); doesntOverrideTest(doc); }); + it("does not generate edDraftURI when explicitly set to null", async () => { + const opts = { + config: Object.assign(makeBasicConfig(), { + github: "speced/respec", + edDraftURI: null, + }), + body: makeDefaultBody(), + }; + const doc = await makeRSDoc(opts); + const { respecConfig: conf } = doc.defaultView; + expect(conf.edDraftURI).toBeNull(); + }); + it("does not generate edDraftURI when explicitly set to empty string", async () => { + const opts = { + config: Object.assign(makeBasicConfig(), { + github: "speced/respec", + edDraftURI: "", + }), + body: makeDefaultBody(), + }; + const doc = await makeRSDoc(opts); + const { respecConfig: conf } = doc.defaultView; + expect(conf.edDraftURI).toBe(""); + }); + it("supports custom newIssuesURL", async () => { + const opts = { + config: Object.assign(makeBasicConfig(), { + github: { + repoURL: "https://github.com/speced/respec/", + newIssuesURL: "https://github.com/speced/respec/issues/new", + }, + }), + body: makeDefaultBody(), + }; + delete opts.config.edDraftURI; + const doc = await makeRSDoc(opts); + const { respecConfig: conf } = doc.defaultView; + expect(conf.github.newIssuesURL).toBe( + "https://github.com/speced/respec/issues/new" + ); + }); it("normalizes github object with custom pullsURL and commitHistoryURL", async () => { const opts = { config: Object.assign(makeBasicConfig(), { From ce9b996a5e2f1830cd4f1a84aa044f721e9e73f1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Mon, 4 May 2026 13:21:07 +0000 Subject: [PATCH 2/2] test(core/github): add DOM assertion for custom newIssuesURL rendered link Agent-Logs-Url: https://github.com/speced/respec/sessions/20f04c30-6520-406b-b673-555dabf64b8b Co-authored-by: marcoscaceres <870154+marcoscaceres@users.noreply.github.com> --- tests/spec/core/github-spec.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/tests/spec/core/github-spec.js b/tests/spec/core/github-spec.js index 9b2a5e66c4..92d9e52af5 100644 --- a/tests/spec/core/github-spec.js +++ b/tests/spec/core/github-spec.js @@ -112,6 +112,7 @@ describe("Core - Github", () => { repoURL: "https://github.com/speced/respec/", newIssuesURL: "https://github.com/speced/respec/issues/new", }, + excludeGithubLinks: false, }), body: makeDefaultBody(), }; @@ -121,6 +122,14 @@ describe("Core - Github", () => { expect(conf.github.newIssuesURL).toBe( "https://github.com/speced/respec/issues/new" ); + // Also verify the rendered feedback link in the DOM uses the custom URL + const fileABug = Array.from(doc.querySelectorAll("dd")).find( + elem => elem.textContent.trim() === "File an issue" + ); + expect(fileABug).toBeTruthy(); + expect(fileABug.querySelector("a").href).toBe( + "https://github.com/speced/respec/issues/new" + ); }); it("normalizes github object with custom pullsURL and commitHistoryURL", async () => { const opts = {