CI / build (push) Failing after 6m2s
Introduce a Node build system for minified CSS/JS with content hashes, add PWA support, i18n helpers, accessibility improvements, and more translatable strings. Move theme configuration from bookmarks to localStorage, add Playwright tests, and set up CI workflows.
1 line
49 KiB
JavaScript
1 line
49 KiB
JavaScript
document.addEventListener("DOMContentLoaded",()=>{const e=window.ShaarliProI18n||{t:function(e){return e}},t=["note","shaarli-note","todo","shaarli-todo","shaarli-pin","note-color-*","notebg-*","notefilter-*","font-*","readitlater","brain-dump","shaarli-archive"];function a(e){if(!e)return!1;const a=e.toLowerCase().trim();return function(){try{const e=localStorage.getItem("shaarli_hidden_tags");if(e)return JSON.parse(e)}catch(e){console.error("Error loading hidden tags:",e)}return[...t]}().some(e=>{const t=e.toLowerCase().trim();return t.includes("*")?function(e,t){return new RegExp("^"+e.replace(/\*/g,".*")+"$","i").test(t)}(t,a):t===a})}function s(){document.querySelectorAll(".link-tag[data-tag]").forEach(e=>{a(e.getAttribute("data-tag"))&&(e.style.display="none")}),document.querySelectorAll("#tagListContainer .list-group-item[data-tag-name]").forEach(e=>{a(e.getAttribute("data-tag-name"))&&(e.style.display="none")}),document.querySelectorAll(".tag-item[data-tag]").forEach(e=>{a(e.getAttribute("data-tag"))&&(e.style.display="none")});const e=document.getElementById("visibleTagCount");if(e){const t=document.querySelectorAll('#tagListContainer .list-group-item:not([style*="display: none"])');e.textContent=t.length}}s();new MutationObserver(e=>{let t=!1;e.forEach(e=>{"childList"===e.type&&e.addedNodes.forEach(e=>{e.nodeType===Node.ELEMENT_NODE&&(e.matches?.(".link-tag[data-tag], .tag-item[data-tag], [data-tag-name], .list-group-item[data-tag-name]")||e.querySelector?.(".link-tag[data-tag], .tag-item[data-tag], [data-tag-name], .list-group-item[data-tag-name]"))&&(t=!0)})}),t&&s()}).observe(document.body,{childList:!0,subtree:!0}),window.ShaarliProUtils={escapeHtml:function(e){if(null==e)return"";const t=document.createElement("div");return t.textContent=String(e),t.innerHTML},isTagHidden:a,filterHiddenTags:function(e){return Array.isArray(e)?e.filter(e=>!a(e)):[]}};const n=document.getElementById("links-list"),r=document.getElementById("view-grid-btn"),o=document.getElementById("view-list-btn"),i=document.getElementById("view-compact-btn");function l(e){n&&(n.classList.remove("view-grid","view-list","view-compact"),r?.classList.remove("active"),o?.classList.remove("active"),i?.classList.remove("active"),"list"===e?(n.classList.add("view-list"),o?.classList.add("active")):"compact"===e?(n.classList.add("view-compact"),i?.classList.add("active")):(n.classList.add("view-grid"),r?.classList.add("active")),localStorage.setItem("linksView",e))}l(localStorage.getItem("linksView")||"grid"),r?.addEventListener("click",()=>l("grid")),o?.addEventListener("click",()=>l("list")),i?.addEventListener("click",()=>l("compact"));if(document.querySelector(".page-thumbnails")){const t=document.querySelector(".thumbnail-placeholder"),a=document.querySelector(".thumbnail-link-title"),s=document.querySelector(".progress-current"),n=document.querySelector(".progress-actual"),r=document.querySelector('input[name="ids"]');if(r&&r.value){const o=r.value.split(","),i=o.length;let l=0;const u=function(r){fetch(shaarli.basePath+"/admin/shaare/"+r+"/update-thumbnail",{method:"PATCH",headers:{Accept:"application/json"}}).then(e=>e.json()).then(r=>{if(l++,a&&(a.textContent=r.title||e.t("Processing...")),t&&(t.innerHTML="",r.thumbnail)){const a=document.createElement("img");a.title=e.t("Current thumbnail"),a.src=r.thumbnail,a.style.maxWidth="100%",a.style.height="auto",t.appendChild(a)}s&&(s.textContent=l),n&&(n.style.width=100*l/i+"%"),l<i?u(o[l]):a&&(a.textContent=e.t("Thumbnail update done!"))}).catch(t=>{console.error("Failed to update thumbnail:",t),a&&(a.textContent=e.t("Error updating thumbnail #{index}",{index:l})),l++,l<i&&u(o[l])})};u(o[0])}}const u=document.getElementById("desc-modal"),d=document.getElementById("desc-modal-body"),c=document.getElementById("desc-modal-close");function p(e){u&&d&&(d.innerHTML="",e&&d.appendChild(e),u.classList.add("show"),document.body.style.overflow="hidden")}function h(){u&&(u.classList.remove("show"),document.body.style.overflow="")}c?.addEventListener("click",h),u?.addEventListener("click",e=>{e.target===u&&h()}),document.addEventListener("keydown",e=>{"Escape"===e.key&&u?.classList.contains("show")&&h()}),document.addEventListener("click",t=>{const a=t.target.closest(".view-desc-btn");if(a){t.preventDefault();const s=a.dataset.id,n=document.getElementById(s);if(n){const t=n.querySelector(".link-description");if(t)p(t.cloneNode(!0));else{const t=document.createElement("p");t.className="text-muted",t.textContent=e.t("No description available."),p(t)}}}});const m=document.getElementById("qrcode-modal"),g=document.getElementById("qrcode-modal-body"),y=document.getElementById("qrcode-modal-close");function v(){m&&(m.classList.remove("show"),document.body.style.overflow="")}y?.addEventListener("click",v),m?.addEventListener("click",e=>{e.target===m&&v()}),document.addEventListener("keydown",e=>{"Escape"===e.key&&m?.classList.contains("show")&&v()}),document.querySelectorAll(".link-plugin .linkqrcode, .link-plugin img.qrcode").forEach(t=>{const a="IMG"===t.tagName?t:t.querySelector("img.qrcode");if(!a)return;const s=a.dataset.permalink||"",n=a.closest("a")||a.parentElement,r=document.createElement("i");if(r.className="mdi mdi-qrcode","A"===n.tagName||n.classList.contains("linkqrcode")){const a=document.createElement("a");a.href="#",a.className="qrcode-trigger",a.title=e.t("QR Code"),a.dataset.permalink=s,a.appendChild(r);(t.classList.contains("linkqrcode")?t:t.closest(".linkqrcode")||t).replaceWith(a)}}),document.addEventListener("click",t=>{const a=t.target.closest(".qrcode-trigger, .link-plugin img.qrcode");if(!a)return;t.preventDefault(),t.stopPropagation();const s=a.dataset?.permalink||a.querySelector("img")?.dataset?.permalink||"",n=a.closest(".link-outer"),r=n?.querySelector(".link-title")?.textContent?.trim()||s;s&&function(t,a){function s(e){g.innerHTML="";const t=document.createElement("div");t.style.padding="2rem",t.style.color="var(--text-muted)",t.textContent=e,g.appendChild(t)}m&&g&&(s(e.t("Generating QR Code...")),m.classList.add("show"),document.body.style.overflow="hidden",function n(){if("undefined"!=typeof qr){const n=qr.image({size:8,value:t});if(n){if(g.innerHTML="",n.style.maxWidth="100%",n.style.borderRadius="0.5rem",n.style.background="white",n.style.padding="0.75rem",g.appendChild(n),a){const e=document.createElement("div");e.className="qrcode-modal-title",e.textContent=a,g.appendChild(e)}}else s(e.t("Failed to generate QR Code"))}else{const e=document.querySelector('input[name="js_base_path"]')?.value||"",t=document.createElement("script");t.src=e+"/plugins/qrcode/qr-1.1.3.min.js",document.body.appendChild(t),setTimeout(()=>n(),300)}}())}(s,r)});const f="readitlater",b=["readitlater","readlater","toread"],w=e=>(e||"").trim().toLowerCase(),k=e=>b.includes(w(e));async function E(t,a){const s=await fetch(t,{method:"GET",credentials:"same-origin"});if(!s.ok)throw new Error(e.t("Unable to load bookmark edit form."));const n=await s.text(),r=(new DOMParser).parseFromString(n,"text/html").querySelector('form[name="linkform"]');if(!r)throw new Error(e.t("Bookmark edit form not found."));const o=function(e){const t=new URLSearchParams;return e.querySelectorAll("input, textarea, select").forEach(e=>{e.name&&!e.disabled&&("checkbox"!==e.type?("radio"!==e.type||e.checked)&&t.append(e.name,e.value||""):e.checked&&t.append(e.name,e.value||"on"))}),t}(r),i=(o.get("lf_tags")||"").split(/[\s,]+/).map(e=>e.trim()).filter(Boolean).filter(e=>!k(e));a&&i.push(f),o.set("lf_tags",i.join(" ")),o.set("save_edit","1");if(!(await fetch(r.action,{method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded"},body:o.toString(),credentials:"same-origin"})).ok)throw new Error(e.t("Unable to save bookmark tags."))}function S(t,a){if(!t)return;t.classList.toggle("readitlater-active",a);let s=t.querySelector(".link-readlater-badge");a&&!s?(s=document.createElement("div"),s.className="link-readlater-badge",s.textContent=e.t("Read Later"),t.appendChild(s)):!a&&s&&s.remove();const n=t.querySelector(".readitlater-toggle-btn");if(n){const t=a?e.t("Remove from Read It Later"):e.t("Add to Read It Later");n.classList.toggle("active",a),n.dataset.active=a?"1":"0",n.setAttribute("title",t),n.setAttribute("aria-label",t);const s=n.querySelector("i");s&&(s.className="mdi "+(a?"mdi-bookmark-clock":"mdi-bookmark-clock-outline"))}!function(t,a){const s=t.querySelector(".link-tag-list");if(!s)return;const n=Array.from(s.querySelectorAll(".link-tag")).find(e=>{const t=e.dataset.tag||e.querySelector(".link-tag-link")?.textContent||e.textContent||"";return w(t)===f});if(!a)return void n?.remove();if(n)return;const r=document.createElement("span");r.className="link-tag",r.dataset.tag=f;const o=document.createElement("a");if(o.className="link-tag-link",o.href=`${shaarli.basePath}/add-tag/${encodeURIComponent(f)}`,o.textContent=f,r.appendChild(o),shaarli.isAuth){const t=document.createElement("button");t.type="button",t.className="tag-remove-btn",t.dataset.tag=f,t.setAttribute("aria-label",e.t("Delete tag {tag}",{tag:f})),t.title=e.t("Delete"),t.textContent="×",r.appendChild(t)}s.appendChild(r)}(t,a)}document.querySelectorAll(".link-outer").forEach(e=>{const t=Array.from(e.querySelectorAll(".link-tag")).map(e=>{const t=e.dataset.tag||e.querySelector(".link-tag-link")?.textContent||e.textContent||"";return w(t)}).some(k)||e.classList.contains("readitlater-active")||e.classList.contains("readitlater-unread");S(e,t)}),document.addEventListener("click",async t=>{const a=t.target.closest(".readitlater-toggle-btn");if(!a)return;t.preventDefault(),t.stopPropagation();const s=a.closest(".link-outer");if(!s)return;const n=function(e){if(!e)return"";const t=e.dataset.id;if(t)return`${shaarli.basePath}/admin/shaare/${encodeURIComponent(t)}`;const a=e.querySelector('.link-actions a[href*="/admin/shaare/"]:not([href*="/pin"]):not([href*="/delete"])');return a?a.href:""}(s);if(!n)return;const r=!(s.classList.contains("readitlater-active")||"1"===a.dataset.active);if(!a.disabled){a.disabled=!0,a.classList.add("is-loading");try{await E(n,r),S(s,r)}catch(t){console.error("Failed to toggle readitlater tag:",t),alert(e.t("Failed to toggle readitlater tag."))}finally{a.disabled=!1,a.classList.remove("is-loading")}}}),function(){const e=document.querySelectorAll('.bookmark-editor-form[data-batch-mode="0"]');if(!e.length)return;const t=e=>e.trim().replace(/\s+/g,"-");e.forEach(e=>{e.classList.add("is-enhanced");const a=e.querySelector(".bookmark-editor-source"),s=e.querySelector(".bookmark-markdown-editor"),n=e.querySelector(".bookmark-tags-hidden-input"),r=e.querySelector(".bookmark-tags-input"),o=e.querySelector(".bookmark-tags-list"),i=e.querySelector(".bookmark-tags-text-input"),l=e.querySelector(".bookmark-toggle-readlater"),u=e.querySelector(".bookmark-toggle-note"),d=e.querySelector(".bookmark-toggle-todo"),c=e.querySelector('input[name="lf_title"]'),p="dark"===document.documentElement.getAttribute("data-theme");if(a&&s&&window.toastui&&window.toastui.Editor){const t=window.innerWidth<992?"tab":"vertical";let n=null;const r=new window.toastui.Editor({el:s,height:"320px",initialEditType:"wysiwyg",previewStyle:t,initialValue:a.value||"",placeholder:a.getAttribute("placeholder")||"",theme:p?"dark":void 0,usageStatistics:!1});n=window.setInterval(()=>{if(!(a.value||"").trim())return;(r.getMarkdown()||"").trim()||r.setMarkdown(a.value||"",!1),window.clearInterval(n),n=null},250),e.addEventListener("submit",()=>{n&&(window.clearInterval(n),n=null),a.value=r.getMarkdown()})}else s&&(s.style.display="none",a&&(a.style.display="block"));if(!n||!o||!i)return;const h=(n.getAttribute("data-tag-options")||"").split(",").map(e=>t(e)).filter(Boolean),m=()=>h.filter(e=>!v.some(t=>t.toLowerCase()===e.toLowerCase()));let g=null;const y=()=>{g&&(g.list=m())};r&&r.addEventListener("click",()=>i.focus());let v=n.value.split(/[\s,]+/).map(e=>t(e)).filter(Boolean);v=v.filter((e,t,a)=>t===a.findIndex(t=>t.toLowerCase()===e.toLowerCase()));const f=e.querySelector('input[name="returnurl"]');f&&e.addEventListener("submit",()=>{(u?.checked||v.some(e=>/^note$/i.test(e)))&&(f.value=`${shaarli.basePath}/?searchtags=note`)});const b=()=>{n.value=v.join(" ")},w=()=>{l&&(l.checked=v.some(e=>/^(readitlater|readlater|toread)$/i.test(e)))},k=()=>{u&&(u.checked=v.some(e=>/^(note|#note|shaarli-note)$/i.test(e)))},E=()=>{d&&(d.checked=v.some(e=>/^(todo|#todo|shaarli-todo)$/i.test(e)))},S="📝",L="✅",I=e=>e&&e.startsWith(S),x=e=>e&&e.startsWith(L),C=e=>e?I(e)?e:"📝 "+e:"📝 ",D=e=>e?x(e)?e:"✅ "+e:"✅ ",B=e=>{if(!c)return;const t=c.value||"";var a;e?I(t)||(c.value=C(t)):I(t)&&(c.value=(a=t)?a.startsWith("📝 ")?a.substring(3):a.startsWith(S)?a.substring(2):a:"")},T=e=>{if(!c)return;const t=c.value||"";var a;e?x(t)||(c.value=D(t)):x(t)&&(c.value=(a=t)?a.startsWith("✅ ")?a.substring(2):a.startsWith(L)?a.substring(1):a:"")},q=e=>{const a=t(e);if(!a)return;v.some(e=>e.toLowerCase()===a.toLowerCase())||(v.push(a),b(),w(),k(),E(),N(),y())},P=e=>{v=v.filter(t=>t.toLowerCase()!==e.toLowerCase()),b(),w(),k(),E(),N(),y()},A=()=>{const e=i.value;e.trim()&&(e.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean).forEach(q),i.value="",y())};function N(){o.innerHTML="",v.forEach(e=>{const t=document.createElement("span");t.className="bookmark-tag-pill",t.setAttribute("data-tag",e);const a=document.createElement("span");a.className="bookmark-tag-label",a.textContent=e;const s=document.createElement("button");s.type="button",s.className="bookmark-tag-remove",s.setAttribute("aria-label",`Remove tag ${e}`),s.innerHTML='<i class="mdi mdi-close" aria-hidden="true"></i>',s.addEventListener("click",()=>P(e)),t.appendChild(a),t.appendChild(s),o.appendChild(t)})}if(i.addEventListener("keydown",e=>{const t=Boolean(g&&g.ul&&!g.ul.hasAttribute("hidden"));if(" "===e.key||","===e.key||"Enter"===e.key&&!t)return e.preventDefault(),void A();"Backspace"===e.key&&!i.value&&v.length&&P(v[v.length-1])}),i.addEventListener("blur",A),i.addEventListener("paste",e=>{const t=e.clipboardData?e.clipboardData.getData("text"):"";t&&(e.preventDefault(),t.split(/[\s,]+/).map(e=>e.trim()).filter(Boolean).forEach(q),i.value="")}),l&&l.addEventListener("change",()=>{v=v.filter(e=>!/^(readitlater|readlater|toread)$/i.test(e)),l.checked&&v.push("readitlater"),b(),k(),N(),y()}),u&&u.addEventListener("change",()=>{v=v.filter(e=>!/^note$/i.test(e)),u.checked?(v.push("note"),B(!0)):B(!1),b(),w(),E(),N(),y()}),d&&d.addEventListener("change",()=>{v=v.filter(e=>!/^shaarli-todo$/i.test(e)),d.checked?(v.push("shaarli-todo"),T(!0)):T(!1),b(),w(),k(),N(),y()}),window.Awesomplete&&h.length&&(g=new window.Awesomplete(i,{list:m(),minChars:1,maxItems:8,autoFirst:!0,sort:!1,filter:window.Awesomplete.FILTER_CONTAINS}),i.addEventListener("input",()=>{y(),g.evaluate()}),i.addEventListener("awesomplete-selectcomplete",A)),e.addEventListener("submit",A),e.addEventListener("submit",()=>{try{if(!window.ShaarItRules)return;const t=e.querySelector('input[name="lf_url"]'),a=t?(t.value||"").trim():"";if(!v.some(e=>/^(todo|shaarli-todo)$/i.test(e)))return;if(v.some(e=>/^shaarli-todo$/i.test(e))&&(v=v.filter(e=>!/^shaarli-todo$/i.test(e)),v.some(e=>/^todo$/i.test(e))||v.push("todo"),b()),!a||/^https?:\/\/shaarli-todo/.test(a)||"http://shaarli-todo"===a){const e=window.ShaarItRules.generateTodoUrl();t.value=e}}catch(e){console.warn("[shaarit] todo migration failed:",e)}}),e.addEventListener("submit",()=>{try{if(!window.ShaarItRules)return;const t=e.querySelector('input[name="lf_url"]'),a=t?(t.value||"").trim():"";if(!a)return;const s={url:a,tags:v};if(window.ShaarItRules.isNote(s)||window.ShaarItRules.isTodo(s))return;const n=window.ShaarItRules.detectContentType(a);if(!n||!n.tags||0===n.tags.length)return;v=window.ShaarItRules.mergeAutoTags(v,n.tags),b()}catch(e){console.warn("[shaarit] content-type auto-tagging failed:",e)}}),b(),w(),k(),E(),N(),y(),d&&d.checked&&c){const e=c.value||"";x(e)||e.trim()?x(e)||(c.value=D(e)):c.value="✅ "}else if(u&&u.checked&&c){const e=c.value||"";"Note:"===e||"Note"===e?c.value="📝 ":I(e)||e.trim()?I(e)||(c.value=C(e)):c.value="📝 "}})}(),function(){const e=document.querySelector(".button-batch-addform"),t=document.querySelector("form.batch-addform");e&&t&&e.addEventListener("click",()=>{const a=t.classList.contains("hidden");if(t.classList.toggle("hidden"),e.setAttribute("aria-expanded",a?"true":"false"),a){const e=t.querySelector("#urls");e?.focus()}});const a=document.querySelector(".page-edit-link-batch");if(!a)return;const s=document.getElementById("progress-overlay"),n=a.querySelector(".progress-current"),r=a.querySelector(".progress-total"),o=a.querySelector(".progress-actual"),i=a.querySelectorAll('button[name="save_edit_batch"]'),l=()=>Array.from(a.querySelectorAll('.bookmark-editor-form[data-batch-mode="1"]')),u=(e,t)=>{if(n&&(n.textContent=String(e)),r&&(r.textContent=String(t)),o){const a=t>0?100*e/t:0;o.style.width=`${a}%`}},d=()=>{const e=l().length;u(0,e)};d(),a.addEventListener("click",e=>{const t=e.target.closest('button[name="cancel-batch-link"]');if(!t)return;e.preventDefault();const a=t.closest(".editlinkform");a?.remove(),d()}),i.forEach(e=>{e.addEventListener("click",async e=>{e.preventDefault();const t=l();t.length&&(i.forEach(e=>{e.disabled=!0}),await async function(e){const t=e.length;let a=0;u(0,t),s?.classList.remove("hidden");for(const s of e){const e=new FormData(s);try{const t=await fetch(s.action||`${shaarli.basePath}/admin/shaare`,{method:"POST",body:e,credentials:"same-origin"});t.ok||console.error("Batch save failed with status",t.status)}catch(e){console.error("Batch save request failed",e)}a+=1,u(a,t)}window.location.href=`${shaarli.basePath}/`}(t))})})}();const L=[".mp3",".mp4",".ogg",".webm",".m3u8",".flac",".wav",".aac",".m4a",".opus",".wma",".oga",".m3u",".pls"];function I(e){if(!e)return!1;for(var t=e.toLowerCase().split("?")[0].split("#")[0],a=0;a<L.length;a++)if(t.endsWith(L[a]))return!0;return!!/\/(stream|listen|live|icecast|shoutcast)(\/|$|\?)/i.test(e)}var x=document.getElementById("media-player-bar"),C=document.getElementById("media-player-play"),D=document.getElementById("media-player-play-icon"),B=document.getElementById("media-player-title"),T=document.getElementById("media-player-progress"),q=document.getElementById("media-player-time"),P=document.getElementById("media-player-volume"),A=document.getElementById("media-player-vol-btn"),N=document.getElementById("media-player-vol-icon"),M=document.getElementById("media-player-close"),R=null,F=null;try{F=new BroadcastChannel("shaarli-media-player")}catch(e){}function O(t,a){if(localStorage.setItem("mediaPlayerUrl",t),localStorage.setItem("mediaPlayerTitle",a||t),localStorage.setItem("mediaPlayerPlaying","true"),R&&!R.closed)F&&F.postMessage({type:"player-load",url:t,title:a}),R.focus();else{var s=function(){const t="dark"===document.documentElement.getAttribute("data-theme")?"dark":"light";var a=[];return a.push("<!DOCTYPE html>"),a.push('<html data-theme="'+t+'">'),a.push("<head>"),a.push('<meta charset="utf-8">'),a.push('<meta name="viewport" content="width=device-width, initial-scale=1.0">'),a.push("<title>♪ Shaarli Player</title>"),a.push('<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/MaterialDesign-Webfont/7.2.96/css/materialdesignicons.min.css">'),a.push("<style>"),a.push(":root {"),a.push(" --primary: #2563eb;"),a.push(" --primary-hover: #1d4ed8;"),a.push(" --primary-light: rgba(37,99,235,0.08);"),a.push(" --bg-body: #f1f5f9;"),a.push(" --bg-card: #ffffff;"),a.push(" --text-main: #1e293b;"),a.push(" --text-secondary: #64748b;"),a.push(" --text-muted: #94a3b8;"),a.push(" --border: #e2e8f0;"),a.push(" --danger: #ef4444;"),a.push(" --shadow: 0 1px 3px rgba(0,0,0,0.1);"),a.push("}"),a.push('[data-theme="dark"] {'),a.push(" --primary: #3b82f6;"),a.push(" --primary-hover: #60a5fa;"),a.push(" --primary-light: rgba(59,130,246,0.12);"),a.push(" --bg-body: #0f172a;"),a.push(" --bg-card: #1e293b;"),a.push(" --text-main: #e2e8f0;"),a.push(" --text-secondary: #94a3b8;"),a.push(" --text-muted: #64748b;"),a.push(" --border: #334155;"),a.push(" --danger: #f87171;"),a.push(" --shadow: 0 1px 3px rgba(0,0,0,0.3);"),a.push("}"),a.push("* { box-sizing: border-box; margin: 0; padding: 0; }"),a.push("body {"),a.push(" font-family: -apple-system, BlinkMacSystemFont, 'Inter', 'Segoe UI', sans-serif;"),a.push(" background: var(--bg-body);"),a.push(" color: var(--text-main);"),a.push(" display: flex;"),a.push(" flex-direction: column;"),a.push(" align-items: center;"),a.push(" justify-content: center;"),a.push(" min-height: 100vh;"),a.push(" padding: 1rem;"),a.push(" user-select: none;"),a.push(" overflow: hidden;"),a.push("}"),a.push(".player-card {"),a.push(" background: var(--bg-card);"),a.push(" border: 1px solid var(--border);"),a.push(" border-radius: 1rem;"),a.push(" box-shadow: var(--shadow);"),a.push(" padding: 1.5rem;"),a.push(" width: 100%;"),a.push(" max-width: 420px;"),a.push(" display: flex;"),a.push(" flex-direction: column;"),a.push(" gap: 1rem;"),a.push("}"),a.push(".player-artwork {"),a.push(" display: flex;"),a.push(" align-items: center;"),a.push(" justify-content: center;"),a.push(" background: var(--primary-light);"),a.push(" border-radius: 0.75rem;"),a.push(" padding: 1.5rem;"),a.push(" position: relative;"),a.push(" overflow: hidden;"),a.push("}"),a.push(".player-artwork i {"),a.push(" font-size: 3rem;"),a.push(" color: var(--primary);"),a.push(" animation: pulse-icon 2s ease-in-out infinite;"),a.push(" opacity: 0.6;"),a.push("}"),a.push(".player-artwork i.playing {"),a.push(" animation: pulse-icon 1.5s ease-in-out infinite;"),a.push(" opacity: 1;"),a.push("}"),a.push("@keyframes pulse-icon {"),a.push(" 0%, 100% { transform: scale(1); }"),a.push(" 50% { transform: scale(1.08); }"),a.push("}"),a.push(".live-badge {"),a.push(" position: absolute;"),a.push(" top: 0.5rem;"),a.push(" right: 0.5rem;"),a.push(" background: var(--danger);"),a.push(" color: white;"),a.push(" font-size: 0.65rem;"),a.push(" font-weight: 700;"),a.push(" padding: 0.15rem 0.5rem;"),a.push(" border-radius: 999px;"),a.push(" text-transform: uppercase;"),a.push(" letter-spacing: 0.06em;"),a.push(" display: none;"),a.push("}"),a.push(".live-badge.show { display: block; }"),a.push(".player-title {"),a.push(" font-size: 0.9rem;"),a.push(" font-weight: 600;"),a.push(" color: var(--text-main);"),a.push(" text-align: center;"),a.push(" overflow: hidden;"),a.push(" text-overflow: ellipsis;"),a.push(" white-space: nowrap;"),a.push(" max-width: 100%;"),a.push("}"),a.push(".player-progress-wrap { width: 100%; }"),a.push(".player-progress {"),a.push(" -webkit-appearance: none;"),a.push(" appearance: none;"),a.push(" width: 100%;"),a.push(" height: 5px;"),a.push(" background: var(--border);"),a.push(" border-radius: 3px;"),a.push(" outline: none;"),a.push(" cursor: pointer;"),a.push("}"),a.push(".player-progress:hover { height: 7px; }"),a.push(".player-progress::-webkit-slider-thumb {"),a.push(" -webkit-appearance: none;"),a.push(" width: 14px; height: 14px;"),a.push(" border-radius: 50%;"),a.push(" background: var(--primary);"),a.push(" cursor: pointer;"),a.push(" border: 2px solid white;"),a.push(" box-shadow: 0 1px 4px rgba(0,0,0,0.2);"),a.push("}"),a.push(".player-progress::-moz-range-thumb {"),a.push(" width: 14px; height: 14px;"),a.push(" border-radius: 50%;"),a.push(" background: var(--primary);"),a.push(" cursor: pointer;"),a.push(" border: 2px solid white;"),a.push(" box-shadow: 0 1px 4px rgba(0,0,0,0.2);"),a.push("}"),a.push(".player-time {"),a.push(" display: flex;"),a.push(" justify-content: space-between;"),a.push(" font-size: 0.7rem;"),a.push(" color: var(--text-muted);"),a.push(" margin-top: 0.2rem;"),a.push(" font-variant-numeric: tabular-nums;"),a.push("}"),a.push(".player-controls {"),a.push(" display: flex;"),a.push(" align-items: center;"),a.push(" justify-content: center;"),a.push(" gap: 0.75rem;"),a.push("}"),a.push(".ctrl-btn {"),a.push(" display: flex;"),a.push(" align-items: center;"),a.push(" justify-content: center;"),a.push(" border: none;"),a.push(" border-radius: 50%;"),a.push(" cursor: pointer;"),a.push(" transition: all 0.2s ease;"),a.push(" background: transparent;"),a.push(" color: var(--text-secondary);"),a.push("}"),a.push(".ctrl-btn:hover { background: var(--primary-light); color: var(--primary); }"),a.push(".ctrl-btn.sm { width: 36px; height: 36px; font-size: 1.1rem; }"),a.push(".ctrl-btn.lg {"),a.push(" width: 52px; height: 52px;"),a.push(" background: var(--primary);"),a.push(" color: white;"),a.push(" font-size: 1.5rem;"),a.push("}"),a.push(".ctrl-btn.lg:hover { background: var(--primary-hover); transform: scale(1.06); }"),a.push(".ctrl-btn.close:hover { background: rgba(239,68,68,0.1); color: var(--danger); }"),a.push(".volume-wrap {"),a.push(" display: flex;"),a.push(" align-items: center;"),a.push(" gap: 0.4rem;"),a.push(" width: 100%;"),a.push("}"),a.push(".volume-slider {"),a.push(" -webkit-appearance: none;"),a.push(" appearance: none;"),a.push(" flex: 1;"),a.push(" height: 4px;"),a.push(" background: var(--border);"),a.push(" border-radius: 2px;"),a.push(" outline: none;"),a.push(" cursor: pointer;"),a.push("}"),a.push(".volume-slider::-webkit-slider-thumb {"),a.push(" -webkit-appearance: none;"),a.push(" width: 12px; height: 12px;"),a.push(" border-radius: 50%;"),a.push(" background: var(--primary);"),a.push(" cursor: pointer;"),a.push("}"),a.push(".volume-slider::-moz-range-thumb {"),a.push(" width: 12px; height: 12px;"),a.push(" border-radius: 50%;"),a.push(" background: var(--primary);"),a.push(" cursor: pointer;"),a.push("}"),a.push(".no-media {"),a.push(" text-align: center;"),a.push(" color: var(--text-muted);"),a.push(" padding: 2rem;"),a.push(" font-size: 0.9rem;"),a.push("}"),a.push(".no-media i {"),a.push(" font-size: 3rem;"),a.push(" display: block;"),a.push(" margin-bottom: 1rem;"),a.push(" opacity: 0.4;"),a.push("}"),a.push("</style>"),a.push("</head>"),a.push("<body>"),a.push(""),a.push('<div class="player-card" id="player-card">'),a.push(' <div class="player-artwork" id="artwork">'),a.push(' <i class="mdi mdi-music-note" id="artwork-icon"></i>'),a.push(' <span class="live-badge" id="live-badge">'+e.t("LIVE")+"</span>"),a.push(" </div>"),a.push(' <div class="player-title" id="title">'+e.t("Loading...")+"</div>"),a.push(' <div class="player-progress-wrap" id="progress-wrap">'),a.push(' <input type="range" class="player-progress" id="progress" min="0" max="100" value="0" step="0.1">'),a.push(' <div class="player-time">'),a.push(' <span id="time-current">0:00</span>'),a.push(' <span id="time-total">0:00</span>'),a.push(" </div>"),a.push(" </div>"),a.push(' <div class="player-controls">'),a.push(' <button class="ctrl-btn sm" id="vol-btn" title="'+e.t("Mute/Unmute")+'">'),a.push(' <i class="mdi mdi-volume-high" id="vol-icon"></i>'),a.push(" </button>"),a.push(' <button class="ctrl-btn lg" id="play-btn" title="'+e.t("Play/Pause")+'">'),a.push(' <i class="mdi mdi-play" id="play-icon"></i>'),a.push(" </button>"),a.push(' <button class="ctrl-btn sm close" id="close-btn" title="'+e.t("Stop & Close")+'">'),a.push(' <i class="mdi mdi-close"></i>'),a.push(" </button>"),a.push(" </div>"),a.push(' <div class="volume-wrap">'),a.push(' <i class="mdi mdi-volume-low" style="color:var(--text-muted);font-size:0.85rem;"></i>'),a.push(' <input type="range" class="volume-slider" id="volume" min="0" max="1" value="0.8" step="0.01">'),a.push(' <i class="mdi mdi-volume-high" style="color:var(--text-muted);font-size:0.85rem;"></i>'),a.push(" </div>"),a.push("</div>"),a.push(""),a.push('<div class="no-media" id="no-media" style="display:none;">'),a.push(' <i class="mdi mdi-music-note-off"></i>'),a.push(" No media selected. Click play on a bookmark to start."),a.push("</div>"),a.push(""),a.push('<audio id="audio" preload="metadata"></audio>'),a.push(""),a.push("<script>"),a.push("(function() {"),a.push(" // --- DOM refs ---"),a.push(" var audio = document.getElementById('audio');"),a.push(" var playBtn = document.getElementById('play-btn');"),a.push(" var playIcon = document.getElementById('play-icon');"),a.push(" var closeBtn = document.getElementById('close-btn');"),a.push(" var progress = document.getElementById('progress');"),a.push(" var progressWrap = document.getElementById('progress-wrap');"),a.push(" var timeCurrent = document.getElementById('time-current');"),a.push(" var timeTotal = document.getElementById('time-total');"),a.push(" var volumeSlider = document.getElementById('volume');"),a.push(" var volBtn = document.getElementById('vol-btn');"),a.push(" var volIcon = document.getElementById('vol-icon');"),a.push(" var artworkIcon = document.getElementById('artwork-icon');"),a.push(" var liveBadge = document.getElementById('live-badge');"),a.push(" var titleEl = document.getElementById('title');"),a.push(" var playerCard = document.getElementById('player-card');"),a.push(" var noMediaEl = document.getElementById('no-media');"),a.push(""),a.push(" var currentUrl = '';"),a.push(" var currentTitle = '';"),a.push(" var prevVol = 0.8;"),a.push(""),a.push(" // --- Apply theme ---"),a.push(" var savedTheme = localStorage.getItem('shaarliTheme') || 'light';"),a.push(" document.documentElement.setAttribute('data-theme', savedTheme);"),a.push(""),a.push(" // --- BroadcastChannel for communication with main page ---"),a.push(" var channel = null;"),a.push(" try {"),a.push(" channel = new BroadcastChannel('shaarli-media-player');"),a.push(" } catch(e) {"),a.push(" // BroadcastChannel not supported, fallback to localStorage events"),a.push(" }"),a.push(""),a.push(" // --- Helpers ---"),a.push(" function fmt(s) {"),a.push(" if (!s || isNaN(s) || !isFinite(s)) return '0:00';"),a.push(" var m = Math.floor(s / 60);"),a.push(" var sec = Math.floor(s % 60);"),a.push(" return m + ':' + (sec < 10 ? '0' : '') + sec;"),a.push(" }"),a.push(""),a.push(" function updateVolIcon(v) {"),a.push(" if (v <= 0) volIcon.className = 'mdi mdi-volume-off';"),a.push(" else if (v < 0.5) volIcon.className = 'mdi mdi-volume-medium';"),a.push(" else volIcon.className = 'mdi mdi-volume-high';"),a.push(" }"),a.push(""),a.push(" function broadcastState() {"),a.push(" var state = {"),a.push(" type: 'player-state',"),a.push(" url: currentUrl,"),a.push(" title: currentTitle,"),a.push(" playing: !audio.paused,"),a.push(" currentTime: audio.currentTime,"),a.push(" duration: audio.duration,"),a.push(" volume: audio.volume"),a.push(" };"),a.push(" // Save to localStorage for page reloads"),a.push(" localStorage.setItem('mediaPopupState', JSON.stringify(state));"),a.push(" // Broadcast via channel"),a.push(" if (channel) {"),a.push(" try { channel.postMessage(state); } catch(e) {}"),a.push(" }"),a.push(" }"),a.push(""),a.push(" function loadAndPlay(url, title) {"),a.push(" if (!url) return;"),a.push(" currentUrl = url;"),a.push(" currentTitle = title || url;"),a.push(" titleEl.textContent = currentTitle;"),a.push(" document.title = '\\u266A ' + currentTitle;"),a.push(" audio.src = url;"),a.push(" audio.volume = parseFloat(volumeSlider.value);"),a.push(" audio.play().catch(function() {});"),a.push(""),a.push(" playerCard.style.display = '';"),a.push(" noMediaEl.style.display = 'none';"),a.push(""),a.push(" // Update localStorage keys (for the main page bar)"),a.push(" localStorage.setItem('mediaPlayerUrl', url);"),a.push(" localStorage.setItem('mediaPlayerTitle', currentTitle);"),a.push(" localStorage.setItem('mediaPlayerPlaying', 'true');"),a.push(" }"),a.push(""),a.push(" // --- Audio events ---"),a.push(" audio.addEventListener('play', function() {"),a.push(" playIcon.className = 'mdi mdi-pause';"),a.push(" artworkIcon.classList.add('playing');"),a.push(" broadcastState();"),a.push(" });"),a.push(""),a.push(" audio.addEventListener('pause', function() {"),a.push(" playIcon.className = 'mdi mdi-play';"),a.push(" artworkIcon.classList.remove('playing');"),a.push(" broadcastState();"),a.push(" });"),a.push(""),a.push(" audio.addEventListener('timeupdate', function() {"),a.push(" if (!audio.duration) return;"),a.push(" if (isFinite(audio.duration)) {"),a.push(" progress.value = (audio.currentTime / audio.duration) * 100;"),a.push(" timeCurrent.textContent = fmt(audio.currentTime);"),a.push(" }"),a.push(" // Sync every 2 seconds"),a.push(" if (Math.floor(audio.currentTime) % 2 === 0) broadcastState();"),a.push(" });"),a.push(""),a.push(" audio.addEventListener('loadedmetadata', function() {"),a.push(" if (!isFinite(audio.duration)) {"),a.push(" liveBadge.classList.add('show');"),a.push(" progressWrap.style.display = 'none';"),a.push(" artworkIcon.className = 'mdi mdi-radio-tower playing';"),a.push(" } else {"),a.push(" liveBadge.classList.remove('show');"),a.push(" progressWrap.style.display = '';"),a.push(" timeTotal.textContent = fmt(audio.duration);"),a.push(" artworkIcon.className = 'mdi mdi-music-note';"),a.push(" if (!audio.paused) artworkIcon.classList.add('playing');"),a.push(" }"),a.push(" });"),a.push(""),a.push(" audio.addEventListener('ended', function() {"),a.push(" playIcon.className = 'mdi mdi-play';"),a.push(" progress.value = 0;"),a.push(" artworkIcon.classList.remove('playing');"),a.push(" broadcastState();"),a.push(" });"),a.push(""),a.push(" audio.addEventListener('error', function() {"),a.push(" titleEl.textContent = "+JSON.stringify(e.t("Error loading media"))+";"),a.push(" playIcon.className = 'mdi mdi-play';"),a.push(" artworkIcon.classList.remove('playing');"),a.push(" });"),a.push(""),a.push(" // --- Player controls ---"),a.push(" playBtn.addEventListener('click', function() {"),a.push(" if (audio.paused) audio.play().catch(function() {});"),a.push(" else audio.pause();"),a.push(" });"),a.push(""),a.push(" closeBtn.addEventListener('click', function() {"),a.push(" audio.pause();"),a.push(" audio.src = '';"),a.push(" localStorage.removeItem('mediaPopupState');"),a.push(" localStorage.removeItem('mediaPlayerUrl');"),a.push(" localStorage.removeItem('mediaPlayerTitle');"),a.push(" localStorage.removeItem('mediaPlayerPlaying');"),a.push(" if (channel) {"),a.push(" try { channel.postMessage({ type: 'player-closed' }); } catch(e) {}"),a.push(" }"),a.push(" window.close();"),a.push(" });"),a.push(""),a.push(" progress.addEventListener('input', function() {"),a.push(" if (audio.duration && isFinite(audio.duration)) {"),a.push(" audio.currentTime = (progress.value / 100) * audio.duration;"),a.push(" }"),a.push(" });"),a.push(""),a.push(" volumeSlider.addEventListener('input', function() {"),a.push(" audio.volume = parseFloat(volumeSlider.value);"),a.push(" updateVolIcon(audio.volume);"),a.push(" broadcastState();"),a.push(" });"),a.push(""),a.push(" volBtn.addEventListener('click', function() {"),a.push(" if (audio.volume > 0) {"),a.push(" prevVol = audio.volume;"),a.push(" audio.volume = 0;"),a.push(" volumeSlider.value = 0;"),a.push(" } else {"),a.push(" audio.volume = prevVol || 0.8;"),a.push(" volumeSlider.value = audio.volume;"),a.push(" }"),a.push(" updateVolIcon(audio.volume);"),a.push(" broadcastState();"),a.push(" });"),a.push(""),a.push(" // --- Listen for commands from main page via BroadcastChannel ---"),a.push(" if (channel) {"),a.push(" channel.addEventListener('message', function(e) {"),a.push(" var msg = e.data;"),a.push(" if (!msg || !msg.type) return;"),a.push(""),a.push(" if (msg.type === 'player-load') {"),a.push(" loadAndPlay(msg.url, msg.title);"),a.push(" } else if (msg.type === 'player-toggle') {"),a.push(" if (audio.paused) audio.play().catch(function() {});"),a.push(" else audio.pause();"),a.push(" } else if (msg.type === 'player-stop') {"),a.push(" audio.pause();"),a.push(" audio.src = '';"),a.push(" localStorage.removeItem('mediaPopupState');"),a.push(" localStorage.removeItem('mediaPlayerUrl');"),a.push(" localStorage.removeItem('mediaPlayerTitle');"),a.push(" localStorage.removeItem('mediaPlayerPlaying');"),a.push(" if (channel) {"),a.push(" try { channel.postMessage({ type: 'player-closed' }); } catch(e) {}"),a.push(" }"),a.push(" window.close();"),a.push(" } else if (msg.type === 'player-seek') {"),a.push(" if (audio.duration && isFinite(audio.duration)) {"),a.push(" audio.currentTime = (msg.value / 100) * audio.duration;"),a.push(" }"),a.push(" } else if (msg.type === 'player-volume') {"),a.push(" audio.volume = parseFloat(msg.value);"),a.push(" volumeSlider.value = msg.value;"),a.push(" updateVolIcon(audio.volume);"),a.push(" } else if (msg.type === 'player-mute-toggle') {"),a.push(" if (audio.volume > 0) {"),a.push(" prevVol = audio.volume;"),a.push(" audio.volume = 0;"),a.push(" volumeSlider.value = 0;"),a.push(" } else {"),a.push(" audio.volume = prevVol || 0.8;"),a.push(" volumeSlider.value = audio.volume;"),a.push(" }"),a.push(" updateVolIcon(audio.volume);"),a.push(" broadcastState();"),a.push(" }"),a.push(" });"),a.push(" }"),a.push(""),a.push(" // --- Also listen for localStorage changes (fallback for no BroadcastChannel) ---"),a.push(" window.addEventListener('storage', function(e) {"),a.push(" if (e.key === 'mediaPopupState' && e.newValue) {"),a.push(" try {"),a.push(" var state = JSON.parse(e.newValue);"),a.push(" if (state.url) {"),a.push(" loadAndPlay(state.url, state.title);"),a.push(" }"),a.push(" } catch(err) {}"),a.push(" } else if (e.key === 'mediaPlayerClosed') {"),a.push(" if (playerBar) playerBar.classList.remove('show');"),a.push(" playerPopup = null;"),a.push(" }"),a.push(" });"),a.push(""),a.push(" // --- Clean up on window close ---"),a.push(" window.addEventListener('beforeunload', function() {"),a.push(" localStorage.removeItem('mediaPopupState');"),a.push(" if (channel) {"),a.push(" try { channel.postMessage({ type: 'player-closed' }); } catch(e) {}"),a.push(" }"),a.push(" });"),a.push(""),a.push(" // --- Initial load: read config from localStorage ---"),a.push(" var initUrl = localStorage.getItem('mediaPlayerUrl');"),a.push(" var initTitle = localStorage.getItem('mediaPlayerTitle');"),a.push(""),a.push(" if (initUrl) {"),a.push(" loadAndPlay(initUrl, initTitle);"),a.push(" } else {"),a.push(" playerCard.style.display = 'none';"),a.push(" noMediaEl.style.display = '';"),a.push(" }"),a.push(""),a.push(" // Announce that the popup is ready"),a.push(" if (channel) {"),a.push(" try { channel.postMessage({ type: 'player-ready' }); } catch(e) {}"),a.push(" }"),a.push("})();"),a.push("<\/script>"),a.push("</body>"),a.push("</html>"),a.push(""),a.join("\n")}(),n=new Blob([s],{type:"text/html"}),r=URL.createObjectURL(n);if(R=window.open(r,"shaarli-media-player","width=460,height=420,resizable=yes,scrollbars=no,toolbar=no,menubar=no,location=no,status=no"),setTimeout(function(){URL.revokeObjectURL(r)},5e3),!R)return URL.revokeObjectURL(r),void function(e,t){var a=document.getElementById("media-player-audio");if(!x||!a)return;a.src=e,a.volume=parseFloat(P?P.value:.8),a.play().catch(function(){}),U(t,!0)}(t,a)}U(a,!0)}function U(t,a){x&&(B&&(B.textContent=t||e.t("No media")),D&&(D.className=a?"mdi mdi-pause":"mdi mdi-play"),x.classList.add("show"))}function _(e){if(!e||isNaN(e)||!isFinite(e))return"0:00";var t=Math.floor(e/60),a=Math.floor(e%60);return t+":"+(a<10?"0":"")+a}function $(e){N&&(N.className=e<=0?"mdi mdi-volume-off":e<.5?"mdi mdi-volume-medium":"mdi mdi-volume-high")}C&&C.addEventListener("click",function(){if(F&&F.postMessage({type:"player-toggle"}),!R||R.closed){var e=localStorage.getItem("mediaPlayerUrl"),t=localStorage.getItem("mediaPlayerTitle");e&&O(e,t||e)}}),M&&M.addEventListener("click",function(){if(F&&F.postMessage({type:"player-stop"}),R&&!R.closed)try{R.close()}catch(e){}var e=document.getElementById("media-player-audio");e&&(e.pause(),e.src=""),x&&x.classList.remove("show"),localStorage.removeItem("mediaPlayerUrl"),localStorage.removeItem("mediaPlayerTitle"),localStorage.removeItem("mediaPlayerPosition"),localStorage.removeItem("mediaPlayerPlaying"),localStorage.removeItem("mediaPopupState"),R=null}),T&&T.addEventListener("input",function(){F&&F.postMessage({type:"player-seek",value:T.value})}),P&&P.addEventListener("input",function(){F&&F.postMessage({type:"player-volume",value:P.value}),$(P.value)}),A&&A.addEventListener("click",function(){F&&F.postMessage({type:"player-mute-toggle"})}),F&&F.addEventListener("message",function(t){var a=t.data;a&&a.type&&("player-state"===a.type?(U(a.title,a.playing),T&&isFinite(a.duration)&&a.duration>0?(T.value=a.currentTime/a.duration*100,T.style.display=""):T&&!isFinite(a.duration)&&(T.style.display="none"),q&&(isFinite(a.duration)?q.textContent=_(a.currentTime)+" / "+_(a.duration):q.textContent=e.t("LIVE")),void 0!==a.volume&&($(a.volume),P&&(P.value=a.volume))):"player-closed"===a.type&&(x&&x.classList.remove("show"),localStorage.removeItem("mediaPlayerUrl"),localStorage.removeItem("mediaPlayerTitle"),localStorage.removeItem("mediaPlayerPlaying"),localStorage.removeItem("mediaPopupState"),R=null))}),window.addEventListener("storage",function(e){if("mediaPopupState"===e.key&&e.newValue)try{var t=JSON.parse(e.newValue);U(t.title,t.playing)}catch(e){}else"mediaPlayerClosed"===e.key&&(x&&x.classList.remove("show"),R=null)}),document.querySelectorAll(".link-outer").forEach(function(t){var a=t.querySelector(".link-url"),s=t.querySelector(".link-title");if(a){var n=a.textContent.trim(),r=s&&s.getAttribute("href")||n,o=!1,i=t.dataset.id||"";if(t.querySelectorAll(".link-tag[data-tag]").forEach(function(e){"note"===e.dataset.tag&&(o=!0)}),o&&s&&s.addEventListener("click",function(e){if(0===e.button&&!e.ctrlKey&&!e.metaKey&&!e.shiftKey){e.preventDefault();var t="undefined"!=typeof shaarli&&shaarli.basePath?shaarli.basePath:"";window.location.href=t+"/?searchtags=note#open-note-"+i}}),I(n)||I(r)){var l=t.querySelector(".link-actions");if(!l)return;var u=document.createElement("button");u.className="media-play-action",u.title=e.t("Play media"),u.innerHTML='<i class="mdi mdi-play-circle-outline"></i>';var d=l.querySelector('a[title="'+e.t("Open Link")+'"]');d?l.insertBefore(u,d):l.appendChild(u),u.addEventListener("click",function(e){e.preventDefault(),e.stopPropagation(),O(I(n)?n:r,s&&s.textContent?s.textContent.trim():n)})}}}),function(){var e=localStorage.getItem("mediaPopupState");if(e)try{var t=JSON.parse(e);t.url&&U(t.title,t.playing)}catch(e){}}(),function(){var e=window.ShaarliProI18n||{t:function(e){return e}},t=document.getElementById("daily-calendar-toggle"),a=document.getElementById("daily-calendar-panel"),s=a?a.closest(".daily-calendar-wrap"):null,n=document.getElementById("daily-calendar-month"),r=document.getElementById("daily-calendar-weekdays"),o=document.getElementById("daily-calendar-grid"),i=document.getElementById("daily-calendar-prev"),l=document.getElementById("daily-calendar-next"),u=document.getElementById("daily-calendar-start"),d=document.getElementById("daily-calendar-end"),c=document.getElementById("daily-calendar-cancel"),p=document.getElementById("daily-calendar-apply"),h=document.getElementById("daily-date-display"),m=document.querySelectorAll(".daily-calendar-shortcut");if(t&&a&&o&&r&&n){var g=[e.t("January"),e.t("February"),e.t("March"),e.t("April"),e.t("May"),e.t("June"),e.t("July"),e.t("August"),e.t("September"),e.t("October"),e.t("November"),e.t("December")],y=[e.t("Mon"),e.t("Tue"),e.t("Wed"),e.t("Thu"),e.t("Fri"),e.t("Sat"),e.t("Sun")],v={viewDate:new Date,startDate:null,endDate:null,hoverDate:null};t.addEventListener("click",function(){L(!a.classList.contains("is-open"))}),document.addEventListener("click",function(e){a.classList.contains("is-open")&&s&&!s.contains(e.target)&&e.target!==t&&L(!1)}),a.addEventListener("click",function(e){e.stopPropagation()}),i&&i.addEventListener("click",function(){v.viewDate=new Date(v.viewDate.getFullYear(),v.viewDate.getMonth()-1,1),S()}),l&&l.addEventListener("click",function(){v.viewDate=new Date(v.viewDate.getFullYear(),v.viewDate.getMonth()+1,1),S()}),m.forEach(function(e){e.addEventListener("click",function(){var e,t,a,s=parseInt(this.dataset.range,10);e=s,t=k(new Date),(a=k(new Date)).setDate(t.getDate()-e),v.startDate=a,v.endDate=t,v.viewDate=new Date(t.getFullYear(),t.getMonth(),1),E(),S()})}),c&&c.addEventListener("click",function(){L(!1)}),p&&p.addEventListener("click",function(){if(v.startDate&&v.endDate){L(!1);var e=v.startDate.toISOString().split("T")[0].replace(/-/g,""),t=v.endDate.toISOString().split("T")[0].replace(/-/g,""),a=window.location.pathname+"?start="+e+"&end="+t;window.location.href=a}}),r.innerHTML=y.map(function(e){return"<span>"+e+"</span>"}).join(""),E(),S()}function f(e){return e?new Intl.DateTimeFormat("fr-FR",{day:"numeric",month:"long",year:"numeric"}).format(e):""}function b(e,t){return!(!e||!t)&&(e.getDate()===t.getDate()&&e.getMonth()===t.getMonth()&&e.getFullYear()===t.getFullYear())}function w(e,t,a){return!!(t&&a&&e)&&(e>t&&e<a)}function k(e){return new Date(e.getFullYear(),e.getMonth(),e.getDate())}function E(){u&&(u.textContent=v.startDate?f(v.startDate):"-"),d&&(d.textContent=v.endDate?f(v.endDate):"-"),p&&(p.disabled=!(v.startDate&&v.endDate)),h&&v.startDate&&v.endDate&&(b(v.startDate,v.endDate)?h.textContent=f(v.startDate):h.textContent=f(v.startDate)+" - "+f(v.endDate))}function S(){var e=v.viewDate.getFullYear(),t=v.viewDate.getMonth(),a=function(e,t){return new Date(e,t+1,0).getDate()}(e,t),s=function(e,t){var a=new Date(e,t,1).getDay();return 0===a?6:a-1}(e,t);n.textContent=g[t]+" "+e,o.innerHTML="";for(var r=0;r<s;r++){var i=document.createElement("span");i.className="daily-calendar-empty",o.appendChild(i)}for(var l=1;l<=a;l++){var u=new Date(e,t,l),d=document.createElement("button");d.type="button",d.textContent=l,d.className="daily-calendar-day";var c=b(u,v.startDate),p=b(u,v.endDate),h=v.endDate||v.hoverDate,m=h&&w(u,v.startDate,h);c&&p?d.classList.add("is-range-start","is-range-end","is-range-single"):c?d.classList.add("is-range-start"):p?d.classList.add("is-range-end"):m&&d.classList.add("is-in-range"),function(e,t,a){d.addEventListener("mouseenter",function(){if(v.startDate&&!v.endDate){var s=new Date(t,a,e);v.hoverDate&&v.hoverDate.getTime()===s.getTime()||(v.hoverDate=s,S())}}),d.addEventListener("click",function(s){s.stopPropagation();var n=k(new Date(t,a,e));!v.startDate||v.startDate&&v.endDate?(v.startDate=n,v.endDate=null):v.startDate&&!v.endDate&&(n<v.startDate?(v.endDate=v.startDate,v.startDate=n):v.endDate=n),v.hoverDate=null,E(),S()})}(l,e,t),o.appendChild(d)}}function L(e){a.classList.toggle("is-open",e),a.setAttribute("aria-hidden",String(!e)),s&&s.classList.toggle("is-open",e),t&&t.setAttribute("aria-expanded",String(e))}}(),async function(){try{if(!window.ShaaritThemeConfig)return;const e=await window.ShaaritThemeConfig.load();if(!e)return;const t=e.default,a=e.mode,s=localStorage.getItem("shaarit_theme_id")||"DEFAULT",n=localStorage.getItem("theme")||(window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light");let r=!1;t&&t!==s&&(localStorage.setItem("shaarit_theme_id",t),document.documentElement.setAttribute("data-theme-id",t),r=!0),a&&a!==n&&(localStorage.setItem("theme",a),document.documentElement.setAttribute("data-theme",a),r=!0);-1!==["LINEAR","SPOTIFY","NOTION","DISCORD","DRACULA","ONE_DARK_PRO","TOKYO_NIGHT","NORD","NIGHT_OWL","ANTHRACITE","CYBERPUNK","NAVY_ELEGANCE","EARTHY"].indexOf(t||s)&&"dark"!==localStorage.getItem("theme")&&(localStorage.setItem("theme","dark"),document.documentElement.setAttribute("data-theme","dark"),r=!0),r&&window.dispatchEvent(new Event("themeChanged"))}catch(e){}}()}); |