Stiglo je novo izdanje. Osvježi stranu.
Pravo na uvid u kod. Otvoren protokol omogućava nezavisne operatere i interoperabilnost. Manifest
Izvor
4d7883a894b3
- server.js
- lib/auth.js
- lib/build.js
- lib/cards.js
- lib/db.js
- lib/gradovi.js
- lib/icons.js
- lib/imena.js
- lib/jezik.js
- lib/kartapodaci.js
- lib/lekcije.js
- lib/md.js
- lib/mehanika.js
- lib/mreza.js
- lib/pages.js
- lib/registar.js
- lib/routes.js
- lib/schema2.js
- lib/views.js
- seed/content.mjs
- seed/seed.mjs
- public/app.js
- public/style.css
1 import {esc} from './md.js';
2 import {t, S, jezik, tekstHTML, datum} from './jezik.js';
3 export const SITE='https://www.yugoslavia.forum', NAME='JUGOSLOVENSKI FORUM';
4 export const csrfField=c=>`<input type="hidden" name="csrf" value="${esc(c.csrf)}">`;
5 export const time=ms=>`<time datetime="${new Date(ms).toISOString()}">${datum(ms)}</time>`;
6 export const ago=ms=>datum(ms);
7 export const userLink=u=>`<a class="lat" href="/u/${esc(u.handle)}">${esc(u.deleted?t('Otišli član'):u.display)}</a>`;
8 export const badge=u=>`<span class="badge">${t(['posjetilac','istraživač','član','graditelj','ustanova'][u.nivo??2])}</span>`;
9 export const crumbs=items=>`<nav>${items.map(([h,l])=>`<a href="${h}">${esc(l)}</a>`).join(' · ')}</nav>`;
10 export const pager=(base,n,total)=>total>1?`<nav>${Array.from({length:total},(_,i)=>`<a href="${base}?page=${i+1}">${i+1}</a>`).join(' · ')}</nav>`:'';
11 export function layout(c,{title='',body,noindex=false,spy=false}) {
12 const nav=[['/','Naslovna'],['/#rubrike','Rubrike'],['/karta','Karta mreže'],['/registar','Registar'],['/pijaca','Pijaca'],['/slicice','Sličice'],['/uprava','Uprava'],['/manifest','Manifest']];
13 const foot=[['/pravila','Kućni red'],['/privatnost','Privatnost'],['/operater','Operater'],['/izvor','Izvor'],['/protokol','Protokol'],['/mjerila','Mjerila'],['/en','EN']];
14 const now=new Date(), days=['nedjelja','ponedjeljak','utorak','srijeda','četvrtak','petak','subota'], months=['januar','februar','mart','april','maj','jun','jul','avgust','septembar','oktobar','novembar','decembar'];
15 const auth=c.user?`<a class="lat" href="/u/${esc(c.user.handle)}">@${esc(c.user.handle)}</a> <a href="/podesavanja">${t('Podešavanja')}</a> <a href="/obavjestenja">${t('Obavještenja')} ${c.notif||0}</a> <a href="/dinar">${c.user.dinar} ${t('DINAR · probni bodovi')}</a> <form method="post" action="/odjava">${csrfField(c)}<button>${t('Odjava')}</button></form>`:`<span>${c.cookies?.istrazivac==='1'?t('Istraživač, bez naloga'):''}</span><a href="/prijava">${t('Prijava')}</a> <a href="/upis">${t('Upis')}</a>`;
16 if(body.includes('class="karta ')&&!body.includes('data-tilt'))body='<div><button data-tilt hidden>'+t('nagib')+'</button><p data-tilt-status></p></div>'+body;
17 const html=`<!doctype html><html lang="sh-${c.pismo==='cir'?'Cyrl':'Latn'}"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>${esc(title)} · ${t('naslov')}</title><meta name="description" content="${esc(t('opis'))}"><meta name="yugoslavia-forum-build" content="${c.build}"><meta name="color-scheme" content="light"><link rel="canonical" href="${SITE}${esc(c.path)}">${noindex?'<meta name="robots" content="noindex">':''}<meta property="og:title" content="${t('naslov')}"><meta property="og:description" content="${t('opis')}"><meta property="og:image" content="${SITE}/og.gif"><meta property="og:image:width" content="1200"><meta property="og:image:height" content="630"><meta property="og:image:alt" content="${t('opis')}"><meta name="twitter:card" content="summary_large_image"><meta name="twitter:image" content="${SITE}/twitter.png"><link rel="icon" href="/favicon.svg"><link rel="apple-touch-icon" href="/apple-touch-icon.png"><link rel="manifest" href="/site.webmanifest"><link rel="stylesheet" href="/static/style.css?v=${c.build}"><script src="/static/app.js?v=${c.build}" defer></script></head><body><div class="novine"><a class="skip" href="#main">${t('Pređi na sadržaj')}</a><header><div class="datum mono">${t(days[now.getUTCDay()])}, ${now.getUTCDate()}. ${t(months[now.getUTCMonth()])} ${now.getUTCFullYear()}. · ${t('Godina I · Broj')} ${Math.floor((Date.now()-Date.UTC(2026,9,28))/86400000)+1} · ${t('Cijena: 0 dinara')}</div><a class="masthead" href="/">${t('naslov')}</a><p class="podnaslov">${t('podnaslov')}</p><div class="trobojka"></div><nav class="nav">${nav.map(([h,l])=>`<a href="${h}"${c.path===h?' aria-current="page"':''}>${t(l)}</a>`).join('')}<span translate="no"><a href="/pismo/lat">Latinica</a> | <a href="/pismo/cir">Ћирилица</a></span></nav><div class="userbox">${auth}<form action="/pretraga"><label><span class="sr">${t('Pretraga')}</span><input name="q" maxlength="100" placeholder="${t('Pretraga')}"></label><button>${t('Traži')}</button></form></div><div class="teletekst"><a href="/teletekst"><span class="lat">P100 YU-TELETEKST</span> <time data-clock></time></a> ${c.ticker||''}</div></header><main id="main"${spy?' data-spy':''}><div id="update" hidden>${t('update')} <button data-reload>${t('Osvježi')}</button></div>${c.flash?`<p role="status">${esc(c.flash[1])}</p>`:''}${body}</main><footer><div class="probna-slika" aria-hidden="true"></div><svg viewBox="0 0 80 80" width="50" height="50" aria-hidden="true"><circle cx="40" cy="40" r="35" fill="none" stroke="currentColor"/><path d="M5 40h70M40 5v70M15 20h50M15 60h50" stroke="currentColor"/></svg>${['d1','d2','d3','d4'].map(k=>`<p>${t(k)}</p>`).join('')}<p>${t('Početne razgovore vode izmišljeni probni likovi.')}</p><nav>${foot.map(([h,l])=>`<a href="${h}">${t(l)}</a>`).join(' · ')}</nav><p>${t('Izdavač')} <a href="https://www.tejl.com" rel="noopener noreferrer">TEJL</a> · ${t('jezik')} · <span class="mono">${c.build}</span></p></footer></div><script type="application/json" id="str">${JSON.stringify(Object.fromEntries(Object.keys(S).map(k=>[k,t(k)]))).replaceAll('<','\\u003c')}</script></body></html>`;
18 return tekstHTML(html,c.pismo);
19 }
20 export function errorPage(c,status,msg){return layout(c,{title:t('Greška'),body:`<h1>${status} · ${t(status===404?'Strana nije pronađena':'Greška')}</h1><p>${esc(msg||t('Zahtjev nije uspio.'))}</p><a href="/">${t('Naslovna')}</a>`});}
21