on-codemerge
Version:
A WYSIWYG editor for on-codemerge is a user-friendly interface that allows users to edit and view their code in real time, exactly as it will appear in the final product
209 lines (202 loc) • 7.79 kB
JavaScript
/*! on-codemerge v1.3.1 @author Pavel Kuzmin @license MIT @homepage https://s00d.github.io/on-codemerge/ @repository git+https://github.com/s00d/on-codemerge.git Copyright (c) 2026 Pavel Kuzmin - Built on 2026-07-02T13:39:17.947Z */
var g = Object.defineProperty;
var u = (a, t, e) => t in a ? g(a, t, { enumerable: !0, configurable: !0, writable: !0, value: e }) : a[t] = e;
var c = (a, t, e) => u(a, typeof t != "symbol" ? t + "" : t, e);
class f {
constructor(t) {
c(this, "timersKey", "html-editor-timers");
c(this, "editor");
this.editor = t;
}
getTimers() {
const t = localStorage.getItem(this.timersKey);
return t ? JSON.parse(t).map((r) => ({
...r,
targetDate: new Date(r.targetDate)
})) : [];
}
getTimer(t) {
return this.getTimers().find((r) => r.id === t) || null;
}
createTimer(t) {
const e = this.getTimers(), r = {
id: crypto.randomUUID(),
title: t.title,
description: t.description,
targetDate: t.targetDate,
targetTime: t.targetTime,
color: t.color || "#3b82f6",
category: t.category,
tags: t.tags || [],
isActive: !0,
createdAt: Date.now(),
updatedAt: Date.now()
};
return e.push(r), localStorage.setItem(
this.timersKey,
JSON.stringify(e, (i, s) => s instanceof Date ? s.toISOString() : s)
), r;
}
updateTimer(t, e) {
const r = this.getTimers(), i = r.findIndex((n) => n.id === t);
if (i === -1)
throw new Error("Timer not found");
const s = {
...r[i],
...e,
updatedAt: Date.now()
};
return r[i] = s, localStorage.setItem(
this.timersKey,
JSON.stringify(r, (n, o) => o instanceof Date ? o.toISOString() : o)
), s;
}
deleteTimer(t) {
const e = this.getTimers().filter((r) => r.id !== t);
localStorage.setItem(this.timersKey, JSON.stringify(e));
}
getTimeLeft(t) {
let e;
t.targetDate instanceof Date ? e = t.targetDate : e = /* @__PURE__ */ new Date(`${t.targetDate}T${t.targetTime}`);
const r = /* @__PURE__ */ new Date(), i = e.getTime() - r.getTime();
if (i <= 0)
return {
days: 0,
hours: 0,
minutes: 0,
seconds: 0,
isExpired: !0
};
const s = Math.floor(i / (1e3 * 60 * 60 * 24)), n = Math.floor(i % (1e3 * 60 * 60 * 24) / (1e3 * 60 * 60)), o = Math.floor(i % (1e3 * 60 * 60) / (1e3 * 60)), d = Math.floor(i % (1e3 * 60) / 1e3);
return {
days: s,
hours: n,
minutes: o,
seconds: d,
isExpired: !1
};
}
// Генерация HTML таймера
generateTimerHTML(t) {
const e = this.getTimeLeft(t), r = t.color || "#3b82f6", i = t.category || this.editor.t("General"), s = t.tags && t.tags.length > 0 ? `<div class="timer-tags">${t.tags.map((l) => `<span class="timer-tag">${l}</span>`).join("")}</div>` : "", n = e.isExpired ? `<div class="timer-expired">${this.editor.t("Time expired")}</div>` : `<div class="timer-countdown" id="timer-countdown-${t.id}">
<div class="timer-unit">
<span class="timer-value" id="timer-days-${t.id}">${e.days}</span>
<span class="timer-label">${this.editor.t("days")}</span>
</div>
<div class="timer-unit">
<span class="timer-value" id="timer-hours-${t.id}">${e.hours.toString().padStart(2, "0")}</span>
<span class="timer-label">${this.editor.t("hours")}</span>
</div>
<div class="timer-unit">
<span class="timer-value" id="timer-minutes-${t.id}">${e.minutes.toString().padStart(2, "0")}</span>
<span class="timer-label">${this.editor.t("min")}</span>
</div>
<div class="timer-unit">
<span class="timer-value" id="timer-seconds-${t.id}">${e.seconds.toString().padStart(2, "0")}</span>
<span class="timer-label">${this.editor.t("sec")}</span>
</div>
</div>`;
let o;
t.targetDate instanceof Date ? o = t.targetDate : o = /* @__PURE__ */ new Date(`${t.targetDate}T${t.targetTime}`);
const d = o.toLocaleDateString("ru-RU", {
day: "numeric",
month: "short",
year: "numeric",
hour: "2-digit",
minute: "2-digit"
}), m = `
<script>
(function() {
const targetDate = new Date('${t.targetDate}T${t.targetTime}');
const expiredText = '${this.editor.t("Timer expired") || "Timer expired"}';
function updateTimer() {
const now = new Date();
const diff = targetDate.getTime() - now.getTime();
if (diff <= 0) {
// Таймер истек
const countdownEl = document.querySelector('[data-timer-id="${t.id}"] .timer-countdown');
if (countdownEl) {
countdownEl.innerHTML = '<div class="timer-expired">' + expiredText + '</div>';
}
return;
}
const days = Math.floor(diff / (1000 * 60 * 60 * 24));
const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
const seconds = Math.floor((diff % (1000 * 60)) / 1000);
const timerElement = document.querySelector('[data-timer-id="${t.id}"]');
if (timerElement) {
const daysEl = timerElement.querySelector('.timer-days');
const hoursEl = timerElement.querySelector('.timer-hours');
const minutesEl = timerElement.querySelector('.timer-minutes');
const secondsEl = timerElement.querySelector('.timer-seconds');
if (daysEl) daysEl.textContent = days;
if (hoursEl) hoursEl.textContent = hours.toString().padStart(2, '0');
if (minutesEl) minutesEl.textContent = minutes.toString().padStart(2, '0');
if (secondsEl) secondsEl.textContent = seconds.toString().padStart(2, '0');
}
}
// Обновляем каждую секунду
updateTimer();
setInterval(updateTimer, 1000);
})();
<\/script>
`;
return `
<div class="timer-widget" data-timer-id="${t.id}" style="--timer-color: ${t.color || "#3b82f6"}">
<div class="timer-header">
<div class="timer-title">${t.title}</div>
<div class="timer-category" style="background-color: ${r}">${i}</div>
</div>
${t.description ? `<div class="timer-description">${t.description}</div>` : ""}
<div class="timer-target-date">${this.editor.t("Until")}: ${d}</div>
${n}
${s}
</div>
${m}
`;
}
exportTimer(t) {
const e = this.getTimer(t);
if (!e)
throw new Error("Timer not found");
const r = {
timer: e,
exportDate: (/* @__PURE__ */ new Date()).toISOString()
};
return JSON.stringify(r, null, 2);
}
importTimer(t) {
try {
const r = JSON.parse(t).timer;
return this.createTimer({
title: r.title,
description: r.description,
targetDate: r.targetDate,
targetTime: r.targetTime,
color: r.color,
category: r.category,
tags: r.tags
});
} catch {
throw new Error("Invalid timer data format");
}
}
copyTimer(t) {
const e = this.getTimer(t);
if (!e)
throw new Error("Timer not found");
return this.createTimer({
title: `${e.title} (Копия)`,
description: e.description,
targetDate: e.targetDate,
targetTime: e.targetTime,
color: e.color,
category: e.category,
tags: e.tags
});
}
}
export {
f as TimerManager
};