const CONFIG={owner:"Hamster4Doom",repo:"Krea2",branch:"main"}; const API=`https://huggingface.co/api/models/${CONFIG.owner}/${CONFIG.repo}/tree/${CONFIG.branch}`; const REPO=`https://huggingface.co/${CONFIG.owner}/${CONFIG.repo}`; const IMAGE_EXT=/\.(png|jpe?g|webp|avif)$/i; const MODEL_EXT=/\.safetensors$/i; const state={items:[],filtered:[]}; const $=id=>document.getElementById(id); const els={grid:$("grid"),empty:$("emptyState"),emptyMessage:$("emptyMessage"),notice:$("notice"),search:$("searchInput"),sort:$("sortSelect"),results:$("resultLabel"),updated:$("updatedLabel"),count:$("totalCount"),size:$("totalSize"),downloads:$("downloadCount"),refresh:$("refreshButton"),theme:$("themeButton"),dialog:$("detailDialog"),dialogContent:$("dialogContent"),close:$("closeDialog")}; function prettyName(path){return path.split("/").pop().replace(/\.safetensors$/i,"").replace(/^(krea[-_ ]?2[-_ ]?)/i,"").replace(/[-_ ]?krea[-_ ]?2$/i,"").replace(/[_-]+/g," ").replace(/\b\w/g,c=>c.toUpperCase()).trim()||"Untitled LoRA"} function base(path){return path.replace(/\.[^.]+$/,"").toLowerCase().replace(/(?:[-_](?:preview|cover|thumb|thumbnail|sample(?:[-_]?\d+)?))$/i,"")} function formatBytes(bytes=0){if(!bytes)return "—";const units=["B","KB","MB","GB"];const i=Math.min(Math.floor(Math.log(bytes)/Math.log(1024)),3);return `${(bytes/1024**i).toFixed(i>1?2:0)} ${units[i]}`} function esc(value=""){return String(value).replace(/[&<>'"]/g,c=>({"&":"&","<":"<",">":">","'":"'",'"':"""}[c]))} function fileUrl(path,download=false){return `${REPO}/${download?"resolve":"blob"}/${CONFIG.branch}/${path}${download?"?download=true":""}`} function showSkeleton(){els.grid.innerHTML=Array.from({length:8},()=>'
').join("")} async function loadDownloadCount(){try{const response=await fetch(`https://huggingface.co/api/models/${CONFIG.owner}/${CONFIG.repo}`);if(!response.ok)throw new Error("stats");const data=await response.json();els.downloads.textContent=Number(data.downloads||0).toLocaleString()}catch{els.downloads.textContent="—"}} async function listAllFiles(){let files=[],cursor="";do{const url=new URL(API);url.searchParams.set("recursive","true");url.searchParams.set("expand","true");url.searchParams.set("limit","50");if(cursor)url.searchParams.set("cursor",cursor);const response=await fetch(url,{headers:{Accept:"application/json"}});if(!response.ok)throw new Error(response.status===401||response.status===403?"private":"http");const batch=await response.json();files.push(...batch);const link=response.headers.get("link")||"";const match=link.match(/[?&]cursor=([^&>]+)>;\s*rel="next"/);cursor=match?decodeURIComponent(match[1]):""}while(cursor);return files.filter(f=>f.type==="file")} function buildItems(files){const images=files.filter(f=>IMAGE_EXT.test(f.path));const metadata=files.filter(f=>/\.json$/i.test(f.path));return files.filter(f=>MODEL_EXT.test(f.path)).map(file=>{const stem=base(file.path);const filenameStem=stem.split("/").pop();const image=images.find(img=>base(img.path)===stem&&/[-_]preview\./i.test(img.path))||images.find(img=>base(img.path)===stem)||null;const meta=metadata.find(item=>base(item.path)===stem)||null;return{path:file.path,name:prettyName(file.path),size:file.size||0,modified:file.lastCommit?.date||file.lastModified||null,image:image?.path||null,metaPath:meta?.path||null,samples:[]}})} async function addMetadata(items){await Promise.all(items.map(async item=>{if(!item.metaPath)return;try{const response=await fetch(fileUrl(item.metaPath,true));if(!response.ok)return;const data=await response.json();const folder=item.metaPath.includes("/")?item.metaPath.slice(0,item.metaPath.lastIndexOf("/")+1):"";const resolve=name=>name?(name.includes("/")?name:`${folder}${name}`):null;item.name=data.name||item.name;item.baseModel=data.base_model||"Krea 2";item.triggers=Array.isArray(data.triggers)?data.triggers:[];item.strength=data.recommended_strength||"";item.steps=data.training_steps||"";item.description=data.description||"";item.image=resolve(data.preview)||item.image;item.samples=(Array.isArray(data.samples)?data.samples:[]).map(resolve).filter(Boolean)}catch{}}));return items} function applyFilters(){const query=els.search.value.trim().toLowerCase();state.filtered=state.items.filter(item=>!query||`${item.name} ${item.path} ${(item.triggers||[]).join(" ")}`.toLowerCase().includes(query));const mode=els.sort.value;state.filtered.sort((a,b)=>mode==="largest"?b.size-a.size:mode==="newest"?new Date(b.modified||0)-new Date(a.modified||0):a.name.localeCompare(b.name));render()} function render(){els.grid.innerHTML="";els.results.textContent=`${state.filtered.length} of ${state.items.length} LoRA${state.items.length===1?"":"s"}`;els.empty.classList.toggle("hidden",state.filtered.length>0);if(!state.filtered.length){els.emptyMessage.textContent=state.items.length?"No LoRAs match that search.":"Upload .safetensors files to the Krea2 repository and they will appear here automatically.";return}const fragment=document.createDocumentFragment();state.filtered.forEach((item,index)=>{const article=document.createElement("article");article.className="card";article.tabIndex=0;article.setAttribute("role","button");article.setAttribute("aria-label",`View ${item.name}`);article.innerHTML=`${esc((item.description||"").trim() || "—")}