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
75 lines (68 loc) • 6.68 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);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});class p{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=new Date(`${t.targetDate}T${t.targetTime}`);const r=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}}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=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: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})}}exports.TimerManager=p;