From 1af8fa6aeafceccdcce90e47796f7312b81c4f39 Mon Sep 17 00:00:00 2001 From: Dmitry Sharabin Date: Wed, 10 Jun 2026 19:37:59 +0200 Subject: [PATCH 1/3] Fix timer plugin crashing on init (this is undefined in ESM) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The init-start handler stored duration on `this`, but the handler is a top-level arrow function, so `this` is the module's top-level value — `undefined` in ESM. It threw `TypeError: Cannot set properties of undefined` before the timer was ever created, so the timer never worked. It only worked when plugins loaded as classic scripts (top-level `this` === `window`); they now load as modules. Use a local variable instead. Co-Authored-By: Claude Opus 4.8 (1M context) --- timer/plugin.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/timer/plugin.js b/timer/plugin.js index 47948c7..ee2be38 100644 --- a/timer/plugin.js +++ b/timer/plugin.js @@ -2,18 +2,18 @@ import Inspire from "@inspirejs/core"; Inspire.hooks.add("init-start", me => { // Create timer, if needed - this.duration = document.body.getAttribute("data-duration"); + let duration = document.body.getAttribute("data-duration"); - if (this.duration > 0) { + if (duration > 0) { document.body.insertAdjacentHTML( "beforeend", - `
`, + `
`, ); addEventListener("load", evt => { timer.className = "end"; - setTimeout(() => timer.classList.add("overtime"), this.duration * 60000); + setTimeout(() => timer.classList.add("overtime"), duration * 60000); }); } }); From 9655bbce8bdad5e3e1a14e0dcbec0f8d076d5847 Mon Sep 17 00:00:00 2001 From: Dmitry Sharabin Date: Wed, 10 Jun 2026 21:05:03 +0200 Subject: [PATCH 2/3] Start the timer even if it loads after the load event MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The countdown started on the window `load` event, but the plugin loads asynchronously and can finish after `load` has already fired — then the listener never ran and the timer never started. Run the start logic immediately when the document is already loaded, the way the autosize plugin handles late loading. Co-Authored-By: Claude Opus 4.8 (1M context) --- timer/plugin.js | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/timer/plugin.js b/timer/plugin.js index ee2be38..2978a60 100644 --- a/timer/plugin.js +++ b/timer/plugin.js @@ -10,10 +10,19 @@ Inspire.hooks.add("init-start", me => { `
`, ); - addEventListener("load", evt => { + // Start the countdown on load — or right away if the plugin loaded after + // the load event already fired, so a late load isn't missed. + let start = () => { timer.className = "end"; setTimeout(() => timer.classList.add("overtime"), duration * 60000); - }); + }; + + if (document.readyState === "complete") { + start(); + } + else { + addEventListener("load", start); + } } }); From a56bad87dab0c6ded9585b678b7a25baa807bd30 Mon Sep 17 00:00:00 2001 From: Dmitry Sharabin Date: Wed, 10 Jun 2026 21:09:51 +0200 Subject: [PATCH 3/3] Load the timer plugin's stylesheet (hasCSS was missing) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit timer/plugin.css styles the #timer progress bar, but the plugin never exported `hasCSS`, so the core loader — which injects plugin.css only when `module.hasCSS` is truthy — skipped it, and the timer rendered unstyled. Export hasCSS = true, like the other CSS-bearing plugins. Co-Authored-By: Claude Opus 4.8 (1M context) --- timer/plugin.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/timer/plugin.js b/timer/plugin.js index 2978a60..5c6e3bf 100644 --- a/timer/plugin.js +++ b/timer/plugin.js @@ -1,5 +1,7 @@ import Inspire from "@inspirejs/core"; +export const hasCSS = true; + Inspire.hooks.add("init-start", me => { // Create timer, if needed let duration = document.body.getAttribute("data-duration");