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
This commit is contained in:
Claude 2026-05-19 06:52:43 +00:00
parent aa9ea34683
commit e1527d8e3b
No known key found for this signature in database
2 changed files with 14 additions and 8 deletions

View file

@ -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) {

View file

@ -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)