Spaces:
Running
Running
| <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> |