1(function () { 2 "use strict"; 3 // ÐаÑÑоÑка «ÑÐ²ÐµÐ¶Ð°Ñ Ñводка Ñ Ð¾Ð±Ð»Ð¾Ð¶ÐºÐ¾Ð¹Â» Ð´Ð»Ñ ÐºÐ°ÑÑ (idea СеÑÑги 14.07). ÐаÑÑÑ â 4 // ÑоÑки Ð²Ñ Ð¾Ð´Ð° Ñ Ð²ÑÑоким оÑказом (/karta-bpla ~22%): ÑиÑаÑÐµÐ»Ñ Ð¿Ð¾ÑмоÑÑел и ÑÑÑл. 5 // ÐÑа плаÑка ÑпÑава-ÑвеÑÑ Ñ Ð¿Ð¾ÐºÐ°Ð·ÑÐ²Ð°ÐµÑ ÐÐÐÐÐÐУ поÑледней Ñводки (на каÑÑинке Ñже 6 // гоÑод ÑдаÑа + подпиÑÑ ÑÑо пÑоизоÑло) â клик ÑÐ²Ð¾Ð´Ð¸Ñ ÑиÑаÑÑ /news/<даÑа>, а не 7 // закÑÑваÑÑ Ð²ÐºÐ»Ð°Ð´ÐºÑ. РаÑÑÐ¸Ñ Ð³Ð»ÑÐ±Ð¸Ð½Ñ Ð²Ð¸Ð·Ð¸Ñа (#5 бÑклога ÑоÑÑа). 8 // СамодоÑÑаÑоÑна (инжекÑÐ¸Ñ Ñвой CSS), докаеÑÑÑ Ð² обÑий window.__nudgeDock из 9 // vpn-nudge.js â одна каÑÑоÑка оÑкÑÑÑа за Ñаз, не пеÑекÑÑÐ²Ð°ÐµÑ VPN/подпиÑкÑ. 10 // ponytail: даннÑе ÑÑÐ½ÐµÑ Ð¸Ð· Ñже деплоÑÑегоÑÑ /data/news-archive.json (no-cache), 11 // Ð¾Ð±Ð»Ð¾Ð¶ÐºÑ ÑÑÑÐ¾Ð¸Ñ Ð¿Ð¾ пÑедÑказÑÐµÐ¼Ð¾Ð¼Ñ Ð¸Ð¼ÐµÐ½Ð¸ /assets/cover-<даÑа>.png; пÑи 404 12 // обложки каÑÑоÑка пÑоÑÑо не показÑваеÑÑÑ (не Ð»Ð¾Ð¼Ð°ÐµÑ ÑÑÑаниÑÑ). 13 14 var K = "art_nudge"; // localStorage: 'dock' | 'seen:<date>' 15 var GOAL = "art_read"; 16 // ÐеÑÑиониÑÐ¾Ð²Ð°Ð½Ð½Ð°Ñ Ð·Ð°Ð¼ÐµÐ½Ð° заглÑÑки: ÑÑаÑое Ð¸Ð¼Ñ Ð·Ð°ÐºÑеплено в CDN-кÑÑе. 17 var COVER_OVERRIDES = { "2026-09-11": "/assets/cover-2026-09-11-restored.png" }; 18 var MONTHS = ["ÑнваÑÑ","ÑевÑалÑ","маÑÑа","апÑелÑ","маÑ","иÑнÑ","иÑлÑ", 19 "авгÑÑÑа","ÑенÑÑбÑÑ","окÑÑбÑÑ","ноÑбÑÑ","декабÑÑ"]; 20 21 function seenState() { try { return localStorage.getItem(K) || ""; } catch (e) { return ""; } } 22 function markSeen(date) { try { localStorage.setItem(K, "seen:" + date); } catch (e) {} } 23 function track() { 24 try { if (window.ym) ym(110490245, "reachGoal", GOAL); } catch (e) {} 25 try { if (window.va) va("event", { name: GOAL }); } catch (e) {} 26 } 27 28 function rusDate(iso) { 29 var p = String(iso).split("-"); 30 if (p.length !== 3) return iso; 31 return parseInt(p[2], 10) + " " + MONTHS[parseInt(p[1], 10) - 1]; 32 } 33 34 // Ðаголовок из strikes Ñводки: «<гоÑод> и еÑÑ N ÑдаÑов» (ÑÑÐ¸Ð»Ñ ÑÑÑÐ°Ð½Ð¸Ñ /news). 35 function makeTitle(brief) { 36 var s = (brief && brief.strikes) || []; 37 if (!s.length) return "ÐÑоги днÑ: ÑдаÑÑ Ð¸ деÑиÑÐ¸Ñ Ñоплива"; 38 var city = s[0].city || ""; 39 var extra = s.length - 1; 40 if (!city) return s.length + " ÑдаÑов за ÑÑÑки"; 41 if (extra <= 0) return "УдаÑ: " + city; 42 return city + " и еÑÑ " + extra + " " + plural(extra, "ÑдаÑ", "ÑдаÑа", "ÑдаÑов"); 43 } 44 function plural(n, one, few, many) { 45 var m10 = n % 10, m100 = n % 100; 46 if (m10 === 1 && m100 !== 11) return one; 47 if (m10 >= 2 && m10 <= 4 && (m100 < 10 || m100 >= 20)) return few; 48 return many; 49 } 50 51 // еÑÑÑ Ð»Ð¸ Ñже ÑаÑкÑÑÑÐ°Ñ ÑоÑеднÑÑ Ð¿Ð»Ð°Ñка (vpn/sub)? Ñогда ÑÑÑÑпаем â ÑÑаÑÑÑем ÑзÑÑком 52 function siblingOpen() { 53 return !!document.querySelector(".vpn-nudge:not(.nudge-out), .sub-nudge:not(.nudge-out)"); 54 } 55 56 function build(date, title) { 57 var cover = COVER_OVERRIDES[date] || "/assets/cover-" + date + ".png"; 58 var href = "/news/" + date; 59 var d = document.createElement("div"); 60 d.className = "art-nudge"; 61 d.innerHTML = 62 '<button type="button" class="art-nudge-x" aria-label="ÐакÑÑÑÑ">Ã</button>' + 63 '<a class="art-nudge-lnk" href="' + href + '">' + 64 '<img class="art-nudge-img" src="' + cover + '" alt="Сводка за ' + rusDate(date) + '" loading="lazy">' + 65 '<div class="art-nudge-body">' + 66 '<div class="art-nudge-kick">ð° Ð¡Ð²ÐµÐ¶Ð°Ñ Ñводка · ' + rusDate(date) + '</div>' + 67 '<div class="art-nudge-t">' + title + '</div>' + 68 '<div class="art-nudge-cta">ЧиÑаÑÑ ÑÐ²Ð¾Ð´ÐºÑ â</div>' + 69 '</div>' + 70 '</a>'; 71 d.querySelector(".art-nudge-lnk").addEventListener("click", function () { track(); markSeen(date); }); 72 return d; 73 } 74 75 function wireDock(card, date, startDocked) { 76 var xbtn = card.querySelector(".art-nudge-x"); 77 var dockFn = window.__nudgeDock; 78 if (dockFn) { 79 var d = dockFn(card, { key: K, label: "Ð¡Ð²ÐµÐ¶Ð°Ñ Ñводка", icon: NEWS_ICON, side: "right", 80 pos: "top:60%", accent: "#d23a2e", startDocked: !!startDocked }); 81 xbtn.addEventListener("click", d.collapse); 82 } else { 83 xbtn.addEventListener("click", function () { markSeen(date); card.remove(); }); 84 } 85 } 86 87 // газеÑа-иконка Ð´Ð»Ñ ÑзÑÑка (Ñибling к ÑиÑÑ VPN / ÑамолÑÑÐ¸ÐºÑ Ð¿Ð¾Ð´Ð¿Ð¸Ñки) 88 var NEWS_ICON = 89 '<svg class="guard-face" viewBox="0 0 26 26" aria-hidden="true">' + 90 '<circle class="sh-body" cx="13" cy="13" r="11"/>' + 91 '<g class="face" fill="none" stroke="currentColor" stroke-width="1.4" stroke-linecap="round">' + 92 '<rect x="8" y="8" width="10" height="10" rx="1.2"/>' + 93 '<path d="M10 11h6M10 13.5h6M10 16h4"/>' + 94 '</g>' + 95 '</svg>'; 96 97 var shown = false;
98 function show(date, title, forceDock) { 99 if (shown) return; 100 shown = true; 101 var d = build(date, title); 102 // обложки Ð½ÐµÑ (404) â не показÑваем ÑломаннÑÑ ÐºÐ°ÑÑоÑÐºÑ 103 d.querySelector(".art-nudge-img").addEventListener("error", function () { 104 d.remove(); 105 }); 106 var dock = forceDock || siblingOpen(); 107 document.body.appendChild(d); 108 if (dock) { 109 d.classList.add("in"); d.classList.add("nudge-out"); // ÑÑÐ°Ð·Ñ ÑзÑÑком 110 wireDock(d, date, true); 111 } else { 112 wireDock(d, date, false); 113 void d.offsetWidth; // ÑоÑÑ-reflow â пеÑÐµÑ Ð¾Ð´ игÑÐ°ÐµÑ Ð½Ð°Ð´Ñжно даже в Ñоновой вкладке 114 d.classList.add("in"); 115 } 116 } 117 118 function css() { 119 var s = document.createElement("style"); 120 s.textContent = 121 ".art-nudge{position:fixed;right:0;top:78px;z-index:1250;width:290px;max-width:calc(100vw - 28px);" + 122 "background:var(--surface,#fff);border:1px solid var(--line,#e4e4e7);border-right:none;" + 123 "border-radius:14px 0 0 14px;box-shadow:0 8px 30px rgba(0,0,0,.22);overflow:hidden;" + 124 "transform:translateX(115%);transition:transform .45s cubic-bezier(.22,1,.36,1)}" + 125 ".art-nudge.in{transform:translateX(0)}" + 126 ".art-nudge.nudge-out{transform:translateX(115%)}" + 127 ".art-nudge-x{position:absolute;top:6px;right:9px;z-index:2;background:rgba(0,0,0,.45);border:none;" + 128 "color:#fff;font-size:16px;line-height:1;cursor:pointer;padding:1px 7px;border-radius:20px}" + 129 ".art-nudge-x:hover{background:rgba(0,0,0,.7)}" + 130 ".art-nudge-lnk{display:block;text-decoration:none;color:inherit}" + 131 ".art-nudge-img{display:block;width:100%;height:150px;object-fit:cover;background:var(--surface2,#f0f0f0)}" + 132 ".art-nudge-body{padding:11px 14px 13px}" + 133 ".art-nudge-kick{color:var(--red,#d23a2e);font-size:10.5px;font-weight:800;letter-spacing:.3px;text-transform:uppercase}" + 134 ".art-nudge-t{color:var(--ink,#111);font-size:14px;font-weight:800;line-height:1.28;margin:5px 0 8px;font-family:var(--disp,inherit)}" + 135 ".art-nudge-cta{color:var(--teal,#12a594);font-size:12.5px;font-weight:800}" + 136 ".art-nudge-lnk:hover .art-nudge-cta{text-decoration:underline}" + 137 "@media(max-width:560px){.art-nudge{right:10px;left:10px;top:10px;width:auto;border-radius:14px;border-right:1px solid var(--line,#e4e4e7);" + 138 "transform:translateY(-140%)}.art-nudge.in{transform:translateY(0)}.art-nudge.nudge-out{transform:translateY(-140%)}" + 139 ".art-nudge-img{height:130px}}"; 140 document.head.appendChild(s); 141 } 142 143 function init() { 144 css(); 145 fetch("/data/news-archive.json", { cache: "no-store" }) 146 .then(function (r) { return r.ok ? r.json() : null; }) 147 .then(function (j) { 148 if (!j || !j.briefs) return; 149 var dates = Object.keys(j.briefs).sort().reverse(); 150 resolveCover(dates, j.briefs, 0); 151 }) 152 .catch(function () {}); 153 } 154 155 // СвежайÑÐ°Ñ Ð´Ð°Ñа, Ñ ÐºÐ¾ÑоÑой Ð ÐÐÐЬÐРеÑÑÑ Ð¾Ð±Ð»Ð¾Ð¶ÐºÐ°: Ñводка ÐеÑмеÑа Ð¼Ð¾Ð¶ÐµÑ Ð¾Ð¿ÐµÑежаÑÑ 156 // генеÑаÑÐ¸Ñ Ð¾Ð±Ð»Ð¾Ð¶ÐºÐ¸ (build-covers). ÐÑе-probe деÑаÑ-каÑÑинкой â показÑваем каÑÑоÑÐºÑ 157 // ÑолÑко когда обложка загÑÑзилаÑÑ (знаÑÐ¸Ñ Ð¸ в DOM оÑÑиÑÑеÑÑÑ Ð¼Ð³Ð½Ð¾Ð²ÐµÐ½Ð½Ð¾, из кеÑа). 158 // ponytail: окно оÑÑÑÐ°Ð²Ð°Ð½Ð¸Ñ Ð¾Ð±Ð»Ð¾Ð¶ÐºÐ¸ â¤1 ÑÑÑки â 3 попÑÑки Ñ Ð·Ð°Ð¿Ð°Ñом. 159 function resolveCover(dates, briefs, i) { 160 if (i >= dates.length || i >= 3) return; // обложек Ð½ÐµÑ Ð² ÑазÑмном окне â каÑÑоÑÐºÑ Ð½Ðµ показÑваем 161 var date = dates[i]; 162 var probe = new Image(); 163 probe.onload = function () { dispatch(date, makeTitle(briefs[date])); }; 164 probe.onerror = function () { resolveCover(dates, briefs, i + 1); }; 165 probe.src = COVER_OVERRIDES[date] || "/assets/cover-" + date + ".png"; 166 } 167 168 function dispatch(date, title) { 169 var st = seenState(); 170 var docked = (st === "seen:" + date || st === "dock"); // видел ÑÑÑ Ð´Ð°ÑÑ / Ñанее ÑвеÑнÑл â ÑзÑÑком 171 arm(date, title, docked); 172 } 173 174 // показаÑÑ Ð¿Ð¾Ñле пеÑвого взаимодейÑÑÐ²Ð¸Ñ (пан/ÑкÑолл/клик) или ÑеÑез 10Ñ â 175 // ловим «вовлеÑÑнного, но ÑобÑавÑегоÑÑ ÑйÑи» ÑиÑаÑелÑ, не долбим ÑÑÐ°Ð·Ñ 176 function arm(date, title, forceDock) { 177 if (forceDock) { show(date, title, true); return; } 178 var fired = false, t; 179 function trigger() { 180 if (fired) return; 181 fired = true; 182 document.removeEventListener("pointerdown", trigger, true); 183 document.removeEventListener("wheel", trigger, { passive: true }); 184 window.removeEventListener("scroll", trigger, { passive: true }); 185 clearTimeout(t); 186 show(date, title, false); 187 } 188 document.addEventListener("pointerdown", trigger, true); 189 document.addEventListener("wheel", trigger, { passive: true }); 190 window.addEventListener("scroll", trigger, { passive: true }); 191 t = setTimeout(trigger, 10000); 192 } 193 194 if (document.readyState !== "loading") init(); 195 else document.addEventListener("DOMContentLoaded", init); 196})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.