From e1527d8e3b9c1a0bd85d760b3c2224ca43062555 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 19 May 2026 06:52:43 +0000 Subject: [PATCH] Show category-less posts/pages in all categories Files without a category suffix (e.g. post.md alongside post.en.md) previously only appeared in the default category. They now appear in every category, so untranslated content is always visible. - mdcms.py: nav entries with a bare variant get `uncategorized: true`; search.json keeps `category: null` instead of mapping to default code - index.html: pageShouldDisplay, posts filter, and category dropdown all treat uncategorized/null-category items as universally visible https://claude.ai/code/session_01EzU13EL8D5Ud2ngQUKDj9e --- app/index.html | 7 ++++--- mdcms.py | 15 ++++++++++----- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/app/index.html b/app/index.html index c813133..656fe37 100644 --- a/app/index.html +++ b/app/index.html @@ -1200,6 +1200,7 @@ body { // - Otherwise: hide if (!categoriesUse) return true; if (page.file === defaultPage()) return true; + if (page.uncategorized) return true; const variants = page.variants || []; if (variants.includes(activeCategory)) return true; const cat = categoriesByCode[activeCategory]; @@ -1602,7 +1603,7 @@ function fmtDatetime(dtStr) { // Category filter if (categoriesUse && activeCategory) { - posts = posts.filter(function(e) { return e.category === activeCategory; }); + posts = posts.filter(function(e) { return !e.category || e.category === activeCategory; }); } // Field filter @@ -2245,7 +2246,7 @@ function fmtDatetime(dtStr) { ? navData.find(p => p.file === currentPage) : null; categoriesList.forEach(cat => { - const hasVariant = !page || !page.variants || page.variants.includes(cat.code); + const hasVariant = !page || page.uncategorized || !(page.variants && page.variants.length) || page.variants.includes(cat.code); const hasMsg = !!cat.notfoundmessage; if (hasVariant || hasMsg || cat.code === activeCategory) out.add(cat.code); }); @@ -2272,7 +2273,7 @@ function fmtDatetime(dtStr) { 'data-code': cat.code }); option.appendChild(document.createTextNode(primary)); - const hasVariant = !page || !page.variants || page.variants.includes(cat.code); + const hasVariant = !page || page.uncategorized || !(page.variants && page.variants.length) || page.variants.includes(cat.code); if (!hasVariant && cat.notfoundmessage) { option.appendChild(el('span', { className: 'secondary', textContent: cat.notfoundmessage })); } else if (secondary) { diff --git a/mdcms.py b/mdcms.py index 7050c9e..b50ebb5 100644 --- a/mdcms.py +++ b/mdcms.py @@ -266,10 +266,14 @@ def build_page_nav( } if categories_use: covered = {} + has_uncategorized = False for code, record in variants.items(): - key = code if code is not None else default_code - if key: - covered[key] = record.get("title", "") + if code is None: + has_uncategorized = True + else: + covered[code] = record.get("title", "") + if has_uncategorized: + entry["uncategorized"] = True entry["variants"] = sorted(covered.keys()) entry["titles"] = covered out.append(entry) @@ -313,6 +317,8 @@ def generate_nav_yml(sections: list, pages: list, categories_use: bool = False) if p.get("section-id"): lines.append(f" section-id: {p['section-id']}") lines.append(f" sort: {p.get('sort', 100)}") + if categories_use and p.get("uncategorized"): + lines.append(" uncategorized: true") if categories_use and p.get("variants"): lines.append(f" variants: [{', '.join(p['variants'])}]") if categories_use and p.get("titles"): @@ -344,8 +350,7 @@ def generate_search_json( "body": r.get("body", ""), } if categories_use: - code = r.get("code") - entry["category"] = code if code is not None else default_code + entry["category"] = r.get("code") # None → null = show in all categories out.append(entry) return json.dumps(out, indent=2, ensure_ascii=False)