niki-til

<h1 class="admin-page-title">タクソノミー</h1>

<blockquote class="taxonomy-principle">{{ site.data.taxonomy.design_principle_jp }}</blockquote>

<script id="articles-data" type="application/json">{{ site.data.articles | jsonify }}</script> <script id="taxonomy-data" type="application/json">{{ site.data.taxonomy | jsonify }}</script>

<h2 class="admin-section-title">カテゴリ</h2>

<div class="category-grid"> {% for cat in site.data.taxonomy.categories %} <div class="category-card" style="border-left-color: var({{ cat.color_token }});"> <p class="cat-card-name">{{ cat.name_jp }}</p> <p class="cat-card-id">{{ cat.id }}</p> <p class="cat-card-scope">{{ cat.scope_jp | default: "—" }}</p> <span class="badge badge--cat cat-card-count">{{ cat.article_count }} 件</span> </div> {% endfor %} </div>

<h2 class="admin-section-title">タグ</h2> <p style="font-size:12px;color:var(--color-fg-muted);margin-bottom:1rem;">クリックで該当記事を展開します。</p>

<div class="tag-cloud" id="tag-cloud"></div> <div class="tag-articles-panel" id="tag-panel"> <strong id="tag-panel-title" style="font-size:13px;"></strong> <ul id="tag-panel-list" style="margin-top:0.5rem;"></ul> </div>

<h2 class="admin-section-title">タグ語彙の提案</h2> <p style="font-size:12px;color:var(--color-fg-muted);margin-bottom:1rem;">現在未使用のタグ候補。新記事執筆時に参照してください。</p>

<div id="tag-suggestions-root"></div>

<script defer> (function() { var rawArt = document.getElementById('articles-data'); var rawTax = document.getElementById('taxonomy-data'); if (!rawArt || !rawTax) return;

var artData, taxData; try { artData = JSON.parse(rawArt.textContent); taxData = JSON.parse(rawTax.textContent); } catch(e) { return; }

var tags = taxData.tags || []; var articles = artData.articles || []; var suggestions = taxData.tag_suggestions || []; var baseUrl = '{{ site.baseurl }}';

function escHtml(s) { return String(s||'').replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>').replace(/"/g,'"'); }

// --- Build tag cloud --- var maxCount = tags.reduce(function(m,t){ return Math.max(m, t.count||0); }, 1); var cloud = document.getElementById('tag-cloud'); var panel = document.getElementById('tag-panel'); var panelTitle = document.getElementById('tag-panel-title'); var panelList = document.getElementById('tag-panel-list');

tags.forEach(function(t) { var ratio = (t.count||0) / maxCount; var size = Math.round(10 + ratio * 8); var item = document.createElement('button'); item.className = 'tag-cloud-item'; item.textContent = t.tag + ' (' + (t.count||0) + ')'; item.style.fontSize = size + 'px'; item.setAttribute('aria-label', t.tag + ' のタグが付いた記事を表示'); item.addEventListener('click', function() { var wasActive = item.classList.contains('is-active'); document.querySelectorAll('.tag-cloud-item').forEach(function(el){ el.classList.remove('is-active'); }); if (wasActive) { panel.classList.remove('is-open'); return; } item.classList.add('is-active'); var matched = articles.filter(function(a){ return (a.tags||[]).indexOf(t.tag) !== -1; }); panelTitle.textContent = t.tag + ' — ' + matched.length + ' 件'; panelList.innerHTML = matched.map(function(a){ // a.url already includes baseurl (e.g. /til/mind/cognition-basics/) return '<li><a href="' + escHtml(a.url) + '">' + escHtml(a.title || a.path) + '</a></li>'; }).join(''); panel.classList.add('is-open'); panel.scrollIntoView({ behavior: 'smooth', block: 'nearest' }); }); cloud.appendChild(item); });

// --- Tag suggestions groups --- var groups = [ { label: '学術系', items: suggestions.slice(0, 10) }, { label: '思想系', items: suggestions.slice(10, 15) }, { label: '実務系', items: suggestions.slice(15, 25) }, { label: '社会系', items: suggestions.slice(25, 35) }, { label: '生活系', items: suggestions.slice(35) } ];

var sugRoot = document.getElementById('tag-suggestions-root'); var sugHtml = ''; groups.forEach(function(g) { if (!g.items || !g.items.length) return; sugHtml += '<div style="margin-bottom:1.25rem;">'; sugHtml += '<p style="font-size:11px;font-weight:500;letter-spacing:0.05em;text-transform:uppercase;color:var(--color-fg-muted);margin:0 0 0.5rem;">' + escHtml(g.label) + '</p>'; sugHtml += '<div style="display:flex;flex-wrap:wrap;gap:6px;">'; g.items.forEach(function(tag) { sugHtml += '<span class="tag-cloud-item" style="cursor:default;font-size:12px;">' + escHtml(tag) + '</span>'; }); sugHtml += '</div></div>'; }); sugRoot.innerHTML = sugHtml; })(); </script>