Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions src/core/link-to-dfn.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,28 @@ function mapTitleToDfns() {
elements: duplicates,
});
}
// When a dfn uses `data-lt="For/term"` style (e.g. "script/src"), also
// register the short title ("src") under the for-context ("script") so that
// scoped links like [^ script/src ^] can resolve to it.
if (key.includes("/")) {
const lastSlash = key.lastIndexOf("/");
const forContext = key.slice(0, lastSlash);
const shortTitle = key.slice(lastSlash + 1);
if (shortTitle) {
for (const [dfnFor, typeMap] of result) {
// Only promote dfns that are registered with an empty for-context —
// dfns with an explicit for-context are already scoped correctly.
if (dfnFor !== "") continue;
if (!titleToDfns.has(shortTitle)) {
titleToDfns.set(shortTitle, new Map());
}
const shortTitleMap = titleToDfns.get(shortTitle);
if (!shortTitleMap.has(forContext)) {
shortTitleMap.set(forContext, new Map(typeMap));
}
}
}
}
}
return titleToDfns;
}
Expand Down
26 changes: 26 additions & 0 deletions tests/spec/core/link-to-dfn-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -387,4 +387,30 @@ describe("Core — Link to definitions", () => {
expect(codeElem.textContent).toEqual("MediaDevices");
expect(codeElem.querySelector("code")).toBeNull();
});

it("resolves scoped link using data-lt with slash notation", async () => {
// Regression test for https://github.com/speced/respec/issues/4133.
// Authors sometimes write <dfn data-lt="element/attr"> as shorthand for
// defining "attr" in the context of "element". The link [^ element/attr ^]
// generates a scoped link (data-link-for="element", text="attr") and must
// resolve to the dfn even though data-dfn-for is absent on the dfn.
const body = `
<section>
<p>
<dfn id="dfn-src" data-lt="script/src" data-dfn-type="element-attr">
The src IDL attribute
</dfn>
</p>
<p id="link-test">[^ script/src ^]</p>
</section>
`;
const ops = makeStandardOps(null, body);
const doc = await makeRSDoc(ops);

const a = doc.querySelector("#link-test a");
expect(a).toBeTruthy();
expect(a.hash).toBe("#dfn-src");
expect(a.classList).toContain("internalDFN");
expect(a.classList).not.toContain("respec-offending-element");
});
});