openfree commited on
Commit
fdb1677
·
verified ·
1 Parent(s): 2de9c75

Update index.html

Browse files
Files changed (1) hide show
  1. index.html +182 -50
index.html CHANGED
@@ -48,7 +48,7 @@
48
  }
49
  .main-container {
50
  display: flex;
51
- height: calc(100vh - 100px); /* 상단 영역 제외 전체 높이 */
52
  }
53
  #sidebar {
54
  width: 25%;
@@ -72,7 +72,6 @@
72
  #sidebar li:hover {
73
  background-color: #f0f0f0;
74
  }
75
- /* 우측 임베드 영역: 남은 공간을 모두 차지 */
76
  #embed-container {
77
  flex: 1;
78
  padding: 0;
@@ -92,28 +91,20 @@
92
  <a href="https://discord.gg/openfreeai" target="_blank">Community</a>
93
  </div>
94
 
95
- <!-- 필터 버튼 영역 (카테고리별) -->
96
- <div class="filter-group" id="filter-group">
97
- <!-- JavaScript로 동적으로 버튼 생성 -->
98
- </div>
99
 
100
  <div class="main-container">
101
- <!-- 좌측 사이드바: 선택한 카테고리의 항목 전체 목록 -->
102
- <div id="sidebar">
103
- <!-- JavaScript로 동적으로 생성 -->
104
- </div>
105
- <!-- 우측 임베드 영역 -->
106
  <div id="embed-container">
107
  <iframe id="embed-frame" src=""></iframe>
108
  </div>
109
  </div>
110
 
111
  <script>
112
- // 1. 제공해주신 전체 프로젝트 리스트 (키: 프로젝트 이름, 값: URL)
113
  const projectList = {
114
-
115
-
116
- "fantos/Panorama": "https://huggingface.co/spaces/fantos/Panorama",
117
  "ginigen/Multi-LoRAgen": "https://huggingface.co/spaces/ginigen/Multi-LoRAgen",
118
  "ginigen/canvas-studio": "https://huggingface.co/spaces/ginigen/canvas-studio",
119
  "ginipick/Fashion-Stylegen": "https://huggingface.co/spaces/ginipick/Fashion-Style",
@@ -158,7 +149,6 @@
158
  "ginigen/text3d-R1": "https://huggingface.co/spaces/ginigen/text3d-R1",
159
  "openfree/MagicFace-V3": "https://huggingface.co/spaces/openfree/MagicFace-V3",
160
  "ginipick/DeepSeekR1-LIVE": "https://huggingface.co/spaces/ginipick/DeepSeekR1-LIVE",
161
- "ginipick/like-history": "https://huggingface.co/spaces/ginipick/like-history",
162
  "ginigen/ColPali-multi": "https://huggingface.co/spaces/ginigen/ColPali-multi",
163
  "ginigen/Janus-Pro-7B": "https://huggingface.co/spaces/ginigen/Janus-Pro-7B",
164
  "ginigen/Animagine": "https://huggingface.co/spaces/ginigen/Animagine",
@@ -219,9 +209,7 @@
219
  "fantaxy/Sound-AI-SFX": "https://huggingface.co/spaces/fantaxy/Sound-AI-SFX",
220
  "fantos/flx8lora": "https://huggingface.co/spaces/fantos/flx8lora",
221
  "openfree/trending-board": "https://huggingface.co/spaces/openfree/trending-board",
222
- "aiqtech/Particle-Accelerator-Simulation": "https://huggingface.co/spaces/aiqtech/Particle-Accelerator-Simulation",
223
  "ginipick/Realtime-FLUX": "https://huggingface.co/spaces/ginipick/Realtime-FLUX",
224
- "VIDraft/prime-number": "https://huggingface.co/spaces/VIDraft/prime-number",
225
  "aiqtech/kofaceid": "https://huggingface.co/spaces/aiqtech/kofaceid",
226
  "fantaxy/fastvideogena": "https://huggingface.co/spaces/fantaxy/fastvideogen",
227
  "fantos/cogvidx": "https://huggingface.co/spaces/fantos/cogvidx",
@@ -231,49 +219,195 @@
231
  "aiqtech/FLUX-Ghibli-Studio-LoRA": "https://huggingface.co/spaces/aiqtech/FLUX-Ghibli-Studio-LoRA",
232
  "aiqtech/flxgif": "https://huggingface.co/spaces/aiqtech/flxgif",
233
  "aiqtech/imaginpaint": "https://huggingface.co/spaces/aiqtech/imaginpaint"
 
234
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
235
  };
