aaa / index.html
OpenLab-NLP's picture
Update index.html
36bf5f0 verified
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HUIUCL Online Archive</title>
<style>
:root {
--bg-color: #f9f7f2;
--card-bg: #ffffff;
--primary-color: #5d5b54;
--accent-color: #d4a373;
--border-color: #e0ddd5;
--variation-bg: #faf9f6;
}
body {
font-family: 'Pretendard', sans-serif;
background-color: var(--bg-color);
color: var(--primary-color);
margin: 0; padding: 0; line-height: 1.6;
}
nav {
position: sticky; top: 0; background: rgba(249, 247, 242, 0.9);
backdrop-filter: blur(10px); padding: 20px; text-align: center;
border-bottom: 1px solid var(--border-color); z-index: 100;
}
nav a { margin: 0 15px; text-decoration: none; color: var(--primary-color); font-weight: 500; font-size: 0.9rem; transition: 0.2s; }
nav a:hover { color: var(--accent-color); }
header { text-align: center; padding: 60px 20px; }
h1 { font-weight: 300; letter-spacing: 8px; color: var(--accent-color); margin: 0; }
.sub-title { font-size: 0.9rem; color: #999; margin-top: 10px; }
.container { max-width: 900px; margin: 0 auto; padding: 0 20px 100px; }
section { display: none; }
section.active { display: block; animation: fadeIn 0.5s; }
@keyframes fadeIn { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.search-container { margin-bottom: 30px; display: flex; gap: 10px; }
input[type="text"] { flex: 1; padding: 12px 24px; border: 1px solid var(--border-color); border-radius: 30px; outline: none; }
.filter-container { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-bottom: 30px; }
button { background: var(--card-bg); border: 1px solid var(--border-color); padding: 6px 16px; cursor: pointer; border-radius: 20px; font-size: 0.85rem; }
button.active { background: var(--accent-color); color: white; border-color: var(--accent-color); }
.table-wrapper { background: var(--card-bg); border-radius: 15px; overflow: hidden; box-shadow: 0 10px 30px rgba(0,0,0,0.05); }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 15px 20px; text-align: left; border-bottom: 1px solid var(--bg-color); }
th { background: #f1eee6; font-size: 0.9rem; color: #777; }
.word-cell { font-weight: bold; color: var(--accent-color); }
.card { background: var(--card-bg); padding: 40px; border-radius: 15px; box-shadow: 0 10px 30px rgba(0,0,0,0.03); margin-bottom: 20px; }
.archive-layout { display: flex; gap: 30px; }
.story-list { width: 250px; flex-shrink: 0; }
.story-item {
padding: 15px; background: var(--card-bg); margin-bottom: 10px;
border-radius: 10px; cursor: pointer; border: 1px solid var(--border-color);
font-size: 0.9rem; transition: 0.2s;
}
.story-item:hover, .story-item.active { border-color: var(--accent-color); color: var(--accent-color); background: #fdfcf9; }
.story-content { flex: 1; background: var(--card-bg); padding: 40px; border-radius: 15px; box-shadow: 0 10px 30px rgba(0,0,0,0.03); min-height: 400px; }
.story-line { margin-bottom: 25px; }
.huiucl-text { font-size: 1.2rem; color: var(--accent-color); font-weight: 600; margin-bottom: 5px; }
.korean-text { font-size: 1rem; color: #777; border-left: 2px solid var(--border-color); padding-left: 15px; }
</style>
</head>
<body>
<nav>
<a href="#" onclick="showSection('dictionary')">DICTIONARY</a>
<a href="#" onclick="showSection('grammar')">GRAMMAR</a>
<a href="#" onclick="showSection('archive')">ARCHIVE</a>
</nav>
<header>
<h1>HUIUCL</h1>
<div class="sub-title">v2.0 Revision - Artificial Language Project</div>
</header>
<div class="container">
<section id="dictionary" class="active">
<div class="search-container">
<input type="text" id="searchInput" placeholder="๋‹จ์–ด ํ˜น์€ ์˜๋ฏธ ๊ฒ€์ƒ‰..." onkeyup="renderTable()">
</div>
<div class="filter-container" id="categoryButtons">
<button onclick="changeCategory('๋ชจ๋‘', this)" class="active">๋ชจ๋‘ ๋ณด๊ธฐ</button>
</div>
<div class="table-wrapper">
<table>
<thead>
<tr><th>๋‹จ์–ด</th><th>์˜๋ฏธ</th><th>๋ถ„๋ฅ˜</th></tr>
</thead>
<tbody id="dictBody"></tbody>
</table>
</div>
</section>
<section id="grammar">
<div class="card">
<h2 style="font-weight: 300;">Basic Grammar</h2>
<p><strong>1. ์–ด์ˆœ:</strong> ์ฃผ์–ด-๋™์‚ฌ(SV) ๋˜๋Š” ์ฃผ์–ด-๋™์‚ฌ-๋ชฉ์ ์–ด(SVO)</p>
<p><strong>2. ๋ช…๋ น๋ฌธ:</strong> ๋™์‚ฌ๋ฅผ ๋งจ ์•ž์— ์œ„์น˜</p>
<p><strong>3. ์‹œ์ œ:</strong> ๊ณผ๊ฑฐํ˜• <code>-m</code>, ๋ฏธ๋ž˜ํ˜• <code>-n</code></p>
<hr style="border: 0; border-top: 1px solid var(--border-color); margin: 20px 0;">
<h3>Phoneme (์Œ์†Œ)</h3>
<p><strong>Vowels:</strong> a, i, u</p>
<p><strong>Consonants:</strong> m, n, s, h, l, c(ใ„ฒ), t(ใ„ธ)</p>
</div>
</section>
<section id="archive">
<div class="archive-layout">
<div class="story-list">
<!-- ARCHIVE ๋‚ด์šฉ์€ ์ถ”ํ›„ ํ™•์žฅ ๊ฐ€๋Šฅ -->
<div class="story-item" style="color:#999; cursor:default;">์•„์นด์ด๋ธŒ ์ค€๋น„ ์ค‘...</div>
</div>
<div class="story-content" id="storyViewer">
<h2 style="font-weight:300; text-align:center; color:#999;">Coming Soon</h2>
<p style="text-align:center; color:#ccc;">Huiucl๋กœ ์“ฐ์ธ ์ด์•ผ๊ธฐ์™€ ์‹œ๊ฐ€ ๊ณง ์—…๋กœ๋“œ๋ฉ๋‹ˆ๋‹ค.</p>
</div>
</div>
</section>
</div>
<script>
let conlangData = {};
let currentCategory = '๋ชจ๋‘';
function showSection(id) {
document.querySelectorAll('section').forEach(s => s.classList.remove('active'));
document.getElementById(id).classList.add('active');
}
function changeCategory(cat, btn) {
document.querySelectorAll('#categoryButtons button').forEach(b => b.classList.remove('active'));
btn.classList.add('active');
currentCategory = cat;
renderTable();
}
// === ํ•ต์‹ฌ: JSON์—์„œ '๋œป'๊ณผ 'ํŒŒ์ƒ' ๋ชจ๋‘ ์ฒ˜๋ฆฌ ===
function traverse(obj, basePath, search) {
if (!obj || typeof obj !== 'object') return;
for (const key in obj) {
if (key === "์„ค์ •") continue;
const item = obj[key];
// 1. ์ผ๋ฐ˜ ํ•ญ๋ชฉ: '๋œป'์ด ์žˆ์œผ๋ฉด ๊ธฐ๋ณธ ๋‹จ์–ด๋กœ ๊ฐ„์ฃผ
if (item && typeof item === 'object' && item.hasOwnProperty('๋œป')) {
const meaning = item.๋œป;
// ๊ฒ€์ƒ‰ ์กฐ๊ฑด ํ™•์ธ
if (key.toLowerCase().includes(search) || meaning.toLowerCase().includes(search)) {
addRow(key, meaning, basePath, false);
}
// 2. 'ํŒŒ์ƒ' ์ฒ˜๋ฆฌ
if (item.hasOwnProperty('ํŒŒ์ƒ') && typeof item.ํŒŒ์ƒ === 'object') {
for (const derivKey in item.ํŒŒ์ƒ) {
const derivMeaning = item.ํŒŒ์ƒ[derivKey];
if (derivKey.toLowerCase().includes(search) || derivMeaning.toLowerCase().includes(search)) {
addRow(derivKey, derivMeaning, basePath, true);
}
}
}
// 3. '๋ณ€ํ˜•' ์ฒ˜๋ฆฌ (์˜ˆ: ์กฐ๋™์‚ฌ)
if (item.hasOwnProperty('๋ณ€ํ˜•') && typeof item.๋ณ€ํ˜• === 'object') {
for (const varKey in item.๋ณ€ํ˜•) {
const varMeaning = item.๋ณ€ํ˜•[varKey];
if (varKey.toLowerCase().includes(search) || varMeaning.toLowerCase().includes(search)) {
addRow(varKey, varMeaning, basePath, true);
}
}
}
}
// 4. ์ค‘์ฒฉ๋œ ์นดํ…Œ๊ณ ๋ฆฌ (์˜ˆ: "์‚ฌํšŒ > ๊ฐ€์กฑ")
else if (typeof item === 'object') {
const newPath = `${basePath} > ${key}`;
traverse(item, newPath, search);
}
// 5. ๋‹จ์ˆœ ๋ฌธ์ž์—ด ํ•ญ๋ชฉ (์˜ˆ: ๋ฌธ๋ฒ• ๊ทœ์น™)
else if (typeof item === 'string') {
if (key.toLowerCase().includes(search) || item.toLowerCase().includes(search)) {
addRow(key, item, basePath, false);
}
}
}
}
function addRow(word, meaning, path, isDerived) {
const row = document.getElementById('dictBody').insertRow();
row.innerHTML = `
<td class="word-cell">${isDerived ? 'โ†ณ ' : ''}${word}</td>
<td>${meaning}</td>
<td style="font-size:0.7rem; color:#ccc;">${path}</td>
`;
}
function renderTable() {
const body = document.getElementById('dictBody');
const search = document.getElementById('searchInput').value.toLowerCase();
body.innerHTML = '';
if (currentCategory === '๋ชจ๋‘') {
const categories = Object.keys(conlangData).filter(k => k !== "์„ค์ •");
categories.forEach(cat => {
traverse(conlangData[cat], cat, search);
});
} else {
if (conlangData[currentCategory]) {
traverse(conlangData[currentCategory], currentCategory, search);
}
}
}
function initButtons() {
const container = document.getElementById('categoryButtons');
Object.keys(conlangData).forEach(key => {
if (key === "์„ค์ •") return;
const btn = document.createElement('button');
btn.innerText = key;
btn.onclick = (e) => changeCategory(key, e.target);
container.appendChild(btn);
});
}
// ์ดˆ๊ธฐํ™”
window.onload = () => {
fetch('Huiucl4.json')
.then(res => {
if (!res.ok) throw new Error("Huiucl4.json ํŒŒ์ผ์„ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.");
return res.json();
})
.then(data => {
conlangData = data;
initButtons();
renderTable();
})
.catch(err => {
console.error(err);
document.getElementById('dictBody').innerHTML = `<tr><td colspan="3" style="text-align:center;color:red;">โš ๏ธ ์˜ค๋ฅ˜: Huiucl4.json์„ ๋กœ๋“œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.</td></tr>`;
});
};
</script>
</body>
</html>