Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core/dfn): add data-defines on some patterns of term/definition association #4620

Merged
merged 10 commits into from
Jan 29, 2024
39 changes: 38 additions & 1 deletion src/core/dfn.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function run() {
}
dfn.dataset.lt = titles.join("|");
}
sub("plugins-done", addContractDefaults);
sub("plugins-done", completeDefinitionMarkup);
}

/**
Expand Down Expand Up @@ -216,6 +216,11 @@ function processAsInternalSlot(title, dfn) {
return dfnType;
}

function completeDefinitionMarkup() {
addContractDefaults();
addDefinitionPointers();
}

function addContractDefaults() {
// Find all dfns that don't have a type and default them to "dfn".
/** @type NodeListOf<HTMLElement> */
Expand All @@ -238,3 +243,35 @@ function addContractDefaults() {
dfn.dataset.export = "";
}
}

// - Sets data-defines on well-known definition content patterns
function addDefinitionPointers() {
// A dl with class hasdefinitions associated the dfn in each dt
// the definition in the following sibling element
/** @type NodeListOf<HTMLElement> */
const describedDTs = document.querySelectorAll(
"dl.definitions dt:has(dfn[data-dfn-type])"
);
for (const dt of describedDTs) {
const dfnId = dt.querySelector("dfn[data-dfn-type]").id;
const dfnContent = /** @type {HTMLElement | null} */ (
dt.nextElementSibling
);
if (dfnContent && !dfnContent.dataset.defines && dfnId) {
dfnContent.dataset.defines = `#${dfnId}`;
}
}

// an element with class "definition" is marked as defining the term
// found in the element
/** @type NodeListOf<HTMLElement> */
const definitionContainers = document.querySelectorAll(
".definition:has(dfn[data-dfn-type])"
);
for (const el of definitionContainers) {
dontcallmedom marked this conversation as resolved.
Show resolved Hide resolved
const dfn = el.querySelector("dfn[data-dfn-type]");
if (dfn.id && !el.dataset.defines) {
el.dataset.defines = `#${dfn.id}`;
}
}
}
21 changes: 21 additions & 0 deletions tests/spec/core/dfn-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -655,5 +655,26 @@ describe("Core — Definitions", () => {
expect(errors[0].message).toContain("Declares both");
expect(errors[1].message).toContain("but also has a");
});

it("assigns data-defines on well-known patterns", async () => {
const body = `
<section>
<h2>Definitions</h2>
<p id="desc1" class="definition">
A <dfn>definition</dfn> can also have an associated description
</p>
<dl class="definitions">
<dt><dfn>different convention</dfn></dt>
<dd id="desc2">Different conventions can be applied to associate a term with its description</dd>
</dl>
</section>
`;
const ops = makeStandardOps(null, body);
const doc = await makeRSDoc(ops);
const desc1 = doc.getElementById("desc1");
const desc2 = doc.getElementById("desc2");
expect(desc1.dataset.defines).toBe("#dfn-definition");
expect(desc2.dataset.defines).toBe("#dfn-different-convention");
});
});
});