Some checks are pending
CI / ruff (push) Waiting to run
CI / mypy (push) Waiting to run
CI / pytest (push) Waiting to run
CI / package (push) Waiting to run
CI / Install smoke (${{ matrix.label }}) (linux, ubuntu-latest) (push) Blocked by required conditions
CI / Install smoke (${{ matrix.label }}) (macos-arm64, macos-14) (push) Blocked by required conditions
38 lines
1.1 KiB
JavaScript
38 lines
1.1 KiB
JavaScript
// @ts-check
|
|
/** Small shared helpers used across the UI modules: a strict query selector,
|
|
* HTML escaping for text we drop into innerHTML, error-string trimming, and
|
|
* the opt-in debug flag. */
|
|
|
|
/** Opt-in tracing: `localStorage.setItem("s2s.debug", "1")` then reload. */
|
|
export const DEBUG = (() => {
|
|
try {
|
|
return localStorage.getItem("s2s.debug") === "1";
|
|
} catch {
|
|
return false;
|
|
}
|
|
})();
|
|
|
|
/**
|
|
* Query a single element, throwing if it's missing (so a broken selector fails
|
|
* loudly at startup rather than as a later null-deref).
|
|
* @template {HTMLElement} T
|
|
* @param {string} selector
|
|
* @returns {T}
|
|
*/
|
|
export function $(selector) {
|
|
const el = document.querySelector(selector);
|
|
if (!el) throw new Error(`Missing element: ${selector}`);
|
|
return /** @type {T} */ (el);
|
|
}
|
|
|
|
/** @param {string} s @returns {string} */
|
|
export function escHtml(s) {
|
|
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
}
|
|
|
|
/** Trim a long error message to fit the orb caption. @param {string} text */
|
|
export function truncateError(text) {
|
|
if (text.length <= 90) return text;
|
|
return text.slice(0, 87) + "…";
|
|
}
|