Skip to content
Draft
Show file tree
Hide file tree
Changes from 10 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
12e96fd
fix(caniuse): add role=img to browser support cells for valid HTML
marcoscaceres Apr 12, 2026
5ef5330
test(caniuse): update test expectations for role=img change
marcoscaceres Apr 13, 2026
6547bd6
fix(caniuse): include version in aria-label even when version is unknown
Copilot Apr 15, 2026
fb850cf
fix(caniuse): format ternary per prettier rules to fix lint CI
Copilot Apr 15, 2026
3e21335
Merge branch 'main' into fix/caniuse-aria-role
marcoscaceres Apr 17, 2026
6cb969f
fix(caniuse): revert ?? to ternary to handle empty-string version
marcoscaceres Apr 17, 2026
df735f9
Merge branch 'main' into fix/caniuse-aria-role
marcoscaceres Apr 18, 2026
3ee9d56
fix(caniuse): unify title and aria-label text for unknown version
marcoscaceres Apr 18, 2026
51f9509
fix(best-practices): respect existing heading in #bp-summary
marcoscaceres Apr 18, 2026
3e00a49
fix(core/style): insert respec-mainstyle before author-provided style…
marcoscaceres Apr 18, 2026
fadcda6
fix(style): narrow selector to avoid displacing non-stylesheet links
marcoscaceres Apr 18, 2026
39ef038
test(style): inline style-order fixture setup in spec helper ops
Copilot Apr 18, 2026
a7526f5
fix(best-practices): treat existing h1 as summary heading
Copilot Apr 18, 2026
7a7291c
Merge branch 'main' into fix/style-order
marcoscaceres Apr 19, 2026
1e081f6
test(best-practices): allow section numbering in custom summary headi…
Copilot Apr 19, 2026
c7e815f
fix(core/style): clarify comment about stylesheet ordering
marcoscaceres Apr 26, 2026
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
7 changes: 5 additions & 2 deletions src/core/best-practices.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,11 @@ export function run() {
});
if (bps.length) {
if (bpSummary) {
bpSummary.appendChild(html`<h1>Best Practices Summary</h1>`);
if (summaryItems) bpSummary.appendChild(summaryItems);
const existingHeading = bpSummary.querySelector("h2, h3, h4, h5, h6");
Comment thread
marcoscaceres marked this conversation as resolved.
Outdated
Comment thread
marcoscaceres marked this conversation as resolved.
Outdated
if (!existingHeading) {
bpSummary.prepend(html`<h1>Best Practices Summary</h1>`);
}
if (summaryItems) bpSummary.append(summaryItems);
}
} else if (bpSummary) {
const msg = `Using best practices summary (#bp-summary) but no best practices found.`;
Expand Down
20 changes: 13 additions & 7 deletions src/core/caniuse.js
Original file line number Diff line number Diff line change
Expand Up @@ -195,22 +195,28 @@ function browserCellRenderer(feature) {
return (groups, { browser: browserId, version, caniuse }) => {
const entry = BROWSERS.get(browserId);
const { name, type } = entry ?? { name: browserId, type: "desktop" };
const versionLong = version ? ` version ${version}` : "";
const browserName = `${name}${versionLong}`;
const supportLevel = statToText.get(caniuse);
const ariaLabel = `${feature} is ${supportLevel} since ${browserName} on ${type}.`;
const cssClass = `caniuse-cell ${caniuse}`;
const title = capitalize(`${supportLevel} since ${browserName}.`);
const textVersion = version ? version : "—";
const versionSuffix = version
? ` version ${version}`
: " (version unknown)";
const ariaLabel = `${feature} is ${supportLevel} since ${name}${versionSuffix} on ${type}.`;
const cssClass = `caniuse-cell ${caniuse}`;
const title = capitalize(`${supportLevel} since ${name}${versionSuffix}.`);
Comment thread
marcoscaceres marked this conversation as resolved.
Comment thread
marcoscaceres marked this conversation as resolved.
const src = getLogoSrc(browserId);
const result = html`
<div class="${cssClass}" title="${title}" aria-label="${ariaLabel}">
<div
class="${cssClass}"
role="img"
title="${title}"
aria-label="${ariaLabel}"
>
Comment thread
marcoscaceres marked this conversation as resolved.
<img
class="caniuse-browser"
width="20"
height="20"
src="${src}"
alt="${name} logo"
alt=""
/><span class="browser-version">${textVersion}</span>
</div>
`;
Expand Down
5 changes: 4 additions & 1 deletion src/core/style.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ function insertStyle() {
const styleElement = document.createElement("style");
styleElement.id = "respec-mainstyle";
styleElement.textContent = css;
document.head.appendChild(styleElement);
// Insert before any existing <link> elements so author-provided stylesheets
// retain their position after all ReSpec-injected styles, letting custom CSS
// override ReSpec defaults. insertBefore(el, null) === appendChild.
document.head.insertBefore(styleElement, document.head.querySelector("link"));
Comment thread
marcoscaceres marked this conversation as resolved.
Outdated
Comment thread
marcoscaceres marked this conversation as resolved.
Outdated
return styleElement;
}

Expand Down
21 changes: 21 additions & 0 deletions tests/spec/core/best-practices-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,25 @@
);
expect(bps.querySelectorAll("ul li")).toHaveSize(3);
});

