diff --git a/src/core/title.js b/src/core/title.js
index 912df79c35..9d2c2b7b4e 100644
--- a/src/core/title.js
+++ b/src/core/title.js
@@ -51,7 +51,18 @@ export function run(conf) {
}
// Decorate the spec title
- if (!h1Elem.id) h1Elem.id = "title";
+ if (!h1Elem.id) {
+ const existing = document.getElementById("title");
+ if (existing && existing !== h1Elem) {
+ const msg =
+ 'Another element already uses `id="title"`. ' +
+ "The spec's `
` will use a different id to avoid a collision.";
+ showError(msg, name, { elements: [existing] });
+ h1Elem.id = "document-title";
+ } else {
+ h1Elem.id = "title";
+ }
+ }
h1Elem.classList.add("title");
setDocumentTitle(conf, h1Elem);
diff --git a/tests/spec/core/title-spec.js b/tests/spec/core/title-spec.js
new file mode 100644
index 0000000000..745fbefc94
--- /dev/null
+++ b/tests/spec/core/title-spec.js
@@ -0,0 +1,57 @@
+"use strict";
+
+import {
+ flushIframes,
+ makeDefaultBody,
+ makeRSDoc,
+ makeStandardOps,
+} from "../SpecHelper.js";
+
+describe("Core — Title", () => {
+ afterAll(flushIframes);
+
+ it("uses id='document-title' when another element already uses id='title'", async () => {
+ const body = `
+ not the title
+ My Spec Title
+ ${makeDefaultBody()}
+ `;
+ const ops = makeStandardOps(null, body);
+ const doc = await makeRSDoc(ops);
+
+ // The h1 should fall back to id="document-title"
+ const h1 = doc.querySelector("h1.title");
+ expect(h1).toBeTruthy();
+ expect(h1.id).toBe("document-title");
+
+ // The original id="title" element should still exist
+ const original = doc.getElementById("title");
+ expect(original).toBeTruthy();
+ expect(original.localName).toBe("span");
+
+ // An error should have been shown
+ const errors = doc.respec.errors.filter(
+ err => err.plugin === "core/title"
+ );
+ expect(errors).toHaveSize(1);
+ expect(errors[0].message).toContain('id="title"');
+ });
+
+ it("uses id='title' normally when there is no collision", async () => {
+ const body = `
+ My Spec Title
+ ${makeDefaultBody()}
+ `;
+ const ops = makeStandardOps(null, body);
+ const doc = await makeRSDoc(ops);
+
+ const h1 = doc.querySelector("h1#title");
+ expect(h1).toBeTruthy();
+ expect(h1.id).toBe("title");
+
+ const errors = doc.respec.errors.filter(
+ err => err.plugin === "core/title"
+ );
+ expect(errors).toHaveSize(0);
+ });
+});