236
 
237
- // 2. URL 변환 함수: "https://huggingface.co/spaces/{namespace}/{project}" → "https://{namespace}-{project}.hf.space"
238
  function transformUrl(url) {
239
  const prefix = "https://huggingface.co/spaces/";
240
  if (url.startsWith(prefix)) {
241
- const rest = url.substring(prefix.length); // 예: "fantos/VoiceClone"
242
- // 단, key에 있는 "/"는 하이픈(-)으로 변경
243
  return "https://" + rest.replace("/", "-") + ".hf.space";
244
  }
245
  return url;
246
  }
247
 
248
- // 3. 프로젝트 리스트 배열로 변환: 각 항목 { name, url, category }
249
- const projects = Object.keys(projectList).map(key => {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
  return {
251
- name: key, // 예: "ginigen/Multi-LoRAgen"
252
- url: transformUrl(projectList[key]),
253
- category: key.split("/")[0] // 카테고리는 "/" 앞부분, 예: "ginigen"
254
  };
255
  });
256
 
257
- // 4. 카테고리별 그룹화 (예: { ginigen: [...], ginipick: [...], fantos: [...], fantaxy: [...], ... })
258
  const grouped = {};
259
  projects.forEach(project => {
260
- const cat = project.category;
261
- if (!grouped[cat]) {
262
- grouped[cat] = [];
263
- }
264
- grouped[cat].push(project);
 
265
  });
266
 
267
- // 5. 필터 버튼(카테고리) 동적 생성 (기본 "All" 포함)
 
268
  const filterGroupDiv = document.getElementById("filter-group");
269
- // "All" 버튼 생성
 
270
  const allButton = document.createElement("button");
271
  allButton.className = "toggle-button active";
272
  allButton.setAttribute("data-filter", "all");
273
  allButton.textContent = "All";
274
  filterGroupDiv.appendChild(allButton);
275
- // 그룹화된 각 카테고리별 버튼 생성 (정렬하여 표시)
276
- Object.keys(grouped).sort().forEach(category => {
 
277
  const btn = document.createElement("button");
278
  btn.className = "toggle-button";
279
  btn.setAttribute("data-filter", category);
@@ -281,27 +415,26 @@
281
  filterGroupDiv.appendChild(btn);
282
  });
283
 
284
- // 6. 사이드바 업데이트 함수: 선택한 필터의 모든 항목 출력
285
  function updateSidebar(filter) {
286
  const sidebar = document.getElementById("sidebar");
287
- sidebar.innerHTML = ""; // 기존 항목 초기화
288
- let items = [];
289
- if (filter === "all") {
290
- items = projects;
291
- } else {
292
- items = grouped[filter] || [];
293
- }
294
  const ul = document.createElement("ul");
295
  items.forEach(item => {
296
  const li = document.createElement("li");
297
  li.textContent = item.name;
298
- li.addEventListener("click", function() {
299
  document.getElementById("embed-frame").setAttribute("src", item.url);
300
  });
301
  ul.appendChild(li);
302
  });
303
  sidebar.appendChild(ul);
304
- // 기본으로 첫 번째 항목 로드 (있으면)
 
305
  if (items.length > 0) {
306
  document.getElementById("embed-frame").setAttribute("src", items[0].url);
307
  } else {
@@ -309,17 +442,16 @@
309
  }
310
  }
311
 
312
- // 7. 필터 버튼 클릭 이벤트 처리
313
  document.querySelectorAll(".toggle-button").forEach(button => {
314
  button.addEventListener("click", function() {
315
  document.querySelectorAll(".toggle-button").forEach(btn => btn.classList.remove("active"));
316
  this.classList.add("active");
317
- const filter = this.getAttribute("data-filter");
318
- updateSidebar(filter);
319
  });
320
  });
