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
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
"karma-safari-launcher": "^1.0.0",
"lint-staged": "^16.4.0",
"loading-indicator": "^2.0.0",
"mermaid": "^11.14.0",
"pluralize": "^8.0.0",
"prettier": "^3.8.3",
"prompt": "^1.3.0",
Expand Down
933 changes: 933 additions & 0 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions profiles/w3c.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ const modules = [
import("../src/core/issues-notes.js"),
import("../src/core/best-practices.js"),
import("../src/core/figures.js"),
import("../src/core/diagrams.js"),
import("../src/core/tables.js"),
Comment thread
marcoscaceres marked this conversation as resolved.
import("../src/core/webidl.js"),
import("../src/core/cddl.js"),
Expand Down
54 changes: 51 additions & 3 deletions src/core/clipboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,24 +9,61 @@
const COPY_SVG =
'<svg height="16" viewBox="0 0 14 16" width="14"><path fill-rule="evenodd" d="M2 13h4v1H2v-1zm5-6H2v1h5V7zm2 3V8l-3 3 3 3v-2h5v-2H9zM4.5 9H2v1h2.5V9zM2 12h2.5v-1H2v1zm9 1h1v2c-.02.28-.11.52-.3.7-.19.18-.42.28-.7.3H1c-.55 0-1-.45-1-1V4c0-.55.45-1 1-1h3c0-1.11.89-2 2-2 1.11 0 2 .89 2 2h3c.55 0 1 .45 1 1v5h-1V6H1v9h10v-2zM2 5h8c0-.55-.45-1-1-1H8c-.55 0-1-.45-1-1s-.45-1-1-1-1 .45-1 1-.45 1-1 1H3c-.55 0-1 .45-1 1z"/></svg>';

/**
* Find the copy target <pre> for a button.
* If the button has a data-copy-container attribute, searches within that
* ancestor. Otherwise falls back to closest("pre").
* @param {HTMLElement} button
* @returns {HTMLElement | null}
*/
function findCopyTarget(button) {
const containerSel = button.dataset.copyContainer;
if (containerSel) {
const container = button.closest(containerSel);
return /** @type {HTMLElement | null} */ (
container?.querySelector("pre") ?? null
);
}
return /** @type {HTMLElement | null} */ (button.closest("pre"));
}

/**
* Create a copy-to-clipboard button for a code block.
* The button stores the header selector in a data attribute so the
* runtime script can re-attach the handler in exported documents.
*
* @param {string} headerSelector - Selector for the header to exclude from copy
* @param {string} [title="Copy to clipboard"] - Accessible label and tooltip
* @param {string} [containerSelector] - Ancestor selector to find the <pre> within
* @returns {HTMLButtonElement}
*/
export function createCopyButton(headerSelector, title = "Copy to clipboard") {
export function createCopyButton(
headerSelector,
title = "Copy to clipboard",

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should probably localize this.

containerSelector
) {
const button = document.createElement("button");
button.innerHTML = COPY_SVG;
button.title = title;
button.setAttribute("aria-label", title);
button.classList.add("respec-button-copy-paste", "removeOnSave");
button.dataset.copyHeader = headerSelector;
if (containerSelector) {
button.dataset.copyContainer = containerSelector;
}
button.addEventListener("click", () => {
const pre = button.closest("pre");
const containerSel = button.dataset.copyContainer;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: avoid abbreviations in variable names.

if (containerSel) {
const container = /** @type {HTMLElement | null} */ (
button.closest(containerSel)
);
const source = container?.dataset.diagramSource;
if (source) {
navigator.clipboard.writeText(source);
return;
}
}
const pre = findCopyTarget(button);
if (!pre) return;
const clone = /** @type {HTMLElement} */ (pre.cloneNode(true));
clone.querySelector(headerSelector)?.remove();
Expand All @@ -46,7 +83,18 @@ export function injectCopyScript() {
script.textContent = `
document.querySelectorAll(".respec-button-copy-paste").forEach(function(btn) {
btn.addEventListener("click", function() {
var pre = this.closest("pre");
var containerSel = this.dataset.copyContainer;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use let or const where possible (applies throughout this PR.

var pre = null;
if (containerSel) {
var container = this.closest(containerSel);
if (container && container.dataset.diagramSource) {
navigator.clipboard.writeText(container.dataset.diagramSource);
return;
}
pre = container ? container.querySelector("pre") : null;
} else {
pre = this.closest("pre");
}
if (!pre) return;
var sel = this.dataset.copyHeader;
var clone = pre.cloneNode(true);
Expand Down
33 changes: 33 additions & 0 deletions src/core/diagrams-runtime.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// @ts-check
/**
* Module core/diagrams-runtime
*
* Runtime script injected into published specs.
* Handles flip buttons: toggles the flipped class for 3D rotation,
* updates ARIA state, and manages back-face height.
*/

export const runtimeScript = `
"use strict";
(function() {
document.querySelectorAll(".diagram-flip-btn").forEach(function(btn) {
btn.addEventListener("click", function(e) {
e.stopPropagation();
var container = btn.closest(".diagram-container");

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use let or const. Same with other vars.

if (!container) return;
var isFlipped = container.classList.toggle("diagram-container--flipped");
btn.setAttribute("aria-expanded", String(isFlipped));
var viewSource = btn.dataset.labelSource;
var viewDiagram = btn.dataset.labelDiagram;
if (viewSource && viewDiagram) {
btn.setAttribute("aria-label", isFlipped ? viewDiagram : viewSource);
}
var flip = container.querySelector(".diagram-flip");
var back = container.querySelector(".diagram-face--back");
if (flip && back) {
flip.style.minHeight = isFlipped ? back.scrollHeight + "px" : "";
}
});
});
})();
`;
Loading
Loading