it("does not duplicate heading when bp-summary already has one", async () => {
const body = `
<section id="bps">
<h2>Section</h2>
<span class='practicelab'>BP1</span>
<section id='bp-summary'>
<h2>Custom Heading</h2>
</section>
</section>
`;
const ops = {
config: makeBasicConfig(),
body,
};
const doc = await makeRSDoc(ops);
const bpSummary = doc.getElementById("bp-summary");
const headings = bpSummary.querySelectorAll("h2, h3, h4, h5, h6");
expect(headings).toHaveSize(1);
expect(headings[0].textContent).toBe("Custom Heading");

Check failure on line 103 in tests/spec/core/best-practices-spec.js

View workflow job for this annotation

GitHub Actions / Karma Unit Tests (ChromeHeadless)

Core — Best Practices does not duplicate heading when bp-summary already has one Expected '1.1 Custom Heading' to be 'Custom Heading'.
Comment thread
marcoscaceres marked this conversation as resolved.
Outdated
});
});
12 changes: 11 additions & 1 deletion tests/spec/core/caniuse-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,11 @@ describe("Core — Can I Use", () => {

expect(firefox.width).toBe(20);
expect(firefox.height).toBe(20);
expect(chrome.alt).toBe("Android Chrome logo");
expect(chrome.alt).toBe("");

// The parent cell has role=img with aria-label for accessibility
const firstCell = cells[0];
expect(firstCell.getAttribute("role")).toBe("img");

// The version numbers
const [firefoxVersion, chromeVersion, safariVersion] =
Expand All @@ -112,6 +116,12 @@ describe("Core — Can I Use", () => {
expect(firefoxVersion.textContent).toBe("66");
expect(safariVersion.textContent).toBe("—");

// aria-label for no-version cell uses "(version unknown)" to match visible "—"
const safariCell = safariVersion.closest(".caniuse-cell");
expect(safariCell.getAttribute("aria-label")).toBe(
"FEATURE is unknown support since iOS Safari (version unknown) on mobile."
);

// More info link
const moreInfoLink = cells.item(3);
expect(moreInfoLink.href).toBe("https://caniuse.com/FEATURE");
Expand Down
18 changes: 18 additions & 0 deletions tests/spec/core/custom-style.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!doctype html>
<html>
<meta charset="utf-8" />
<title>Custom Style Test</title>
<link rel="stylesheet" href="data:text/css," class="custom-author-style" />
<script class="remove">
var respecConfig = {
specStatus: "base",
shortName: "basics",
};
</script>
<section id="abstract">
<p>Custom style ordering test</p>
</section>
<section id="sotd">
<p>Test doc for verifying custom CSS insertion order.</p>
</section>
</html>
14 changes: 14 additions & 0 deletions tests/spec/core/style-spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,18 @@ describe("Core — Style", () => {
const style = doc.getElementById("respec-mainstyle");
expect(style).toBeTruthy();
});

it("inserts respec-mainstyle before author-provided stylesheets", async () => {
const doc = await makeRSDoc(
makeStandardOps(),
"spec/core/custom-style.html"
);
Comment thread
marcoscaceres marked this conversation as resolved.
Outdated
const respecStyle = doc.getElementById("respec-mainstyle");
const authorLink = doc.querySelector("link.custom-author-style");
expect(respecStyle).toBeTruthy();
expect(authorLink).toBeTruthy();
// Bitmask: Node.DOCUMENT_POSITION_FOLLOWING = 4 means respecStyle comes before authorLink
const position = respecStyle.compareDocumentPosition(authorLink);
expect(position & Node.DOCUMENT_POSITION_FOLLOWING).toBeTruthy();
});
});
Loading