321
 
322
- // 8. 페이지 로드 기본 "all" 필터 적용
323
  updateSidebar("all");
324
  </script>
325
  </body>
 
48
  }
49
  .main-container {
50
  display: flex;
51
+ height: calc(100vh - 100px);
52
  }
53
  #sidebar {
54
  width: 25%;
 
72
  #sidebar li:hover {
73
  background-color: #f0f0f0;
74
  }
 
75
  #embed-container {
76
  flex: 1;
77
  padding: 0;
 
91
  <a href="https://discord.gg/openfreeai" target="_blank">Community</a>
92
  </div>
93
 
94
+ <!-- 필터 버튼 영역 (미리 정의한 10가지 그룹: NEW, BEST, Text, Image Gen, Image Edit, Audio, Video, Productivity, Utility, Vision) -->
95
+ <div class="filter-group" id="filter-group"></div>
 
 
96
 
97
  <div class="main-container">
98
+ <div id="sidebar"></div>
 
 
 
 
99
  <div id="embed-container">
100
  <iframe id="embed-frame" src=""></iframe>
101
  </div>
102
  </div>
103
 
104
  <script>
105
+ // 1. 프로젝트 URL 목록: 프로젝트 이름 -> URL
106
  const projectList = {
107
+ "fantos/Panorama": "https://huggingface.co/spaces/fantos/Panorama",
 
 
108
  "ginigen/Multi-LoRAgen": "https://huggingface.co/spaces/ginigen/Multi-LoRAgen",
109
  "ginigen/canvas-studio": "https://huggingface.co/spaces/ginigen/canvas-studio",
110
  "ginipick/Fashion-Stylegen": "https://huggingface.co/spaces/ginipick/Fashion-Style",
 
149
  "ginigen/text3d-R1": "https://huggingface.co/spaces/ginigen/text3d-R1",
150
  "openfree/MagicFace-V3": "https://huggingface.co/spaces/openfree/MagicFace-V3",
151
  "ginipick/DeepSeekR1-LIVE": "https://huggingface.co/spaces/ginipick/DeepSeekR1-LIVE",
 
152
  "ginigen/ColPali-multi": "https://huggingface.co/spaces/ginigen/ColPali-multi",
153
  "ginigen/Janus-Pro-7B": "https://huggingface.co/spaces/ginigen/Janus-Pro-7B",
154
  "ginigen/Animagine": "https://huggingface.co/spaces/ginigen/Animagine",
 
209
  "fantaxy/Sound-AI-SFX": "https://huggingface.co/spaces/fantaxy/Sound-AI-SFX",
210
  "fantos/flx8lora": "https://huggingface.co/spaces/fantos/flx8lora",
211
  "openfree/trending-board": "https://huggingface.co/spaces/openfree/trending-board",
 
212
  "ginipick/Realtime-FLUX": "https://huggingface.co/spaces/ginipick/Realtime-FLUX",
 
213
  "aiqtech/kofaceid": "https://huggingface.co/spaces/aiqtech/kofaceid",
214
  "fantaxy/fastvideogena": "https://huggingface.co/spaces/fantaxy/fastvideogen",
215
  "fantos/cogvidx": "https://huggingface.co/spaces/fantos/cogvidx",
 
219
  "aiqtech/FLUX-Ghibli-Studio-LoRA": "https://huggingface.co/spaces/aiqtech/FLUX-Ghibli-Studio-LoRA",
220
  "aiqtech/flxgif": "https://huggingface.co/spaces/aiqtech/flxgif",
221
  "aiqtech/imaginpaint": "https://huggingface.co/spaces/aiqtech/imaginpaint"
222
+ };
223
 
