From f76be67247631c3890e8e678b2aa1803d80983c5 Mon Sep 17 00:00:00 2001 From: "Gustavo \"Guz\" L de Mello" Date: Tue, 4 Nov 2025 18:40:00 -0300 Subject: [PATCH] feat(ipub): debug attribute and overlay --- .epub/example/OEBPS/scripts/ipub.js | 88 ++++++++++++++++++- .../example/OEBPS/sections/section0001.xhtml | 2 +- .epub/example/OEBPS/styles/stylesheet.css | 15 ++++ 3 files changed, 101 insertions(+), 4 deletions(-) diff --git a/.epub/example/OEBPS/scripts/ipub.js b/.epub/example/OEBPS/scripts/ipub.js index 906f277..d5d2e5b 100644 --- a/.epub/example/OEBPS/scripts/ipub.js +++ b/.epub/example/OEBPS/scripts/ipub.js @@ -1,14 +1,29 @@ "use strict"; class IPUBElement extends HTMLElement { - static observedAttributes = ["id"]; + /** + * @protected + * @type {Readonly} + */ + static observedAttributes = ["id", "debug"]; connectedCallback() { this.#ensureID(); } - attributeChangedCallback(_name, _oldValue, _newValue) { - this.#ensureID(); + attributeChangedCallback(name, _oldValue, _newValue) { + switch (name) { + case "id": + this.#ensureID(); + break; + case "debug": + if (this.hasAttribute("debug")) { + this.setDebug(true); + } else { + this.setDebug(false); + } + break; + } } /** @@ -20,6 +35,53 @@ class IPUBElement extends HTMLElement { } } + /** + * @returns {boolean} + */ + getDebug() { + return this.hasAttribute("debug"); + } + + /** + * @param {boolean} state + */ + setDebug(state) { + if (state) { + if (!this.hasAttribute("debug")) { + this.setAttribute("debug", "true"); + } + + if (!this.style.getPropertyValue(IPUBElement.#PROPERTY_DEBUG_COLOR)) { + this.style.setProperty( + IPUBElement.#PROPERTY_DEBUG_COLOR, + `#${hashFromHTML(this)}`, + ); + } + } else { + if (!state && this.hasAttribute("debug")) { + this.removeAttribute("debug"); + } + + if ( + !state && + this.style.getPropertyValue(IPUBElement.#PROPERTY_DEBUG_COLOR) + ) { + this.style.removeProperty(IPUBElement.#PROPERTY_DEBUG_COLOR); + } + } + + getAllDescendants(this) + .filter((el) => el.tagName.startsWith("ipub-")) + .forEach((el) => { + el.setDebug?.(state); + }); + } + + /** + * @private + * @type {Readonly} + */ + static #PROPERTY_DEBUG_COLOR = "--ipub-debug-color"; } globalThis.addEventListener("load", () => { @@ -75,6 +137,12 @@ class IPUBBody extends IPUBElement { globalThis.customElements.define(e.elementName, e); } + if (this.getDebug()) { + // HACK: Re-trigger IPUBElement debugging logic + console.debug("IPUBBody: triggeing debugger"); + this.setAttribute("debug", "true"); + } + } } class IPUBCover extends IPUBElement { @@ -590,6 +658,20 @@ function getAncestor(el, tagName) { return getAncestor(el.parentElement, tagName); } +/** + * @param {Element} el + * @returns {Element[]} + */ +function getAllDescendants(el) { + return Array.from(el.children).reduce( + (acc, current) => { + acc.push(current); + return acc.concat(getAllDescendants(current)); + }, + /** @type {Element[]} */ [], + ); +} + /** * @param {Readonly} el * @param {number} [length=6] diff --git a/.epub/example/OEBPS/sections/section0001.xhtml b/.epub/example/OEBPS/sections/section0001.xhtml index 2b2eb5e..7cee4eb 100644 --- a/.epub/example/OEBPS/sections/section0001.xhtml +++ b/.epub/example/OEBPS/sections/section0001.xhtml @@ -11,7 +11,7 @@ - +
diff --git a/.epub/example/OEBPS/styles/stylesheet.css b/.epub/example/OEBPS/styles/stylesheet.css index a2b2c58..2c4114d 100644 --- a/.epub/example/OEBPS/styles/stylesheet.css +++ b/.epub/example/OEBPS/styles/stylesheet.css @@ -12,7 +12,22 @@ overflow: clip; display: flex; +:root { + --z-controls: 10; --z-cover: 9; + --z-overlays: 6; +} + +[debug] { + --ipub-debug-bg-opacity: 30%; + background-color: rgba( + from var(--ipub-debug-color) r g b / var(--ipub-debug-bg-opacity, 30%) + ); + outline-color: var(--ipub-debug-color); + outline-width: 1px; + outline-style: solid; +} + ipub-cover > dialog[open] { --ipub-accent-color: #fff; z-index: var(--z-cover);