@goodandready/dsh-cron 0.2.37 → 0.2.38
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/README.ru.md +1 -0
- package/README.zh.md +1 -0
- package/lib/client.js +57 -8
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -452,6 +452,7 @@ Developer-facing, no behaviour change. `parseScheduleExpression` was split into
|
|
|
452
452
|
- **Modular Client Architecture (#150)**: Decomposed monolithic `lib/client.js` (~3950 lines) into 14 focused, single-responsibility fragments under `lib/client-src/` (none exceeding 580 lines). Integrated zero-dependency build script `scripts/build-client.mjs` wired into `package.json` (`build:client`, `pretest`). Development fragments are excluded from npm distribution via `"files": ["lib/*.js", ...]`.
|
|
453
453
|
- **DSH Theme Tokens & Visual Standardization (#149)**: Replaced inline styles on task type badges (`onSuccess`, `onFailure`, `heartbeat`, `targetSession`, `preflight`) with dedicated `.dsh-cron-tag-*` CSS classes powered by semantic `--dsh-cron-*` theme variables. Modal overlay now adapts dynamically using `var(--dsw-alias-bg-mask, rgba(0, 0, 0, 0.75))`, and keyframe pulse animations use theme variables without hardcoded RGBA.
|
|
454
454
|
- **Label Governance & Triage Audit (#95)**: Standardized 100% of repository issues and triage on the canonical repo-level label set.
|
|
455
|
+
- **Style Self-Healing on Dynamic DOM Sweeps (#263 / GH-4)**: Watches `<head>` and `<html>` via `MutationObserver` alongside a 2s backstop interval and `visibilitychange` listener (`startStyleSelfHeal`), automatically re-attaching or repairing the `<style id="dsh-cron-styles">` tag if swept by host head re-renders, theme switches, or neighbor cleanups.
|
|
455
456
|
|
|
456
457
|
---
|
|
457
458
|
|
package/README.ru.md
CHANGED
|
@@ -319,6 +319,7 @@ cron({
|
|
|
319
319
|
- **Модульная архитектура клиентской части (#150)**: Монолитный файл `lib/client.js` (~3950 строк) декомпозирован на 14 независимых специализированных модулей в каталоге `lib/client-src/` (каждый строго <= 580 строк). Сборка `lib/client.js` выполняется легковесным скриптом `scripts/build-client.mjs` перед запуском тестов и сборки. Исходные фрагменты исключены из npm-дистрибутива через `"files": ["lib/*.js", ...]`.
|
|
320
320
|
- **Семантические токены тем DSH (#149)**: Инлайн-стили тегов типа задач (`onSuccess`, `onFailure`, `heartbeat`, `targetSession`, `preflight`) переведены на выделенные CSS-классы `.dsh-cron-tag-*` на базе переменных темы `--dsh-cron-*`. Оверлей модальных окон переведен на адаптивную маску `var(--dsw-alias-bg-mask, rgba(0, 0, 0, 0.75))`, а анимация пульсации избавлена от захардкоженных значений RGBA.
|
|
321
321
|
- **Аудит меток репозитория (#95)**: Подтверждена 100% консистентность использования канонического репозиторного набора меток и фильтрации задач.
|
|
322
|
+
- **Самовосстановление стилей при динамических перерисовках DOM (#263 / GH-4)**: Отслеживает `<head>` и `<html>` через `MutationObserver`, резервный интервал 2с и событие `visibilitychange` (`startStyleSelfHeal`), мгновенно восстанавливая узел `<style id="dsh-cron-styles">` при перерисовке заголовка хостом, смене темы или очистке соседними модулями.
|
|
322
323
|
|
|
323
324
|
---
|
|
324
325
|
|
package/README.zh.md
CHANGED
|
@@ -444,6 +444,7 @@ bash deploy.sh verify [exact-version]
|
|
|
444
444
|
- **客户端模块化架构 (#150)**: 将庞大的单文件 `lib/client.js` (约 3950 行) 拆分为 `lib/client-src/` 下的 14 个高内聚模块文件 (各模块严格 <= 580 行)。集成零依赖构建脚本 `scripts/build-client.mjs` 并接入 `package.json` (`build:client`, `pretest`),通过 `"files": ["lib/*.js", ...]` 避免开发源码冗余打包进 npm 发布包。
|
|
445
445
|
- **DSH 语义化主题变量对齐 (#149)**: 将任务类型标签 (`onSuccess`, `onFailure`, `heartbeat`, `targetSession`, `preflight`) 的内联样式全部替换为基于主题变量的 `.dsh-cron-tag-*` 类;模态框遮罩层接入自适应主题遮罩变量 `var(--dsw-alias-bg-mask, rgba(0, 0, 0, 0.75))`,移除脉冲动画关键帧中的硬编码 RGBA。
|
|
446
446
|
- **标签治理与工单审计 (#95)**: 审计并确认全仓库 100% 统一规范使用仓库级标签集。
|
|
447
|
+
- **动态 DOM 清理下的样式自动恢复(#263 / GH-4)**: 通过 `MutationObserver`、2 秒兜底定时器与 `visibilitychange` 事件(`startStyleSelfHeal`)监听 `<head>` 与 `<html>`,当宿主重绘 `<head>`、切换主题或邻近插件清理样式时,自动重新注入并修复 `<style id="dsh-cron-styles">` 标签。
|
|
447
448
|
|
|
448
449
|
---
|
|
449
450
|
|
package/lib/client.js
CHANGED
|
@@ -847,17 +847,63 @@ window.__ModuleLoader__.load({
|
|
|
847
847
|
}
|
|
848
848
|
`;
|
|
849
849
|
|
|
850
|
+
const STYLE_ID = 'dsh-cron-styles';
|
|
851
|
+
|
|
850
852
|
function ensureStyles() {
|
|
851
|
-
if (typeof document === 'undefined') return;
|
|
852
|
-
let el = document.getElementById(
|
|
853
|
-
if (
|
|
853
|
+
if (typeof document === 'undefined') return null;
|
|
854
|
+
let el = document.getElementById(STYLE_ID);
|
|
855
|
+
if (el === null) {
|
|
856
|
+
const head = document.head || document.documentElement;
|
|
857
|
+
if (!head) return null;
|
|
854
858
|
el = document.createElement('style');
|
|
855
|
-
el.id =
|
|
859
|
+
el.id = STYLE_ID;
|
|
856
860
|
// Mark ownership before insertion so neighbor cleanups leave it alone (#91)
|
|
857
861
|
el.dataset.dshPlugin = 'dsh-cron';
|
|
858
|
-
|
|
862
|
+
el.textContent = STYLES;
|
|
863
|
+
head.appendChild(el);
|
|
864
|
+
return el;
|
|
859
865
|
}
|
|
860
|
-
el.textContent = STYLES;
|
|
866
|
+
if (el.textContent !== STYLES) el.textContent = STYLES;
|
|
867
|
+
return el;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
// Registry is shared across hot reloads so the newest instance owns exactly
|
|
871
|
+
// one watcher instead of stacking one per module evaluation.
|
|
872
|
+
const STYLE_HEAL_KEY = '__dshCronStyleHeal';
|
|
873
|
+
const STYLE_HEAL_INTERVAL_MS = 2000;
|
|
874
|
+
|
|
875
|
+
/**
|
|
876
|
+
* Keep the stylesheet attached: watch <head> (and <html>, which catches a
|
|
877
|
+
* replaced <head>) and re-attach on demand, with a slow interval as the
|
|
878
|
+
* backstop. heal() is idempotent and writes nothing while healthy.
|
|
879
|
+
*/
|
|
880
|
+
function startStyleSelfHeal() {
|
|
881
|
+
if (typeof document === 'undefined') return () => {};
|
|
882
|
+
if (typeof window !== 'undefined' && typeof window[STYLE_HEAL_KEY] === 'function') {
|
|
883
|
+
try { window[STYLE_HEAL_KEY](); } catch (_err) { void _err; }
|
|
884
|
+
}
|
|
885
|
+
const heal = () => { try { ensureStyles(); } catch (_err) { void _err; } };
|
|
886
|
+
heal();
|
|
887
|
+
let observer = null;
|
|
888
|
+
try {
|
|
889
|
+
if (typeof MutationObserver === 'function') {
|
|
890
|
+
observer = new MutationObserver(heal);
|
|
891
|
+
if (document.head) observer.observe(document.head, { childList: true });
|
|
892
|
+
if (document.documentElement) observer.observe(document.documentElement, { childList: true });
|
|
893
|
+
}
|
|
894
|
+
} catch (_err) { observer = null; }
|
|
895
|
+
let timer = null;
|
|
896
|
+
try { timer = setInterval(heal, STYLE_HEAL_INTERVAL_MS); } catch (_err) { timer = null; }
|
|
897
|
+
const onVisibility = () => { if (document.visibilityState !== 'hidden') heal(); };
|
|
898
|
+
try { document.addEventListener('visibilitychange', onVisibility); } catch (_err) { void _err; }
|
|
899
|
+
const stop = () => {
|
|
900
|
+
try { if (observer) observer.disconnect(); } catch (_err) { void _err; }
|
|
901
|
+
try { if (timer !== null) clearInterval(timer); } catch (_err) { void _err; }
|
|
902
|
+
try { document.removeEventListener('visibilitychange', onVisibility); } catch (_err) { void _err; }
|
|
903
|
+
if (typeof window !== 'undefined' && window[STYLE_HEAL_KEY] === stop) window[STYLE_HEAL_KEY] = undefined;
|
|
904
|
+
};
|
|
905
|
+
if (typeof window !== 'undefined') window[STYLE_HEAL_KEY] = stop;
|
|
906
|
+
return stop;
|
|
861
907
|
}
|
|
862
908
|
|
|
863
909
|
function createErrorBoundary() {
|
|
@@ -4014,6 +4060,9 @@ window.__ModuleLoader__.load({
|
|
|
4014
4060
|
|
|
4015
4061
|
const applyActive = () => {
|
|
4016
4062
|
if (toggle.isOpen()) {
|
|
4063
|
+
// Repair a dropped stylesheet before the panel paints, so opening the
|
|
4064
|
+
// screen never shows an unstyled page (see startStyleSelfHeal).
|
|
4065
|
+
ensureStyles();
|
|
4017
4066
|
document.documentElement.setAttribute(ACTIVE_ATTR, '');
|
|
4018
4067
|
document.dispatchEvent(new CustomEvent(ACTIVATE_EVENT, { detail: PANEL }));
|
|
4019
4068
|
} else {
|
|
@@ -4070,7 +4119,7 @@ window.__ModuleLoader__.load({
|
|
|
4070
4119
|
}
|
|
4071
4120
|
|
|
4072
4121
|
function apply(ctx) {
|
|
4073
|
-
|
|
4122
|
+
const stopStyleSelfHeal = startStyleSelfHeal();
|
|
4074
4123
|
|
|
4075
4124
|
// Register the English canonical strings; rebinding the translator lets
|
|
4076
4125
|
// the translation plugin drive the active language at runtime (#87).
|
|
@@ -4158,7 +4207,7 @@ window.__ModuleLoader__.load({
|
|
|
4158
4207
|
mountSidebarJobs(toggle, translate('sidebar.jobsTitle'), (taskId) => { pendingTaskHighlight = taskId; }),
|
|
4159
4208
|
mountCronScreen(ctx, toggle)
|
|
4160
4209
|
];
|
|
4161
|
-
return () => { for (const dispose of off) dispose(); };
|
|
4210
|
+
return () => { for (const dispose of off) dispose(); stopStyleSelfHeal(); };
|
|
4162
4211
|
}, 'dsh-cron: client overlay');
|
|
4163
4212
|
|
|
4164
4213
|
exports.slots = { card: cardSlot, chip: chipSlot };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-cron",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.38",
|
|
4
4
|
"description": "Background automation runner for DSH: isolated agent runs, script/HTTP/SSH/Docker runtimes, cost guard, notifications, heartbeats.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|