224
+ // 2. 별도 객체: 프로젝트의 개별 카테고리 지정 (없으면 기본값 "Image Gen" 사용)
225
+ const customCategories = {
226
+ "fantos/Panorama": "Image Gen",
227
+ "ginigen/Multi-LoRAgen": "Image Gen",
228
+ "ginigen/canvas-studio": "Image Edit",
229
+ "ginipick/Fashion-Stylegen": "Productivity",
230
+ "ginipick/Time-Stream": "Video",
231
+ "ginipick/AccuVision-Diffusion": "Image Gen",
232
+ "fantos/Magic-Drawings": "Image Edit",
233
+ "ginigen/Lumina-Image-PLUS": "Image Gen",
234
+ "fantaxy/fantasy-novel": "Text",
235
+ "fantaxy/eros": "Text",
236
+ "fantaxy/adult-novel": "Text",
237
+ "fantaxy/kungfu-novel": "Text",
238
+ "fantaxy/love-novel": "Text",
239
+ "VIDraft/mouse-webgen": "Productivity",
240
+ "immunobiotech/MUSIC-Jukebox": "Audio",
241
+ "seawolf2357/Flowise-AI": "Productivity",
242
+ "ginigen/Flux-LayerDiffuse": "Image Gen",
243
+ "VIDraft/Portrait-Animation": "Video",
244
+ "VIDraft/Deepseek-Multimodal": "Vision",
245
+ "VIDraft/BLIP2": "Image Gen",
246
+ "ginigen/text3d-r1": "Image Gen",
247
+ "immunobiotech/drug-discovery": "Productivity",
248
+ "openfree/VisionOCR-Chat": "Vision",
249
+ "immunobiotech/MICHELIN": "Productivity",
250
+ "immunobiotech/MICHELIN-korea": "Productivity",
251
+ "immunobiotech/MICHELIN-japan": "Productivity",
252
+ "immunobiotech/MICHELIN-china": "Productivity",
253
+ "VIDraft/money-radar-korea": "Productivity",
254
+ "VIDraft/money-radar": "Productivity",
255
+ "ginipick/PharmAI-Korea": "Productivity",
256
+ "ginigen/MagicFace-V3": "Image Gen",
257
+ "aiqcamp/MindMap": "Image Gen",
258
+ "ginigen/3D-LLAMA": "Productivity",
259
+ "openfree/VectorFlow": "Image Edit",
260
+ "openfree/webtoon-gen": "Image Gen",
261
+ "VIDraft/topic-prediction": "Text",
262
+ "VIDraft/PapersImpact": "Productivity",
263
+ "VIDraft/EveryRAG": "Text",
264
+ "VIDraft/korea-president-DJ": "Image Gen",
265
+ "VIDraft/korea-president-PARK": "Image Gen",
266
+ "openfree/image-to-vector": "Image Edit",
267
+ "ginipick/QR-Canvas-plus": "Productivity",
268
+ "ginigen/text3d-R1": "Image Gen",
269
+ "openfree/MagicFace-V3": "Image Edit",
270
+ "ginipick/DeepSeekR1-LIVE": "Text",
271
+ "ginigen/ColPali-multi": "Text",
272
+ "ginigen/Janus-Pro-7B": "Vision",
273
+ "ginigen/Animagine": "Image Gen",
274
+ "openfree/PDF-RAG": "Productivity",
275
+ "fantos/Ranking-Tracker": "Utility",
276
+ "aiqcamp/Multilingual-Images": "Image Gen",
277
+ "aiqcamp/Gemini2-Flash-Thinking": "Text",
278
+ "openfree/pepe": "Image Gen",
279
+ "openfree/korea-president-yoon": "Image Gen",
280
+ "openfree/CryptoVision": "Utility",
281
+ "fantos/VoiceClone": "Audio",
282
+ "seawolf2357/ocrlatex": "Utility",
283
+ "seawolf2357/img2vid": "Video",
284
+ "seawolf2357/sd-prompt-gen": "Text",
285
+ "openfree/tarotcard": "Utility",
286
+ "aiqcamp/Polaroid": "Image Gen",
287
+ "ginigen/cartoon": "Image Gen",
288
+ "ginigen/Book-Cover": "Image Gen",
289
+ "aiqcamp/fash": "Productivity",
290
+ "gunship999/Korea-Daily-News": "Utility",
291
+ "immunobiotech/ChicagoGallery": "Utility",
292
+ "immunobiotech/MetropolitanMuseum": "Utility",
293
+ "immunobiotech/opensky": "Utility",
294
+ "VIDraft/eum": "Text",
295
+ "aiqtech/FLUX-military": "Image Gen",
296
+ "fantaxy/Rolls-Royce": "Image Gen",
297
+ "seawolf2357/flux-korea-hanbok-lora": "Image Gen",
298
+ "seawolf2357/flux-korea-palace-lora": "Image Gen",
299
+ "aiqcamp/flux-cat-lora": "Image Gen",
300
+ "gunship999/SexyImages": "Image Gen",
301
+ "aiqtech/flux-claude-monet-lora": "Image Gen",
302
+ "seawolf2357/3D-Avatar-Generator": "Utility",
303
+ "fantaxy/playground25": "Image Gen",
304
+ "openfree/ultpixgen": "Image Gen",
305
+ "seawolf2357/REALVISXL-V5": "Image Gen",
306
+ "fantos/flxcontrol": "Image Edit",
307
+ "fantos/textcutobject": "Image Edit",
308
+ "ginipick/FLUX-Prompt-Generator": "Text",
309
+ "fantaxy/flxloraexp": "Image Gen",
310
+ "fantos/flxloraexp": "Image Gen",
311
+ "seawolf2357/flxloraexp": "Image Gen",
312
+ "ginipick/flxloraexp": "Image Gen",
313
+ "aiqcamp/imagemagic": "Image Edit",
314
+ "openfree/ColorRevive": "Image Edit",
315
+ "VIDraft/RAGOndevice": "Productivity",
316
+ "aiqcamp/AudioLlama": "Audio",
317
+ "ginigen/FLUXllama-Multilingual": "Image Gen",
318
+ "ginipick/FitGen": "Image Gen",
319
+ "fantaxy/FLUX-Animations": "Image Gen",
320
+ "fantaxy/Remove-Video-Background": "Image Edit",
321
+ "fantaxy/ofai-flx-logo": "Image Gen",
322
+ "fantaxy/flx-pulid": "Image Gen",
323
+ "fantaxy/flx-upscale": "Image Edit",
324
+ "aiqcamp/Fashion-FLUX": "Image Gen",
325
+ "fantos/x-mas": "Image Gen",
326
+ "openfree/Korean-Leaderboard": "Utility",
327
+ "ginipick/FLUXllama": "Image Gen",
328
+ "fantaxy/Sound-AI-SFX": "Audio",
329
+ "fantos/flx8lora": "Image Gen",
330
+ "openfree/trending-board": "Utility",
331
+ "ginipick/Realtime-FLUX": "Image Gen",
332
+ "aiqtech/kofaceid": "Image Gen",
333
+ "fantaxy/fastvideogena": "Video",
334
+ "fantos/cogvidx": "Video",
335
+ "fantos/flxfashmodel": "Image Gen",
336
+ "fantos/kolcontrl": "Image Edit",
337
+ "aiqtech/cinevid": "Video",
338
+ "aiqtech/FLUX-Ghibli-Studio-LoRA": "Image Gen",
339
+ "aiqtech/flxgif": "Image Gen",
340
+ "aiqtech/imaginpaint": "Image Edit",
341
+
342
+ // 예시로 NEW/BEST 항목 따로 지정 (키 뒤에 _NEW, _BEST 붙임)
343
+ "fantos/Panorama_NEW": "NEW",
344
+ "ginigen/Multi-LoRAgen_BEST": "BEST"
345
  };
