Spaces:
Running
Running
Download index.html from AnnLior/Base_of_lessons: direct link, hf CLI and curl.
- Browser
- Download file 51.1 kB
-
https://huggingface.co/spaces/AnnLior/Base_of_lessons/resolve/main/index.html
- Command line
-
hf download hf://spaces/AnnLior/Base_of_lessons/index.html
-
curl -L -o index.html https://huggingface.co/spaces/AnnLior/Base_of_lessons/resolve/main/index.html
51.1 kB
| <html lang="ru"> | |
| <head> | |
| <meta charset="utf-8"> | |
| <meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover"> | |
| <title>Уроки Т</title> | |
| <style> | |
| :root{--bg:#ffffff;--sand:#F8FAFC;--ink:#696969;--text:#4a3a31;--dim:#8a7a6e;--chip:#696969;--chipt:#fff;--card:#F8FAFC; | |
| --pray:#7fbab4;--word:#2f8a6c;--dream:#b08a4f;--digest:#925727;--mark:#f1dfa6; | |
| padding-top:env(safe-area-inset-top,0px);padding-bottom:env(safe-area-inset-bottom,0px)} | |
| body.dark{--bg:#171412;--sand:#262120;--ink:#f5f4f0;--text:#d8cfc6;--dim:#9a8d82;--chip:#2f2926;--chipt:#f5f4f0;--card:#211c1a;--mark:#8a6a1e} | |
| *{box-sizing:border-box} | |
| body{margin:0;background:var(--bg);color:var(--text);font-family:system-ui,-apple-system,"Segoe UI",Roboto,Arial,sans-serif;padding-left:46px;min-height:100vh;transition:background .25s} | |
| button{font:inherit;cursor:pointer;border:none;color:inherit} | |
| /* ВЕРХНИЙ БЛОК — СПЛОШНАЯ ЗАЛИВКА */ | |
| .hero{position:relative;margin-left:-46px;background:#185a4f;padding:calc(14px + env(safe-area-inset-top,0px)) 18px 22px} | |
| .hero-top{display:flex;gap:8px;flex-wrap:wrap;justify-content:flex-start;margin-bottom:14px} | |
| .hbtn{background:rgba(255,255,255,.14);color:#fff;border-radius:12px;padding:8px 13px;font-size:12.5px;backdrop-filter:blur(6px)} | |
| .hbtn:hover{background:rgba(255,255,255,.24)} | |
| /* календарь на зелёном */ | |
| #cal{margin:0 auto;text-align:center;color:#fff} | |
| .cal-h{display:flex;justify-content:center;align-items:center;gap:10px;font-size:12.5px;margin-bottom:9px;color:#dff0ea} | |
| .cal-h button{background:rgba(255,255,255,.18);color:#fff;border-radius:8px;width:24px;height:24px} | |
| .cal-g{display:grid;grid-template-columns:repeat(7,28px);gap:4px;justify-content:center} | |
| .cd{width:28px;height:28px;border-radius:8px;display:flex;align-items:center;justify-content:center;font-size:11px;background:rgba(255,255,255,.12);color:#cfe6df} | |
| .cd.l{background:#fff;color:#0a322b;font-weight:700;box-shadow:0 2px 8px rgba(0,0,0,.3)} | |
| .cd.cur{outline:2px solid #f1dfa6} | |
| .cd.e{background:none} | |
| .cal-wd{width:28px;height:14px;font-size:9px;text-align:center;color:#a9ccc3} | |
| .wrap{ | |
| max-width: 900px; | |
| margin: 0 auto; | |
| padding: 24px 56px 80px 18px; | |
| } | |
| @media(min-width:761px){ | |
| .wrap{ | |
| max-width: 800px; | |
| margin: 0 auto; | |
| transform: translateX(-23px); | |
| padding-left: 70px; | |
| padding-right: 70px; | |
| box-sizing: border-box; | |
| } | |
| } | |
| .sub{text-align:center;font-size:13px;color:var(--dim);margin-bottom:20px} | |
| .row{display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin-bottom:18px;align-items:center} | |
| .search{flex:0 1 340px;display:flex;background:var(--sand);border-radius:14px;padding:10px 15px} | |
| .search input{flex:1;border:none;outline:none;background:none;font:inherit;font-size:14.5px;color:var(--ink);min-width:0} | |
| .pill{background:var(--chip);color:var(--chipt);border-radius:12px;padding:10px 16px;font-size:13.5px} | |
| .pill.off{background:var(--sand);color:var(--text)} | |
| .cloud{display:flex;flex-wrap:wrap;gap:6px;justify-content:center;margin-bottom:22px} | |
| .tag{background:var(--chip);color:var(--chipt);border-radius:9px;padding:5px 11px;font-size:12px;display:inline-flex;gap:6px;align-items:center} | |
| .tag i{font-style:normal;opacity:.55;font-size:10.5px} | |
| .tag.dim{background:var(--sand);color:var(--dim)} | |
| .tag.act{outline:2px solid var(--ink);outline-offset:1px} | |
| .tag.act.pray{background:var(--pray);color:#141210}.tag.act.word{background:var(--word);color:#fff}.tag.act.dream{background:var(--dream);color:#fff}.tag.act.digest{background:var(--digest);color:#fff} | |
| .col{ | |
| max-width: 700px; | |
| width: 100%; | |
| margin: 0 auto; | |
| display: flex; | |
| flex-direction: column; | |
| gap: 12px; | |
| } | |
| .sum{text-align:center;font-size:12.5px;color:var(--dim)} | |
| .sum b{color:var(--ink)} | |
| .sum button{margin-left:8px;padding:4px 12px;font-size:12px} | |
| .empty{text-align:center;color:var(--dim);padding:40px 16px;line-height:1.7;font-size:14px} | |
| .note{background:var(--card);border-radius:16px;padding:16px 18px 12px;border-left:2px solid var(--c,var(--pray))} | |
| .nh{display:flex;justify-content:space-between;gap:12px;margin-bottom:8px} | |
| .nt{font-weight:600;color:var(--ink);font-size:15.5px} | |
| .nd{font-size:11.5px;color:var(--dim);white-space:nowrap} | |
| .snip{font-size:11px;font-weight:600;color:var(--dim);text-transform:uppercase;margin-bottom:6px} | |
| .nb{font-size:14.5px;line-height:1.6;white-space:pre-wrap;word-break:break-word} | |
| .nb p{margin:0 0 .6em} | |
| .nb mark{background:var(--mark);border-radius:4px;padding:0 3px;color:inherit} | |
| .nt2{display:flex;flex-wrap:wrap;gap:6px;margin-top:12px} | |
| .nt2 .tag{font-size:11.5px;padding:4px 10px} | |
| .acts{display:flex;gap:8px;justify-content:flex-end;margin-top:10px} | |
| .ib{background:var(--chip);color:var(--chipt);border-radius:10px;width:32px;height:32px;font-size:13px} | |
| .tabs{position:fixed;left:0;top:50%;transform:translateY(-50%);z-index:30;display:flex;flex-direction:column;gap:8px} | |
| .tb{writing-mode:vertical-rl;transform:rotate(180deg);width:32px;padding:12px 0;border-radius:12px 0 0 12px;background:var(--sand);color:var(--text);font-size:12px;font-weight:600;letter-spacing:.4px;display:flex;align-items:center;justify-content:center;gap:8px;white-space:nowrap;transition:width .15s} | |
| .tb:hover{width:32px} | |
| .tb.on{background:var(--chip);color:var(--chipt);width:32px} | |
| .tb b{width:9px;height:9px;border-radius:50%;background:var(--c)} | |
| .tb small{opacity:.6;font-weight:400} | |
| .tb small.fnd{opacity:1;font-weight:700;background:rgba(128,128,128,.28);border-radius:8px;padding:5px 1px} | |
| .ov{position:fixed;inset:0;background:rgba(20,18,16,.55);backdrop-filter:blur(3px);display:none;align-items:center;justify-content:center;padding:18px;z-index:60} | |
| .ov.open{display:flex} | |
| .modal{background:var(--bg);border-radius:20px;padding:22px;width:100%;max-width:520px;max-height:90vh;overflow:auto} | |
| .modal h2{margin:0 0 14px;font-size:18px;color:var(--ink)} | |
| .f{margin-bottom:14px}.f label{display:block;font-size:12.5px;color:var(--dim);margin-bottom:6px} | |
| .f input[type=text],.f textarea{width:100%;border:none;outline:none;background:var(--sand);border-radius:12px;padding:11px 13px;font:inherit;font-size:14.5px;color:var(--ink)} | |
| .f textarea{min-height:140px;resize:vertical;line-height:1.55} | |
| .mdb{display:flex;align-items:center;gap:6px;margin-bottom:6px} | |
| .mdb button{width:30px;height:30px;border-radius:9px;background:var(--sand);color:var(--ink);font-size:13px} | |
| .mdb .hint{margin-left:4px} | |
| .sugs{display:flex;flex-wrap:wrap;gap:6px;margin-top:8px} | |
| .sugs .tag{cursor:pointer;font-size:11.5px;padding:3px 10px} | |
| .mact{display:flex;gap:10px;justify-content:flex-end;margin-top:16px} | |
| .lrow{display:flex;justify-content:space-between;align-items:center;gap:8px;padding:7px 2px;font-size:13px;color:var(--ink)} | |
| .lrow .tag{padding:3px 9px} | |
| input[type=file]{display:none} | |
| .ib.on{outline:2px solid var(--digest)} | |
| .dot{width:9px;height:9px;border-radius:50%;display:inline-block;flex:0 0 auto} | |
| .dgb{line-height:var(--dg-line,1.45);font-size:14px} | |
| .dgb p{position:relative;margin:0 0 var(--dg-gap,.5em);padding-left:44px} | |
| .pbm,.ped{position:absolute;top:.1em;width:18px;background:none;font-size:12px;line-height:1;padding:0;opacity:.18;text-align:center} | |
| .pbm{left:0}.ped{left:22px} | |
| .pbm,.ped,.dopen{-webkit-user-select:none;user-select:none} | |
| .dgb p:hover .pbm,.dgb p:hover .ped{opacity:.9} | |
| @media(hover:none){.pbm,.ped{opacity:.5}} | |
| .dgb p.bmp{background:rgba(128,52,24,.1);border-radius:8px}.bmp .pbm{opacity:1} | |
| .dgb p.dq{background:rgba(175, 80, 113,.34);border-radius:8px;padding-top:4px;padding-bottom:4px} | |
| .dgb p.editing{padding-left:0} | |
| .pe{width:100%;font:inherit;font-size:14px;line-height:1.5;color:var(--ink);background:var(--sand);border:none;border-radius:10px;padding:8px 10px;resize:vertical;outline:none;min-height:60px} | |
| .peb{display:flex;gap:8px;align-items:center;margin-top:6px;flex-wrap:wrap}.hint{font-size:11px;color:var(--dim)} | |
| .dopen{border:none;width:17px;height:17px;border-radius:50%;font-size:9px;padding:0;margin:0 3px;vertical-align:middle;color:#fff} | |
| .rcol{position:fixed;top:calc(12px + env(safe-area-inset-top,0px));right:14px;z-index:46;display:flex;flex-direction:column;gap:6px;align-items:flex-end} | |
| .bmw{display:flex;align-items:center;gap:7px;background:rgba(20,18,16,.78);color:#fff;border-radius:12px;padding:6px 10px;font-size:12px;cursor:pointer;backdrop-filter:blur(6px)} | |
| .bmw em{font-style:normal;opacity:.7}.bmx{display:none;background:none;color:#fff;padding:0 2px}.bmw:hover .bmx{display:inline} | |
| .stabs{position:fixed;right:18px;bottom:calc(84px + env(safe-area-inset-bottom,0px));z-index:40;display:flex;flex-direction:column;gap:8px;align-items:flex-end} | |
| .sw{position:relative} | |
| .st{writing-mode:vertical-rl;background:var(--chip);color:var(--chipt);font-size:12px;font-weight:600;width:32px;padding:12px 0;display:flex;align-items:center;justify-content:center;border-radius:12px 0 0 12px} | |
| .hbtn, .bmw{min-height:34px;box-sizing:border-box} | |
| .sp{ | |
| position:absolute;right:100%;bottom:0;transform:translateX(12px); | |
| width:210px;background:var(--bg);border-radius:16px;padding:14px; | |
| opacity:0;pointer-events:none; | |
| transition:opacity .18s, transform .18s; | |
| box-shadow:0 8px 30px rgba(0,0,0,.25); | |
| color:var(--text);z-index:80; | |
| } | |
| .sw:hover .sp{opacity:1;pointer-events:auto;transform:none} | |
| .sp.scr{ | |
| max-height:320px;overflow-y:auto; | |
| scrollbar-width:none;-ms-overflow-style:none; | |
| } | |
| .sp.scr::-webkit-scrollbar{display:none;width:0;height:0} | |
| body.dark .sp{background:var(--card);box-shadow:0 8px 30px rgba(0,0,0,.55)} | |
| .spt{font-size:11px;font-weight:600;color:var(--dim);text-transform:uppercase;margin-bottom:10px;text-align:center} | |
| .tsr{display:flex;align-items:center;gap:6px;padding:4px 2px;font-size:12.5px;color:var(--ink)} | |
| .hit{display:flex;gap:8px;padding:7px;border-radius:12px;cursor:pointer;font-size:12px;color:var(--text)}.hit:hover{background:var(--sand)}.hit small{display:block;color:var(--dim);font-size:10px} | |
| .he{text-align:center;color:var(--dim);font-size:12px;padding:12px} | |
| .vr{margin-bottom:12px;font-size:12px}.vr label{display:flex;justify-content:space-between;margin-bottom:6px}.vr input{width:100%;accent-color:var(--digest)} | |
| .sab{position:fixed;z-index:70;display:none;background:var(--digest);color:#fff;border-radius:12px;padding:9px 14px;font-size:12.5px;font-weight:600} | |
| .stop{position:fixed;right:18px;bottom:calc(22px + env(safe-area-inset-bottom,0px));width:48px;height:48px;border-radius:50%;background:var(--chip);color:var(--chipt);font-size:18px;opacity:0;pointer-events:none;transition:opacity .2s;z-index:45;display:flex;align-items:center;justify-content:center;padding:0}.stop.v{opacity:1;pointer-events:auto} | |
| .stop svg{position:absolute;inset:0;width:100%;height:100%} | |
| .stop .ar{position:relative;z-index:1;font-weight:600;line-height:1} | |
| /* НОВАЯ ОРАНЖЕВАЯ КНОПКА */ | |
| .fab{position:fixed;left:0;top:0;width:46px;height:46px;border-radius:50%;background:#f08a24;color:#fff;font-size:28px;line-height:1;padding:0;display:none;align-items:center;justify-content:center;z-index:55;box-shadow:0 4px 14px rgba(0,0,0,.35)} | |
| .fab.v{display:flex} | |
| @media(max-width:760px){ | |
| html,body{overflow-x:hidden} | |
| body{padding-left:0} | |
| .hero{margin-left:0} | |
| .hbtn{padding:6px 9px;font-size:11.5px} | |
| .rcol{top:calc(14px + env(safe-area-inset-top,0px));bottom:auto;right:8px;flex-direction:row;gap:6px;align-items:flex-start;max-width:calc(100vw - 90px);overflow-x:auto;overflow-y:hidden;pointer-events:none} | |
| .rcol .bmw{pointer-events:auto;flex-shrink:0;white-space:nowrap;padding:0 4px 0 11px;font-size:11.5px;min-height:34px;border-radius:12px;gap:6px} | |
| .rcol .bmw em{display:none} | |
| .rcol .bmw b{display:inline;font-weight:600} | |
| .rcol .bmw .bmx{display:inline;opacity:.85;min-width:32px;height:34px;margin-left:2px;font-size:14px;border-left:1px solid rgba(255,255,255,.22)} | |
| /* контент по центру, поля чуть шире узких ярлыков */ | |
| .wrap{padding:16px 0 80px} | |
| .row,.cloud,.sub{padding:0 30px} | |
| .col{max-width:100%;width:100%;padding:0;margin:0 auto} | |
| .note{margin:0 30px;padding:14px 14px 10px} | |
| /* левые ярлыки: узкие, полупрозрачные, скругления развернуты */ | |
| .tabs{left:0;gap:6px} | |
| .tb,.tb:hover,.tb.on{width:24px} | |
| .tb{padding:10px 0;font-size:11.5px;gap:5px;border-radius:10px 0 0 10px;opacity:.45;transition:opacity .25s} | |
| .tb b{width:7px;height:7px} | |
| .tb small{font-size:10px} | |
| .tb.on{opacity:.8} | |
| .tb:active{opacity:1} | |
| /* правые ярлыки: так же */ | |
| .stabs{right:0;gap:6px;pointer-events:none} | |
| .sw{pointer-events:auto} | |
| .stabs .st{width:24px;padding:10px 0;font-size:11px;border-radius:10px 0 0 10px;opacity:.45;transition:opacity .25s} | |
| .sw:hover .st,.sw:active .st{opacity:1} | |
| } | |
| /* узкое окно на компьютере: отодвигаем правые ярлыки от полосы прокрутки */ | |
| @media(max-width:760px) and (hover:hover){ | |
| .stabs{right:22px} | |
| .row,.cloud,.sub{padding:0 54px 0 32px} | |
| .note{margin:0 54px 0 32px} | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <!-- ВЕРХНИЙ БЛОК: ЗЕЛЁНАЯ ЗАЛИВКА + КАЛЕНДАРЬ --> | |
| <div class="hero" id="hero"> | |
| <div class="hero-top"> | |
| <button class="hbtn" id="exportBtn" title="Скачать все заметки в файл">⬇ Экспорт</button> | |
| <button class="hbtn" id="importBtn" title="Загрузить заметки из файла">⬆ Импорт</button> | |
| <button class="hbtn" id="themeBtn" title="Переключить тему">☾ Тема</button> | |
| <input type="file" id="importFile" accept=".json,application/json"> | |
| </div> | |
| <div id="cal"></div> | |
| </div> | |
| <div class="wrap"> | |
| <div class="row"> | |
| <div class="search"><input type="text" id="search" placeholder="Поиск по заметкам…"></div> | |
| <button class="pill off" id="clearBtn" title="Сбросить поиск и теги">✕</button> | |
| <button class="pill off" id="onlyBtn" title="Если включено, поиск и теги ищут только среди конспектов">Только конспекты</button> | |
| <button class="pill" id="lessonsBtn">Уроки</button> | |
| <button class="pill" id="addBtn" title="Добавить заметку">+ Заметка</button> | |
| </div> | |
| <div class="cloud" id="cloud"></div> | |
| <div class="col" id="content"></div> | |
| </div> | |
| <div class="rcol" id="bmWidget"></div> | |
| <div class="stabs"> | |
| <div class="sw"><div class="st">Теги</div><div class="sp scr"><div class="spt">Все теги · по популярности</div><div id="tagsPanel"></div></div></div> | |
| <div class="sw"><div class="st">База</div><div class="sp"><div class="spt">Статистика</div><div id="statsBox"></div></div></div> | |
| <div class="sw"><div class="st">Вид</div><div class="sp"><div class="spt">Вид конспектов</div> | |
| <div class="vr"><label><span>Строки в абзаце</span><b id="vLineV"></b></label><input type="range" id="vLine" min="0.8" max="1.8" step="0.05"></div> | |
| <div class="vr"><label><span>Между абзацами</span><b id="vGapV"></b></label><input type="range" id="vGap" min="0" max="1.2" step="0.05"></div></div></div> | |
| <div class="sw"><div class="st">История</div><div class="sp"><div class="spt">Последние 5 добавленных</div><div id="historyList"></div></div></div> | |
| </div> | |
| <button class="stop" id="stop" title="Наверх"> | |
| <svg viewBox="0 0 50 50"><circle cx="25" cy="25" r="21" fill="none" stroke="rgba(128,128,128,.35)" stroke-width="3"/><circle id="ringP" cx="25" cy="25" r="21" fill="none" stroke="#e8c97a" stroke-width="3" stroke-linecap="round" transform="rotate(-90 25 25)"/></svg> | |
| <span class="ar">↑</span> | |
| </button> | |
| <div class="tabs" id="tabs"></div> | |
| <div class="ov" id="ov"><div class="modal" id="modal"></div></div> | |
| <script> | |
| (function(){ | |
| ; | |
| var KEY='my_notes_v1',TYPES=['pray','word','dream','digest'],NAMES={pray:'Молитва',word:'Слово',dream:'Сны',digest:'Конспекты'}; | |
| var notes=[],tab='pray',q='',sel=[],only=false,focus=null,cal=null; | |
| var $=function(i){return document.getElementById(i)}; | |
| function ls(k,v){try{if(v===undefined)return localStorage.getItem(k);localStorage.setItem(k,v)}catch(e){return null}} | |
| function esc(s){return String(s).replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')} | |
| function md(h){return h.replace(/\*\*(.+?)\*\*/g,'<strong>$1</strong>').replace(/__(.+?)__/g,'<u>$1</u>').replace(/\*(.+?)\*/g,'<em>$1</em>')} | |
| function hl(t){var s=esc(t);if(!q)return s;var r=esc(q).replace(/[.*+?^${}()|[\]\\]/g,'\\$&');return s.replace(new RegExp('('+r+')','gi'),'<mark>$1</mark>')} | |
| function el(t,c,x){var e=document.createElement(t);if(c)e.className=c;if(x!=null)e.textContent=x;return e} | |
| function uid(){return Date.now().toString(36)+Math.random().toString(36).slice(2,7)} | |
| function fd(ts){var d=new Date(ts),p=function(n){return n<10?'0'+n:n};return p(d.getDate())+'.'+p(d.getMonth()+1)+'.'+d.getFullYear()+' '+p(d.getHours())+':'+p(d.getMinutes())} | |
| function dom(n){for(var i=0;i<4;i++)if((n.types||[]).indexOf(TYPES[i])>-1)return TYPES[i];return 'pray'} | |
| function save(){ls(KEY,JSON.stringify(notes))} | |
| function load(){try{notes=JSON.parse(ls(KEY)||'[]');if(!Array.isArray(notes))notes=[]}catch(e){notes=[]}} | |
| var LRE=/урок\s*№/i; | |
| function lessonTags(n){return (n.tags||[]).filter(function(t){return LRE.test(t)})} | |
| function pdate(t){var m=/^\s*(\d{4})[-.\/](\d{2})[-.\/](\d{2})/.exec(t||'');return m?{y:+m[1],m:+m[2]-1,d:+m[3]}:null} | |
| function partNo(t){var m=/\((\d+)\s*ч\)/i.exec(t||'');return m?+m[1]:0} | |
| function dlg(text,btns){var o=el('div','ov open'),b=el('div','modal');b.style.maxWidth='380px';var p=el('div','',text);p.style.cssText='white-space:pre-line;color:var(--ink);line-height:1.6;margin-bottom:16px';b.appendChild(p);var a=el('div','mact');btns.forEach(function(x){var k=el('button','pill'+(x.p?'':' off'),x.l);k.onclick=function(){document.body.removeChild(o);x.f&&x.f()};a.appendChild(k)});b.appendChild(a);o.appendChild(b);document.body.appendChild(o)} | |
| function alertM(t){dlg(t,[{l:'ОК',p:1}])} | |
| function theme(d){document.body.classList.toggle('dark',d);ls('uroki_theme',d?'dark':'light')} | |
| $('themeBtn').onclick=function(){theme(!document.body.classList.contains('dark'))}; | |
| theme(ls('uroki_theme')==='dark'||(ls('uroki_theme')===null&&window.matchMedia&&matchMedia('(prefers-color-scheme: dark)').matches)); | |
| $('exportBtn').onclick=function(){if(!notes.length){alertM('Нет заметок для экспорта.');return} | |
| var b=new Blob([JSON.stringify({app:'uroki-t',version:1,exportedAt:new Date().toISOString(),count:notes.length,notes:notes,bookmarks:bm},null,2)],{type:'application/json;charset=utf-8'});var a=document.createElement('a');a.href=URL.createObjectURL(b);a.download='uroki-t.json';document.body.appendChild(a);a.click();document.body.removeChild(a);setTimeout(function(){URL.revokeObjectURL(a.href)},1000)}; | |
| $('importBtn').onclick=function(){$('importFile').value='';$('importFile').click()}; | |
| $('importFile').onchange=function(e){var f=e.target.files&&e.target.files[0];if(!f)return;var r=new FileReader();r.onload=function(ev){var p;try{p=JSON.parse(ev.target.result)}catch(x){alertM('Не удалось прочитать файл: это не корректный JSON.');return} | |
| var inc=Array.isArray(p)?p:(p&&p.notes);if(!Array.isArray(inc)||!inc.length){alertM('В файле не найдено ни одной заметки.');return} | |
| var cl=inc.filter(function(n){return n&&typeof n==='object'}).map(function(n){return{id:n.id||uid(),title:String(n.title||''),body:String(n.body||''),tags:Array.isArray(n.tags)?n.tags.map(String):[],types:Array.isArray(n.types)?n.types.filter(function(t){return TYPES.indexOf(t)>-1}):[],read:!!n.read,created:typeof n.created==='number'?n.created:Date.now()}}).filter(function(n){return n.types.length}); | |
| if(!cl.length){alertM('В файле не найдено корректных заметок.');return} | |
| var ib=(p&&!Array.isArray(p)&&p.bookmarks&&typeof p.bookmarks==='object')?p.bookmarks:{}; | |
| dlg('Найдено заметок: '+cl.length+'.\n\nЗаменить все текущие заметки или добавить их к существующим?',[ | |
| {l:'Добавить',f:function(){var ids={};notes.forEach(function(n){ids[n.id]=1});cl.forEach(function(n){if(ids[n.id])n.id=uid();else if(Object.prototype.hasOwnProperty.call(ib,n.id)&&!hasBm(n.id))bm[n.id]=ib[n.id];notes.push(n)});saveBm();save();render();alertM('Импорт завершён. Всего заметок: '+notes.length)}}, | |
| {l:'Заменить',p:1,f:function(){notes=cl;bm={};cl.forEach(function(n){if(Object.prototype.hasOwnProperty.call(ib,n.id))bm[n.id]=ib[n.id]});saveBm();save();render();alertM('Импорт завершён. Всего заметок: '+notes.length)}}])}; | |
| r.onerror=function(){alertM('Ошибка чтения файла.')};r.readAsText(f,'utf-8')}; | |
| function tagStats(){var c={};notes.forEach(function(n){(n.tags||[]).forEach(function(t){var k=t.trim();if(!k||/^\d{4}[-./]\d{2}[-./]\d{2}/.test(k))return;var l=k.toLowerCase();if(!c[l])c[l]={label:k,n:0,t:{pray:0,word:0,dream:0,digest:0}};c[l].n++;(n.types||[]).forEach(function(x){if(c[l].t[x]!==undefined)c[l].t[x]++})})});return c} | |
| function domTag(s){var b='pray';TYPES.forEach(function(t){if(s.t[t]>s.t[b])b=t});return b} | |
| function tagMatch(n){var l=(n.tags||[]).map(function(t){return t.toLowerCase()});return sel.filter(function(s){return l.indexOf(s.toLowerCase())>-1}).length} | |
| function pass(n){if(sel.length&&!tagMatch(n))return false;if(q){var s=((n.title||'')+' '+(n.body||'')+' '+(n.tags||[]).join(' ')).toLowerCase();if(s.indexOf(q.toLowerCase())<0)return false}return true} | |
| function renderCloud(){var c=$('cloud');c.innerHTML='';var st=tagStats();Object.keys(st).sort().forEach(function(k){var s=st[k],cls=domTag(s),a=sel.some(function(t){return t.toLowerCase()===k}); | |
| var b=el('button','tag '+cls+(a?' act':'')+(s.t[tab]>0?'':' dim'));b.appendChild(document.createTextNode(s.label));b.appendChild(el('i','','('+s.n+')')); | |
| b.onclick=function(){focus=null;if(a)sel=sel.filter(function(t){return t.toLowerCase()!==k});else sel.push(s.label);render()};c.appendChild(b)})} | |
| function renderTabs(res){var t=$('tabs');t.innerHTML='';['pray','word','dream'].forEach(function(x){var n=notes.filter(function(m){return(m.types||[]).indexOf(x)>-1}).length; | |
| var b=el('button','tb'+(tab===x?' on':''));b.style.setProperty('--c','var(--'+x+')');b.appendChild(el('b'));b.appendChild(document.createTextNode(NAMES[x]+' '));b.appendChild(el('small','','('+n+')')); | |
| if(res&&!only){var fn=res.filter(function(m){return(m.types||[]).indexOf(x)>-1}).length;if(fn){b.appendChild(el('small','fnd',String(fn)));b.title='Найдено: '+fn}} | |
| b.onclick=function(){tab=x;focus=null;render()};t.appendChild(b)})} | |
| function renderCal(){var box=$('cal');box.innerHTML='';var tag=null,fn=focus&¬es.filter(function(n){return n.id===focus})[0]; | |
| if(fn)tag=lessonTags(fn).filter(pdate)[0];if(!tag)tag=sel.filter(function(t){return LRE.test(t)&&pdate(t)})[0];if(!tag){cal=null;return} | |
| var d0=pdate(tag);if(!cal||cal.tag!==tag)cal={tag:tag,y:d0.y,m:d0.m}; | |
| var days={};notes.forEach(function(n){lessonTags(n).forEach(function(t){var p=pdate(t);if(p&&p.y===cal.y&&p.m===cal.m){(days[p.d]=days[p.d]||[]);if(days[p.d].indexOf(t)<0)days[p.d].push(t)}})}); | |
| var MN=['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь']; | |
| var h=el('div','cal-h'),pr=el('button','','‹'),nx=el('button','','›'); | |
| pr.onclick=function(){cal.m--;if(cal.m<0){cal.m=11;cal.y--}renderCal()};nx.onclick=function(){cal.m++;if(cal.m>11){cal.m=0;cal.y++}renderCal()}; | |
| h.appendChild(pr);h.appendChild(el('span','',MN[cal.m]+' '+cal.y+' · уроков: '+Object.keys(days).length));h.appendChild(nx);box.appendChild(h); | |
| var g=el('div','cal-g'),first=(new Date(cal.y,cal.m,1).getDay()+6)%7,dim=new Date(cal.y,cal.m+1,0).getDate(); | |
| ['Пн','Вт','Ср','Чт','Пт','Сб','Вс'].forEach(function(w){g.appendChild(el('div','cal-wd',w))}); | |
| for(var i=0;i<first;i++)g.appendChild(el('div','cd e')); | |
| for(var d=1;d<=dim;d++){(function(d){var l=days[d],c=el(l?'button':'div','cd'+(l?' l':'')+(l&&d0.y===cal.y&&d0.m===cal.m&&d0.d===d?' cur':''),d); | |
| if(l){c.title=l.join('\n');c.onclick=function(){openLesson(l)}}g.appendChild(c)})(d)} | |
| box.appendChild(g)} | |
| function openLesson(tags){q='';$('search').value='';focus=null;sel=tags.slice();only=notes.some(function(n){return(n.types||[]).indexOf('digest')>-1&&(n.tags||[]).some(function(t){return tags.indexOf(t)>-1})});$('onlyBtn').classList.toggle('off',!only);render();window.scrollTo({top:0,behavior:'smooth'})} | |
| function card(n,ty){var t=ty||dom(n),e=el('div','note');e.setAttribute('data-id',n.id);e.style.setProperty('--c','var(--'+t+')'); | |
| var h=el('div','nh');if((n.title||'').trim()){var tt=el('div','nt');tt.innerHTML=md(hl(n.title));h.appendChild(tt)}else h.appendChild(el('div')); | |
| h.appendChild(el('div','nd',(n.read?'✓ вычитано · ':'')+fd(n.created)));e.appendChild(h); | |
| var b=el('div','nb'); | |
| if(t==='digest'&&focus===n.id){digestBody(b,n)} | |
| else if(t==='digest'&&focus!==n.id){e.appendChild(el('div','snip','Фрагмент конспекта'));var s=n.body||'',i=q?s.toLowerCase().indexOf(q.toLowerCase()):-1,st=Math.max(0,i-160);b.innerHTML=hl((st>0?'…':'')+s.slice(st,st+360)+(s.length>st+360?'…':''))} | |
| else b.innerHTML=md(hl(n.body||'')); | |
| e.appendChild(b); | |
| if((n.tags||[]).length){var tg=el('div','nt2'),sl=sel.map(function(x){return x.toLowerCase()});n.tags.slice().sort(function(a,b){return a.toLowerCase().localeCompare(b.toLowerCase(),'ru')}).forEach(function(x){var s=el('span','tag'+(sl.indexOf(x.toLowerCase())>-1?' act '+t:''));s.innerHTML=hl(x);tg.appendChild(s)});e.appendChild(tg)} | |
| var a=el('div','acts'); | |
| if(t==='digest'){var o=el('button','ib',focus===n.id?'⤡':'⤢');o.title='Открыть / свернуть';o.onclick=function(){focus=focus===n.id?null:n.id;render()};a.appendChild(o);if(focus===n.id){var bk=el('button','ib'+(hasBm(n.id)?' on':''),'🔖');bk.title='Закладка в начало (для места — 🔖 у абзаца)';bk.onclick=function(){if(hasBm(n.id))clearBm(n.id);else setBm(n.id,null);render()};a.appendChild(bk)}} | |
| var ed=el('button','ib','✎');ed.title='Редактировать';ed.onclick=function(){openModal(n)};a.appendChild(ed); | |
| var dl=el('button','ib','🗑');dl.title='Удалить';dl.onclick=function(){dlg('Удалить эту заметку?',[{l:'Отмена'},{l:'Удалить',p:1,f:function(){notes=notes.filter(function(x){return x.id!==n.id});save();render()}}])};a.appendChild(dl); | |
| e.appendChild(a);return e} | |
| var PS=20,cur=[],rl=PS,rfn=null,io=null; | |
| if(window.IntersectionObserver)io=new IntersectionObserver(function(es){es.forEach(function(x){if(x.isIntersecting)more()})},{rootMargin:'300px'}); | |
| function mk(n){return card(n,rfn(n))} | |
| function status(){var s=$('loadStatus');if(!s)return;s.textContent=!cur.length?'':(rl<cur.length?'Показано '+rl+' из '+cur.length+' · прокрутите вниз, чтобы увидеть ещё':'Показаны все заметки: '+cur.length)} | |
| function sentinel(c){var s=el('div');s.id='loadSentinel';s.style.height='1px';c.appendChild(s);if(io)io.observe(s)} | |
| function more(){if(rl>=cur.length)return;var c=$('content'),o=$('loadSentinel');if(o){if(io)io.unobserve(o);o.remove()}var st=$('loadStatus'),p=rl;rl=Math.min(rl+PS,cur.length);cur.slice(p,rl).forEach(function(n){var e=mk(n);if(st)c.insertBefore(e,st);else c.appendChild(e)});status();if(rl<cur.length)sentinel(c)} | |
| function paged(c,list,fn){if(io)io.disconnect();cur=list;rfn=fn;rl=io?Math.min(PS,cur.length):cur.length;cur.slice(0,rl).forEach(function(n){c.appendChild(mk(n))});var s=el('div','sum');s.id='loadStatus';c.appendChild(s);status();if(rl<cur.length)sentinel(c)} | |
| function filtered(){var dm=only?['digest']:['pray','word','dream']; | |
| return notes.filter(function(n){return(n.types||[]).some(function(t){return dm.indexOf(t)>-1})&&pass(n)}).sort(function(a,b){var d=tagMatch(b)-tagMatch(a);if(d)return d;if(sel.some(function(t){return LRE.test(t)})){var p=partNo(lessonTags(a).join(' '))-partNo(lessonTags(b).join(' '));if(p)return p}return b.created-a.created})} | |
| function render(){var filt=!!(q||sel.length),res=filt?filtered():[]; | |
| renderTabs(filt?res:null);renderCloud();renderCal();renderPanels();renderBm(); | |
| var c=$('content');c.innerHTML='';if(io)io.disconnect(); | |
| if(focus){var f=notes.filter(function(n){return n.id===focus})[0];if(f){var sm0=el('div','sum','Показана одна запись.'),bk0=el('button','pill off','Показать список');bk0.onclick=function(){focus=null;render()};sm0.appendChild(bk0);c.appendChild(sm0);c.appendChild(card(f));return}focus=null} | |
| if(filt){ | |
| if(!res.length){c.appendChild(el('div','empty','Ничего не найдено.'));return} | |
| var sm=el('div','sum'); | |
| if(sel.length>=2&&!sel.every(function(t){return LRE.test(t)})){var an=res.filter(function(n){return tagMatch(n)===sel.length}).length;sm.innerHTML='Найдено: '+res.length+' заметок, <b>'+an+' с тегами: '+esc(sel.join(', '))+'.</b>'} | |
| else sm.textContent='Найдено: '+res.length+' заметок'+(only?'':' (по всем вкладкам)'); | |
| c.appendChild(sm);paged(c,res,function(n){return dom(n)});return} | |
| if(tab==='digest'){c.appendChild(el('div','empty','Конспекты длинные, поэтому полным списком не выводятся.\nОткройте урок кнопкой «Уроки» или днём в календаре, либо включите «Только конспекты» и используйте поиск или теги.'));c.firstChild.style.whiteSpace='pre-line';return} | |
| var list=notes.filter(function(n){return(n.types||[]).indexOf(tab)>-1}).sort(function(a,b){return b.created-a.created}); | |
| if(!list.length){c.appendChild(el('div','empty','Пока нет материалов в этом разделе.'));return} | |
| var tt=tab;paged(c,list,function(){return tt})} | |
| function lessonsList(){var m={};notes.forEach(function(n){lessonTags(n).forEach(function(t){var k=t.trim().toLowerCase();if(!m[k]){var x=/урок\s*№\s*(\d+)/i.exec(t);m[k]={l:t.trim(),n:x?+x[1]:1e9,p:partNo(t),c:0,dg:false}}if((n.types||[]).some(function(x){return x!=='digest'}))m[k].c++;if((n.types||[]).indexOf('digest')>-1){m[k].dg=true;if(n.read)m[k].rd=true}})}); | |
| return Object.keys(m).map(function(k){return m[k]}).sort(function(a,b){return a.n-b.n||a.p-b.p})} | |
| $('lessonsBtn').onclick=function(){var M=$('modal');M.innerHTML='';M.appendChild(el('h2','','Уроки по порядку'));var L=lessonsList(); | |
| if(!L.length)M.appendChild(el('div','empty','Пока нет уроков')); | |
| L.forEach(function(x){var r=el('div','lrow');r.appendChild(el('span','',x.l));var rt=el('span');rt.style.cssText='display:flex;gap:8px;align-items:center';var bmid=null;Object.keys(bm).forEach(function(id){var bn=notes.filter(function(n){return n.id===id})[0];if(bn&&(bn.tags||[]).some(function(t){return t.toLowerCase()===x.l.toLowerCase()}))bmid=id});if(bmid){var bb=el('button','tag','🔖');bb.title='Закладка — вернуться в это место';bb.onclick=function(){$('ov').classList.remove('open');goBm(bmid)};rt.appendChild(bb)}var ad=el('button','tag','+');ad.title='Добавить заметку с тегом «'+x.l+'»';ad.onclick=function(){openModal(null,{tags:[x.l],title:x.l,types:['digest']})};rt.appendChild(ad);var cs=el('span','',String(x.c));if(x.rd){cs.title='Конспект вычитан';cs.style.cssText='border:2px solid var(--word);border-radius:11px;padding:0 6px'}rt.appendChild(cs); | |
| var b=el('button','tag',x.dg?'к · открыть':'открыть');b.onclick=function(){$('ov').classList.remove('open');openLesson([x.l])};rt.appendChild(b);r.appendChild(rt);M.appendChild(r)}); | |
| var a=el('div','mact'),c=el('button','pill off','Закрыть');c.onclick=function(){$('ov').classList.remove('open')};a.appendChild(c);M.appendChild(a);$('ov').classList.add('open')}; | |
| var edId=null,mTags=[],mTypes=[]; | |
| function openModal(n,pre){pre=pre||{};edId=n?n.id:null;mTags=n&&n.tags?n.tags.slice():(pre.tags||[]).slice();mTypes=n?(n.types||[]).slice():(pre.types||[]).slice();var M=$('modal');M.innerHTML='';M.appendChild(el('h2','',n?'Редактировать заметку':'Новая заметка')); | |
| function fld(lbl,inp){var f=el('div','f');f.appendChild(el('label','',lbl));f.appendChild(inp);M.appendChild(f);return f} | |
| var ti=el('input');ti.type='text';ti.value=n?n.title||'':(pre.title||'');fld('Заголовок',ti); | |
| var bo=el('textarea');bo.value=n?n.body||'':(pre.body||''); | |
| var mb=el('div','mdb');[['Ж','**','**','Жирный'],['К','*','*','Курсив'],['Ч','__','__','Подчёркнутый']].forEach(function(x){var b=el('button','',x[0]);b.type='button';b.title=x[3];if(x[0]==='Ж')b.style.fontWeight='700';if(x[0]==='К')b.style.fontStyle='italic';if(x[0]==='Ч')b.style.textDecoration='underline'; | |
| b.onclick=function(){var s=bo.selectionStart,e2=bo.selectionEnd,v=bo.value;bo.value=v.slice(0,s)+x[1]+v.slice(s,e2)+x[2]+v.slice(e2);bo.focus();bo.setSelectionRange(s+x[1].length,s+x[1].length+(e2-s))};mb.appendChild(b)}); | |
| mb.appendChild(el('span','hint','выделите текст и нажмите значок')); | |
| var bw=el('div');bw.appendChild(mb);bw.appendChild(bo);fld('Текст',bw); | |
| var tg=el('div'),chips=el('div','nt2'),ni=el('input'),sg=el('div','sugs');ni.type='text';ni.placeholder='Новый тег и Enter…';chips.style.margin='0 0 8px';tg.appendChild(chips);tg.appendChild(ni);tg.appendChild(sg);fld('Теги',tg); | |
| function drawChips(){chips.innerHTML='';mTags.forEach(function(t){var s=el('span','tag',t+' ');var x=el('button','','×');x.type='button';x.style.cssText='background:none;padding:0;font-size:14px';x.onclick=function(){mTags=mTags.filter(function(y){return y!==t});drawChips()};s.appendChild(x);chips.appendChild(s)}); | |
| sg.innerHTML='';var st=tagStats(),low=mTags.map(function(x){return x.toLowerCase()});Object.keys(st).sort().forEach(function(k){if(low.indexOf(k)>-1)return;var b=el('button','tag dim',st[k].label);b.type='button';b.onclick=function(){mTags.push(st[k].label);drawChips()};sg.appendChild(b)})} | |
| drawChips();function addT(){var v=ni.value.trim().replace(/,$/,'');if(v&&mTags.map(function(x){return x.toLowerCase()}).indexOf(v.toLowerCase())<0)mTags.push(v);ni.value='';drawChips()} | |
| ni.onkeydown=function(e){if(e.key==='Enter'||e.key===','){e.preventDefault();addT()}}; | |
| var tp=el('div','nt2');tp.style.margin='0';TYPES.forEach(function(x){var b=el('button','pill'+(mTypes.indexOf(x)>-1?'':' off'),NAMES[x]);b.type='button';var d=el('i','dot');d.style.background='var(--'+x+')';d.style.marginRight='7px';b.insertBefore(d,b.firstChild);b.onclick=function(){var i=mTypes.indexOf(x);if(i>-1)mTypes.splice(i,1);else mTypes.push(x);b.classList.toggle('off',mTypes.indexOf(x)<0)};tp.appendChild(b)});fld('Тип материала (можно несколько)',tp); | |
| var rd=el('input');rd.type='checkbox';rd.checked=n?!!n.read:false;var rl2=el('label','','');rl2.style.cssText='display:flex;gap:8px;align-items:center;color:var(--ink)';rl2.appendChild(rd);rl2.appendChild(document.createTextNode('✓ Вычитано (конспект разобран на цитаты)'));M.appendChild(rl2); | |
| var a=el('div','mact'),c=el('button','pill off','Отмена'),s=el('button','pill','Сохранить');c.onclick=function(){$('ov').classList.remove('open')}; | |
| s.onclick=function(){if(!mTypes.length){alertM('Отметьте хотя бы один тип.');return}var t=ti.value.trim(),b=bo.value.trim();if(!t&&!b){alertM('Введите заголовок или текст.');return}if(ni.value.trim())addT(); | |
| if(edId){var x=notes.filter(function(m){return m.id===edId})[0];if(x){x.title=t;x.body=b;x.tags=mTags.slice();x.types=mTypes.slice();x.read=rd.checked}}else notes.push({id:uid(),title:t,body:b,tags:mTags.slice(),types:mTypes.slice(),read:rd.checked,created:Date.now()}); | |
| save();$('ov').classList.remove('open');render()}; | |
| a.appendChild(c);a.appendChild(s);M.appendChild(a);$('ov').classList.add('open');setTimeout(function(){ti.focus()},30)} | |
| $('addBtn').onclick=function(){openModal(null)}; | |
| $('ov').onclick=function(e){if(e.target===$('ov'))$('ov').classList.remove('open')}; | |
| document.addEventListener('keydown',function(e){if(e.key==='Escape'&&$('ov').classList.contains('open'))$('ov').classList.remove('open')}); | |
| var tm;$('search').oninput=function(){clearTimeout(tm);var v=this.value;tm=setTimeout(function(){q=v.trim();focus=null;render()},160)}; | |
| $('clearBtn').onclick=function(){$('search').value='';q='';sel=[];focus=null;only=false;$('onlyBtn').classList.add('off');render();$('search').focus()}; | |
| $('onlyBtn').onclick=function(){only=!only;this.classList.toggle('off',!only);focus=null;render()}; | |
| var bm={};try{var sv0=JSON.parse(ls('uroki_bookmarks')||'null');if(sv0&&typeof sv0==='object')bm=sv0;else{var ob=JSON.parse(ls('uroki_bookmark')||'null');if(ob&&ob.id)bm[ob.id]=(typeof ob.para==='number')?ob.para:null}}catch(e){bm={}} | |
| function saveBm(){ls('uroki_bookmarks',JSON.stringify(bm))} | |
| function hasBm(id){return Object.prototype.hasOwnProperty.call(bm,id)} | |
| function lkey(n){var t=(n.tags||[]).filter(function(x){return /урок\s*№/i.test(x)})[0];return t?t.trim().toLowerCase():null} | |
| function setBm(id,p){var cur2=notes.filter(function(n){return n.id===id})[0],k=cur2?lkey(cur2):null;if(k)Object.keys(bm).forEach(function(o){if(o===id)return;var x=notes.filter(function(n){return n.id===o})[0];if(x&&lkey(x)===k)delete bm[o]});bm[id]=typeof p==='number'?p:null;saveBm()} | |
| function clearBm(id){delete bm[id];saveBm()} | |
| function shortL(n){var lt=(n.tags||[]).filter(function(t){return /урок\s*№/i.test(t)})[0];if(lt){var m=/урок\s*№\s*(\d+)/i.exec(lt);if(m){var p=/\((\d+)\s*ч\)/i.exec(lt);return 'Урок '+m[1]+(p?' ('+p[1]+' ч)':'')}return lt.trim()}return (n.title||'').trim()||'Конспект'} | |
| function goBm(id){var n=notes.filter(function(x){return x.id===id})[0];if(!n)return;focus=id;q='';sel=[];only=false;$('onlyBtn').classList.add('off');$('search').value='';render();setTimeout(function(){var t=document.querySelector('.bmp')||document.querySelector('.note');if(t)t.scrollIntoView({behavior:'smooth',block:'center'})},60)} | |
| function renderBm(){var s=$('bmWidget');s.innerHTML='';var it=[];Object.keys(bm).forEach(function(id){var n=notes.filter(function(x){return x.id===id})[0];if(n)it.push(n)}); | |
| function lno(n){var m=/урок\s*№\s*(\d+)/i.exec(lkey(n)||'');return m?+m[1]:1e9}it.sort(function(a,b){return lno(a)-lno(b)}); | |
| it.forEach(function(n){var raw=(n.body||'').replace(/\n+/g,'\n\n'),tot=splitP(raw,names(raw)).filter(function(p){return p.s<p.e}).length,p=bm[n.id],box=el('div','bmw'); | |
| box.innerHTML='<span>🔖</span><b>'+esc(shortL(n))+'</b><em>'+(typeof p==='number'?'абзац '+(p+1)+'/'+tot:'начало')+'</em><button type="button" class="bmx" title="Убрать">✕</button>'; | |
| box.onclick=function(e){if(e.target.closest('.bmx')){e.stopPropagation();clearBm(n.id);render();return}goBm(n.id)};s.appendChild(box)})} | |
| function tok(t){var r=[],re=/[\p{L}\p{N}]+/gu,m;while((m=re.exec(t))!==null)r.push({n:m[0].toLowerCase(),s:m.index,e:m.index+m[0].length});return r} | |
| function align(A,B){var m=A.length,n=B.length;if(!m||!n)return null;var W=n+1,sc=new Int16Array((m+1)*W),dr=new Uint8Array((m+1)*W),mx=0,mi=0,mj=0; | |
| for(var i=1;i<=m;i++)for(var j=1;j<=n;j++){var d=sc[(i-1)*W+j-1]+(A[i-1].n===B[j-1].n?2:-1),u=sc[(i-1)*W+j]-1,l=sc[i*W+j-1]-1,b=0,x=0;if(d>b){b=d;x=1}if(u>b){b=u;x=2}if(l>b){b=l;x=3}sc[i*W+j]=b;dr[i*W+j]=x;if(b>mx){mx=b;mi=i;mj=j}} | |
| if(mx<=0)return null;var i2=mi,j2=mj,ix=[],c=0;while(i2>0&&j2>0&&sc[i2*W+j2]>0){var x2=dr[i2*W+j2];if(x2===1){if(A[i2-1].n===B[j2-1].n){c++;ix.push(j2-1)}i2--;j2--}else if(x2===2)i2--;else if(x2===3)j2--;else break} | |
| if(!ix.length)return null;return{a:Math.min.apply(null,ix),b:Math.max.apply(null,ix),r:c/m}} | |
| function derived(dn,raw){var T=tok(raw);if(!T.length)return [];var dt=(dn.tags||[]).map(function(t){return t.toLowerCase()}),res=[]; | |
| notes.forEach(function(c){if(c.id===dn.id)return;if(!(c.types||[]).some(function(t){return t==='pray'||t==='word'||t==='dream'}))return;if(!(c.tags||[]).some(function(t){return dt.indexOf(t.toLowerCase())>-1}))return; | |
| var A=tok(c.body||'');if(A.length<4)return;var r=align(A,T);if(!r||r.r<.55)return;res.push({note:c,type:dom(c),s:T[r.a].s,e:T[r.b].e,r:r.r})}); | |
| res.sort(function(a,b){return b.r-a.r});var ok=[];res.forEach(function(r){if(!ok.some(function(a){return !(r.e<=a.s||r.s>=a.e)}))ok.push(r)});ok.sort(function(a,b){return a.s-b.s});return ok} | |
| function names(t){var r=[],m,re=/^([ \t]*)(Уззия)(\s*:)/gim;while((m=re.exec(t))!==null){var s=m.index+m[1].length;r.push({s:s,e:s+m[2].length+m[3].length,c:'#7e2625'})} | |
| re=/^([ \t]*)(?!Уззия\s*:)([А-ЯЁA-Z][А-Яа-яЁёA-Za-z\-]{1,24}(?:\s[А-ЯЁA-Z][А-Яа-яЁёA-Za-z\-]{1,24})?)(\s*:)/gm;while((m=re.exec(t))!==null){var s2=m.index+m[1].length;r.push({s:s2,e:s2+m[2].length+m[3].length,c:'#2f6a80'})} | |
| r.sort(function(a,b){return a.s-b.s});return r} | |
| function splitP(t,nr){var act={},re=/\n(?:[ \t]*\n)+/g,m;while((m=re.exec(t))!==null)act[m.index]=1;var ns={};nr.forEach(function(r){ns[r.s]=1}); | |
| for(var i=0;i<t.length;i++){if(t.charAt(i)!=='\n'||act[i])continue;var k=i+1;while(k<t.length&&(t.charAt(k)===' '||t.charAt(k)==='\t'))k++;if(ns[k])act[i]=1} | |
| var ps=[],st=0;for(var j=0;j<=t.length;j++){if(j===t.length||act[j]){ps.push({s:st,e:j});var x=j+1;while(x<t.length&&/[\n \t]/.test(t.charAt(x)))x++;st=x;j=x-1}}return ps} | |
| function digestBody(b,n){var raw=(n.body||'').replace(/\n+/g,'\n\n'),nr=names(raw),dr=derived(n,raw),ps=splitP(raw,nr),bi=hasBm(n.id)?bm[n.id]:undefined,out='',k=0,qo=false,ql=0; | |
| ps.forEach(function(p){if(p.s>=p.e)return;var my=k++,pt=raw.slice(p.s,p.e).trim(),qOp=(pt.match(/«/g)||[]).length,qCl=(pt.match(/»/g)||[]).length,sq=/^[*_\s]*[«"„“]/.test(pt),eq=/[»"”“][*_\s]*[.!?…,;:\-–—]*[*_\s]*$/.test(pt),isq=false; | |
| if(qo){isq=true;ql--;if(qCl>qOp||ql<=0)qo=false}else if(sq&&eq)isq=true;else if(sq&&qOp>qCl){isq=true;qo=true;ql=10} | |
| var bd=[p.s,p.e];dr.concat(nr.map(function(r){return{s:r.s,e:r.e}})).forEach(function(r){if(r.s>p.s&&r.s<p.e)bd.push(r.s);if(r.e>p.s&&r.e<p.e)bd.push(r.e)}); | |
| bd=Array.from(new Set(bd)).sort(function(a,b){return a-b});var po=''; | |
| for(var i=0;i<bd.length-1;i++){var f=bd[i],t=bd[i+1];if(f>=t)continue;var h=md(hl(raw.slice(f,t))),nh=nr.filter(function(r){return r.s<=f&&r.e>=t})[0];if(nh)h='<b style="color:'+nh.c+';font-weight:800">'+h+'</b>'; | |
| var dh=dr.filter(function(r){return r.s<=f&&r.e>=t})[0];if(dh){var col='var(--'+dh.type+')',inf=[];if((dh.note.title||'').trim())inf.push('Заметка: '+dh.note.title.trim());inf.push('Теги: '+((dh.note.tags||[]).join(', ')||'—')); | |
| h='<span title="'+esc(inf.join('\n')).replace(/"/g,'"')+'" style="border-bottom:2px solid '+col+'">'+h+'</span>';if(t>=dh.e)h+='<button type="button" class="dopen" data-id="'+dh.note.id+'" style="background:'+col+'" title="Открыть заметку">✎</button>'}po+=h} | |
| out+='<p class="'+(bi===my?'bmp':'')+(isq?' dq':'')+'"><button type="button" class="pbm" data-p="'+my+'" title="Закладка">🔖</button><button type="button" class="ped" data-p="'+my+'" title="Исправить абзац">✎</button>'+po+'</p>'}); | |
| b.innerHTML=out;b.classList.add('dgb'); | |
| b.onclick=function(e){var ed=e.target.closest('.ped');if(ed){e.stopPropagation();paraEdit(n,+ed.getAttribute('data-p'),ed.closest('p'));return}var op=e.target.closest('.dopen');if(op){e.stopPropagation();notePopup(op.getAttribute('data-id'));return}var bt=e.target.closest('.pbm');if(!bt)return;e.stopPropagation();var ix=+bt.getAttribute('data-p');if(hasBm(n.id)&&bm[n.id]===ix)clearBm(n.id);else setBm(n.id,ix);render()}} | |
| function nmap(t){t=t||'';var o=[],m=[];for(var i=0;i<t.length;i++){var c=t.charAt(i);if(c==='\n'){var j=i;while(j<t.length&&t.charAt(j)==='\n')j++;o.push('\n','\n');m.push(i,i);i=j-1}else{o.push(c);m.push(i)}}return{t:o.join(''),m:m}} | |
| function paraEdit(n,idx,pe){if(!pe||pe.classList.contains('editing'))return;var body=n.body||'',nm=nmap(body),pp=splitP(nm.t,names(nm.t)).filter(function(p){return p.s<p.e}),pr=pp[idx];if(!pr)return;var rs=nm.m[pr.s],re=nm.m[pr.e-1]+1;pe.classList.add('editing');pe.innerHTML='';var ta=el('textarea','pe');ta.value=body.slice(rs,re); | |
| function au(){ta.style.height='auto';ta.style.height=(ta.scrollHeight+2)+'px'}function cm(){n.body=body.slice(0,rs)+ta.value+body.slice(re);save();render()} | |
| ta.oninput=au;ta.onkeydown=function(e){if(e.key==='Escape'){e.preventDefault();render()}else if(e.key==='Enter'&&(e.ctrlKey||e.metaKey)){e.preventDefault();cm()}}; | |
| var bar=el('div','peb'),ok=el('button','pill','Сохранить'),cn=el('button','pill off','Отмена');ok.onclick=cm;cn.onclick=function(){render()};bar.appendChild(ok);bar.appendChild(cn);bar.appendChild(el('span','hint','Ctrl+Enter — сохранить, Esc — отмена'));pe.appendChild(ta);pe.appendChild(bar);au();ta.focus()} | |
| function notePopup(id){var n=notes.filter(function(x){return x.id===id})[0];if(!n)return;var o=el('div','ov open'),b=el('div','modal');b.style.maxWidth='480px'; | |
| if((n.title||'').trim()){var h=el('div','nt');h.innerHTML=md(esc(n.title));h.style.marginBottom='10px';b.appendChild(h)} | |
| var p=el('div','nb');p.innerHTML=md(esc(n.body||''));b.appendChild(p); | |
| if((n.tags||[]).length){var tg=el('div','nt2');n.tags.slice().sort(function(a,b){return a.toLowerCase().localeCompare(b.toLowerCase(),'ru')}).forEach(function(t){tg.appendChild(el('span','tag',t))});b.appendChild(tg)} | |
| var a=el('div','mact'),c=el('button','pill off','Закрыть'),e=el('button','pill','✎ Редактировать');c.onclick=function(){document.body.removeChild(o)};e.onclick=function(){document.body.removeChild(o);openModal(n)}; | |
| a.appendChild(c);a.appendChild(e);b.appendChild(a);o.onclick=function(ev){if(ev.target===o)document.body.removeChild(o)};o.appendChild(b);document.body.appendChild(o)} | |
| function renderPanels(){ | |
| var st=tagStats(),arr=Object.keys(st).map(function(k){return st[k]}).sort(function(a,b){return b.n-a.n}),tp=$('tagsPanel');tp.innerHTML=arr.length?'':'<div class="he">Пока нет тегов</div>'; | |
| arr.forEach(function(s){var r=el('div','tsr'),d=el('i','dot'),l=el('span','',s.label);d.style.background='var(--'+domTag(s)+')';l.style.cssText='flex:1;overflow:hidden;text-overflow:ellipsis;white-space:nowrap';r.appendChild(d);r.appendChild(l);r.appendChild(el('b','',s.n));tp.appendChild(r)}); | |
| var ln={},dl={},by={pray:0,word:0,dream:0,digest:0};notes.forEach(function(n){var dg=(n.types||[]).indexOf('digest')>-1;(n.tags||[]).forEach(function(t){var m=/урок\s*№\s*(\d+)/i.exec(t);if(m){ln[m[1]]=1;if(dg)dl[m[1]]=1}});(n.types||[]).forEach(function(t){if(by[t]!==undefined)by[t]++})}); | |
| function row(c,l,v){return '<div class="tsr">'+(c?'<i class="dot" style="background:var(--'+c+')"></i>':'')+'<span style="flex:1">'+l+'</span><b>'+v+'</b></div>'} | |
| $('statsBox').innerHTML=row('','Всего заметок',notes.length)+row('','Уроков (по тегам)',Object.keys(ln).length)+row('pray','Молитва',by.pray)+row('word','Слово',by.word)+row('dream','Сны',by.dream)+row('digest','Конспекты',Object.keys(dl).length+' ('+by.digest+')'); | |
| var hb=$('historyList');hb.innerHTML=notes.length?'':'<div class="he">Пока пусто</div>'; | |
| notes.slice().sort(function(a,b){return b.created-a.created}).slice(0,5).forEach(function(n){var t=dom(n),it=el('div','hit'),pv=(n.body||'').trim();if(pv.length>80)pv=pv.slice(0,80)+'…';if(!pv)pv=n.title||'(без текста)'; | |
| it.innerHTML='<i class="dot" style="background:var(--'+t+');margin-top:4px"></i><span><small>'+fd(n.created)+'</small>'+esc(pv)+'</span>'; | |
| it.onclick=function(){focus=n.id;if(t!=='digest')tab=t;q='';sel=[];$('search').value='';render()};hb.appendChild(it)})} | |
| var vs={line:1.45,gap:.5};try{var sv=JSON.parse(ls('uroki_view')||'null');if(sv&&typeof sv.line==='number'&&typeof sv.gap==='number')vs=sv}catch(e){} | |
| function applyView(){var r=document.documentElement.style;r.setProperty('--dg-line',vs.line);r.setProperty('--dg-gap',vs.gap+'em');$('vLine').value=vs.line;$('vGap').value=vs.gap;$('vLineV').textContent=vs.line.toFixed(2);$('vGapV').textContent=vs.gap.toFixed(2)} | |
| function onView(){vs={line:parseFloat($('vLine').value),gap:parseFloat($('vGap').value)};applyView();ls('uroki_view',JSON.stringify(vs))} | |
| $('vLine').oninput=onView;$('vGap').oninput=onView;applyView(); | |
| /* НОВАЯ ЛОГИКА ВЫДЕЛЕНИЯ С ОРАНЖЕВОЙ КНОПКОЙ */ | |
| var sb=el('button','sab','+ Заметка из выделения'),fab=el('button','fab','+'),pend=null,touch=!!(window.matchMedia&&matchMedia('(hover:none)').matches); | |
| fab.type='button';fab.title='Заметка из выделения';document.body.appendChild(sb);document.body.appendChild(fab); | |
| function hsb(){sb.style.display='none';fab.classList.remove('v');pend=null} | |
| function chk(){var s=getSelection();if(!s||s.isCollapsed||!s.toString().trim()){hsb();return} | |
| var an=s.anchorNode,e2=an&&an.nodeType===1?an:(an?an.parentElement:null),bd=e2?e2.closest('.dgb'):null,ne=bd?bd.closest('.note'):null;if(!ne){hsb();return} | |
| var sn=notes.filter(function(n){return n.id===ne.getAttribute('data-id')})[0];if(!sn){hsb();return} | |
| pend={text:s.toString(),tags:lessonTags(sn)}; | |
| if(touch){ | |
| var rg=s.getRangeAt(0),rs=rg.getClientRects(),lr=rs.length?rs[rs.length-1]:rg.getBoundingClientRect(); | |
| var x=Math.max(8,Math.min(lr.left+lr.width/2-23,innerWidth-54)),y=lr.bottom+38; | |
| if(y>innerHeight-60)y=innerHeight-60; | |
| fab.style.left=x+'px';fab.style.top=y+'px';fab.classList.add('v'); | |
| }else{ | |
| var r=s.getRangeAt(0).getBoundingClientRect();sb.style.left=Math.max(8,Math.min(r.left,innerWidth-200))+'px';sb.style.top=Math.max(8,r.top-44)+'px';sb.style.display='inline-flex'; | |
| }} | |
| function take(){if(!pend)return;var d=pend;hsb();getSelection().removeAllRanges();openModal(null,{tags:d.tags,body:d.text.trim()})} | |
| document.addEventListener('mouseup',function(e){if(e.target===sb)return;setTimeout(chk,0)}); | |
| var st2;document.addEventListener('selectionchange',function(){if(!touch)return;clearTimeout(st2);st2=setTimeout(chk,200)}); | |
| sb.onclick=take;fab.onclick=take; | |
| fab.addEventListener('touchstart',function(e){e.preventDefault();take()},{passive:false}); | |
| var ring=$('ringP'),RC=2*Math.PI*21;ring.style.strokeDasharray=String(RC); | |
| function upr(){var t=window.scrollY||document.documentElement.scrollTop||0,h=document.documentElement.scrollHeight-innerHeight,f=h>0?Math.min(1,Math.max(0,t/h)):0;ring.style.strokeDashoffset=String(RC*(1-f));$('stop').classList.toggle('v',t>220)} | |
| window.addEventListener('scroll',function(){upr();if(touch){if(pend)chk()}else hsb()},{passive:true}); | |
| window.addEventListener('resize',upr); | |
| $('stop').onclick=function(){window.scrollTo({top:0,behavior:'smooth'})}; | |
| load();render();upr(); | |
| })(); | |
| </script> | |
| </body> | |
| </html> |