From ef4197fa83e8b3b1157c2d78ffe82adc8ada5701 Mon Sep 17 00:00:00 2001 From: Claude Date: Thu, 21 May 2026 15:02:31 +0000 Subject: [PATCH] feat: add visibilityifnocontent per-category config key When set to visible, the category always appears in the selector even when no variant exists for the current page. Navigating to such a page shows pagenotfoundmessage with no fallback to default-category content. Default behaviour (hidden) is unchanged. Updates pageShouldDisplay and visibleCategoryCodesForCurrentPage to honour the new key alongside the existing notfoundmessage logic. Docs updated with key description, summary table, and full example. --- app/index.html | 12 +++++++----- docs/reference-config.md | 10 +++++++++- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/app/index.html b/app/index.html index d811dc9..bb19f87 100644 --- a/app/index.html +++ b/app/index.html @@ -952,7 +952,7 @@ body { // Category state (phase 3) let categoriesUse = false; - let categoriesList = []; // [{code, name, direction, message, notfoundmessage, pagenotfoundmessage, font, ...}] + let categoriesList = []; // [{code, name, direction, message, notfoundmessage, pagenotfoundmessage, visibilityifnocontent, font, ...}] let categoriesByCode = {}; // code → category object let defaultCategoryCode = null; let activeCategory = null; // current code @@ -1202,13 +1202,14 @@ body { // - Home page: always show (per config.homepage or default 'pages/home.md') // - Variant exists for active category: show // - Active category has notfoundmessage: show (renderer falls back to default language) + // - Active category has visibilityifnocontent: visible: show (renderer shows pagenotfoundmessage) // - Otherwise: hide if (!categoriesUse) return true; if (page.file === defaultPage()) return true; const variants = page.variants || []; if (variants.includes(activeCategory)) return true; const cat = categoriesByCode[activeCategory]; - return !!(cat && cat.notfoundmessage); + return !!(cat && (cat.notfoundmessage || cat.visibilityifnocontent === 'visible')); } // ─── Theme ──────────────────────────────────────────────── @@ -2243,7 +2244,8 @@ function fmtDatetime(dtStr) { function visibleCategoryCodesForCurrentPage() { // Which categories should appear in the dropdown: // - the variant exists for this page, OR - // - the category has a notfoundmessage + // - the category has a notfoundmessage (fallback to default content), OR + // - the category has visibilityifnocontent: visible (shows pagenotfoundmessage instead) // - always include the active category so user can see what they're on const out = new Set(); const page = currentPage @@ -2251,8 +2253,8 @@ function fmtDatetime(dtStr) { : null; categoriesList.forEach(cat => { const hasVariant = !page || !page.variants || page.variants.includes(cat.code); - const hasMsg = !!cat.notfoundmessage; - if (hasVariant || hasMsg || cat.code === activeCategory) out.add(cat.code); + const alwaysVisible = !!cat.notfoundmessage || cat.visibilityifnocontent === 'visible'; + if (hasVariant || alwaysVisible || cat.code === activeCategory) out.add(cat.code); }); return out; } diff --git a/docs/reference-config.md b/docs/reference-config.md index c0b429f..0c0d829 100644 --- a/docs/reference-config.md +++ b/docs/reference-config.md @@ -163,6 +163,12 @@ default-category: # The category used when no ?cat= parameter is in # current page. Also enables fallback: the renderer will fall back to # the default-category content instead of hiding the page. # Omit to hide the category from the dropdown when no variant exists. + visibilityifnocontent: hidden # hidden (default) or visible. + # hidden: category disappears from the selector when no variant exists + # for the current page (unless notfoundmessage is also set). + # visible: category stays in the selector regardless. When the user + # navigates to a page with no variant, pagenotfoundmessage is shown + # in the content area. No fallback to default-category content. pagenotfoundmessage: "This page is not yet available in English." # Message shown in the content area when a page cannot be fetched for # this category. Overrides the top-level pagenotfoundmessage. @@ -204,6 +210,7 @@ categories-selecttext: "Language" # Label shown next to the icon in the categor | `name-latin` | No | Secondary label in the dropdown, shown alongside `name` when `name` uses a non-Latin script. | | `direction` | No | `ltr` or `rtl`. Default: `ltr`. RTL flips nav and content direction. | | `notfoundmessage` | No | Short note shown in the dropdown when no variant exists for the current page. Also enables fallback to default-category content. | +| `visibilityifnocontent` | No | `hidden` (default) or `visible`. `visible` keeps the category in the selector when no variant exists; navigating to it shows `pagenotfoundmessage` with no fallback to default content. | | `pagenotfoundmessage` | No | Message shown in the content area when a page cannot be fetched for this category. Overrides the top-level `pagenotfoundmessage`. | | `font` | No | Font filename from `assets/fonts/`. Loaded on demand when this category is activated. | | `line-height` | No | Body line height override for this category. Restores to theme default when switching away. | @@ -277,7 +284,8 @@ categories: - code: nb name: Norsk direction: ltr - notfoundmessage: "Ikke tilgjengelig på norsk" + visibilityifnocontent: visible + pagenotfoundmessage: "Denne siden er ikke tilgjengelig på norsk ennå." - code: ar name: عربي name-latin: Arabic