346
 
347
+ // 3. URL 변환 함수: "https://huggingface.co/spaces/{namespace}/{project}" → "https://{namespace}-{project}.hf.space"
348
  function transformUrl(url) {
349
  const prefix = "https://huggingface.co/spaces/";
350
  if (url.startsWith(prefix)) {
351
+ const rest = url.substring(prefix.length);
 
352
  return "https://" + rest.replace("/", "-") + ".hf.space";
353
  }
354
  return url;
355
  }
356
 
357
+ // 4. 프로젝트 객체 생성
358
+ // projectList의 모든 key 대해 customCategories에서 카테고리를 읽고, 없으면 기본 "Image Gen"
359
+ const keys = Object.keys(projectList);
360
+ const projects = keys.map(key => {
361
+ const url = projectList[key];
362
+ // primaryCategory가 없으면 "Image Gen"
363
+ let primaryCategory = customCategories[key] || "Image Gen";
364
+
365
+ // 중복 카테고리 가능 (NEW, BEST)
366
+ let categories = [primaryCategory];
367
+ if (key.endsWith("_NEW")) {
368
+ categories.push("NEW");
369
+ }
370
+ if (key.endsWith("_BEST")) {
371
+ categories.push("BEST");
372
+ }
373
+
374
+ // 실제 프로젝트명: "/" 뒤의 부분
375
+ let projectName = key;
376
+ if (!key.endsWith("_NEW") && !key.endsWith("_BEST")) {
377
+ projectName = key.split("/").slice(1).join("/");
378
+ }
379
+
380
  return {
381
+ name: primaryCategory + "/" + projectName,
382
+ url: transformUrl(url),
383
+ categories: categories
384
  };
385
  });
