/** * 밍글 스튜디오 블로그 목록 페이지 * blog/index.json에서 글 목록을 불러와 렌더링 */ (function() { 'use strict'; var grid = document.getElementById('blogGrid'); var filtersWrap = document.getElementById('blogFilters'); var loadingEl = document.getElementById('blogLoading'); if (!grid) return; var lang = document.documentElement.lang || 'ko'; var langPrefix = { ko: '', en: '/en', ja: '/ja', zh: '/zh' }; var prefix = langPrefix[lang] || ''; var readMore = { ko: '자세히 보기', en: 'Read more', ja: '続きを読む', zh: '阅读更多' }; var emptyText = { ko: '아직 작성된 글이 없습니다.', en: 'No posts yet.', ja: 'まだ記事がありません。', zh: '暂无文章。' }; var allText = { ko: '전체', en: 'All', ja: 'すべて', zh: '全部' }; var allPosts = []; var currentFilter = 'all'; function init() { fetch('/devlog/index.json?t=' + Date.now()) .then(function(res) { return res.json(); }) .then(function(posts) { allPosts = posts; if (loadingEl) loadingEl.style.display = 'none'; buildFilters(); renderPosts(); }) .catch(function() { if (loadingEl) loadingEl.style.display = 'none'; grid.innerHTML = '

' + emptyText[lang] + '

'; }); } function buildFilters() { if (!filtersWrap || allPosts.length === 0) return; var categories = {}; allPosts.forEach(function(p) { var cat = (p.categories && p.categories[lang]) || (p.categories && p.categories.ko) || p.category || ''; if (cat) categories[cat] = true; }); var cats = Object.keys(categories).sort(); if (cats.length < 2) { filtersWrap.style.display = 'none'; return; } var html = ''; cats.forEach(function(c) { html += ''; }); filtersWrap.innerHTML = html; filtersWrap.addEventListener('click', function(e) { var btn = e.target.closest('.blog-filter-btn'); if (!btn) return; filtersWrap.querySelectorAll('.blog-filter-btn').forEach(function(b) { b.classList.remove('active'); }); btn.classList.add('active'); currentFilter = btn.getAttribute('data-cat'); renderPosts(); }); } function getCategory(post) { return (post.categories && post.categories[lang]) || (post.categories && post.categories.ko) || post.category || ''; } function renderPosts() { var filtered = currentFilter === 'all' ? allPosts : allPosts.filter(function(p) { return getCategory(p) === currentFilter; }); if (filtered.length === 0) { grid.innerHTML = '

' + emptyText[lang] + '

'; return; } var html = ''; filtered.forEach(function(post) { var title = (post.titles && post.titles[lang]) || (post.titles && post.titles.ko) || post.slug; var desc = (post.descriptions && post.descriptions[lang]) || (post.descriptions && post.descriptions.ko) || ''; var cat = getCategory(post); var thumb = post.thumbnail ? '/blog/posts/' + post.slug + '/' + post.thumbnail : ''; var url = prefix + '/devlog/' + post.slug; var date = formatDate(post.date); html += '
'; html += ''; if (thumb) { html += '' + escapeHtml(title) + ''; } else { html += '
'; } html += '
'; html += '
'; if (cat) html += '' + escapeHtml(cat) + ''; html += '

' + escapeHtml(title) + '

'; html += '

' + escapeHtml(desc) + '

'; html += '
'; }); grid.innerHTML = html; } function formatDate(dateStr) { if (!dateStr) return ''; var d = new Date(dateStr + 'T00:00:00'); if (isNaN(d)) return dateStr; var y = d.getFullYear(), m = d.getMonth() + 1, day = d.getDate(); if (lang === 'ko') return y + '.' + m + '.' + day; if (lang === 'ja' || lang === 'zh') return y + '/' + m + '/' + day; var months = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']; return months[m - 1] + ' ' + day + ', ' + y; } function escapeHtml(str) { var div = document.createElement('div'); div.textContent = str; return div.innerHTML; } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', init); } else { init(); } })();