386
 
387
+ // 5. 카테고리별 그룹화
388
  const grouped = {};
389
  projects.forEach(project => {
390
+ project.categories.forEach(cat => {
391
+ if (!grouped[cat]) {
392
+ grouped[cat] = [];
393
+ }
394
+ grouped[cat].push(project);
395
+ });
396
  });
397
 
398
+ // 6. 필터 버튼 생성 (10가지 + All)
399
+ const fixedGroups = ["NEW", "BEST", "Text", "Image Gen", "Image Edit", "Audio", "Video", "Productivity", "Utility", "Vision"];
400
  const filterGroupDiv = document.getElementById("filter-group");
401
+
402
+ // All 버튼
403
  const allButton = document.createElement("button");
404
  allButton.className = "toggle-button active";
405
  allButton.setAttribute("data-filter", "all");
406
  allButton.textContent = "All";
407
  filterGroupDiv.appendChild(allButton);
408
+
409
+ // 나머지 10개 카테고리 버튼
410
+ fixedGroups.forEach(category => {
411
  const btn = document.createElement("button");
412
  btn.className = "toggle-button";
413
  btn.setAttribute("data-filter", category);
 
415
  filterGroupDiv.appendChild(btn);
416
  });
417
 
418
+ // 7. 사이드바 갱신 함수
419
  function updateSidebar(filter) {
420
  const sidebar = document.getElementById("sidebar");
421
+ sidebar.innerHTML = "";
422
+ let items = (filter === "all")
423
+ ? projects
424
+ : projects.filter(project => project.categories.includes(filter));
425
+
 
 
426
  const ul = document.createElement("ul");
427
  items.forEach(item => {
428
  const li = document.createElement("li");
429
  li.textContent = item.name;
430
+ li.addEventListener("click", () => {
431
  document.getElementById("embed-frame").setAttribute("src", item.url);
432
  });
433
  ul.appendChild(li);
434
  });
435
  sidebar.appendChild(ul);
436
+
437
+ // 첫 번째 항목 자동 표시
438
  if (items.length > 0) {
439
  document.getElementById("embed-frame").setAttribute("src", items[0].url);
440
  } else {
 
442
  }
443
  }
444
 
445
+ // 8. 버튼 클릭 필터 적용
446
  document.querySelectorAll(".toggle-button").forEach(button => {
447
  button.addEventListener("click", function() {
448
  document.querySelectorAll(".toggle-button").forEach(btn => btn.classList.remove("active"));
449
  this.classList.add("active");
450
+ updateSidebar(this.getAttribute("data-filter"));
 
451
  });
452
  });
453
 
454
+ // 9. 초기 로딩: All 필터 적용
455
  updateSidebar("all");
456
  </script>
457
  </body>