domma-cms 1.6.7 → 1.6.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "1.6.7",
3
+ "version": "1.6.8",
4
4
  "description": "File-based CMS powered by Domma and Fastify. Run npx domma-cms my-site to create a new project.",
5
5
  "type": "module",
6
6
  "main": "server/server.js",
@@ -917,3 +917,38 @@ export function projectsBadge(projects = []) {
917
917
  }
918
918
  };
919
919
  }
920
+
921
+ /**
922
+ * The pages that are offline because their project is switched off. The public
923
+ * renderer 404s them (pagePublishing.resolvePublishedPage), so search and the
924
+ * sitemap must leave them out too - one rule, here.
925
+ *
926
+ * @param {object[]} pages - each with `urlPath` and optional `project`
927
+ * @param {object} [deps] - DI for tests
928
+ * @param {Function} [deps.projectOf] - async (urlPath, frontmatterProject) → slug
929
+ * @param {Function} [deps.isEnabled] - async (slug) → boolean
930
+ * @param {Function} [deps.listProjects] - async () → projects (the shortcut when none is disabled)
931
+ * @returns {Promise<Set<string>>} urlPaths
932
+ */
933
+ export async function offlinePageUrls(pages = [], deps = {}) {
934
+ const offline = new Set();
935
+ const projectOf = deps.projectOf || getProjectForPage;
936
+ const isEnabled = deps.isEnabled || isProjectEnabled;
937
+ const listAll = deps.listProjects || (deps.projectOf && deps.isEnabled ? null : listProjects);
938
+ // Nothing is disabled on most sites - skip resolving every page's project.
939
+ let anyDisabled = true;
940
+ if (listAll) {
941
+ try { anyDisabled = (await listAll()).some(p => p?.enabled === false); } catch { anyDisabled = true; }
942
+ }
943
+ if (!anyDisabled) return offline;
944
+ const enabled = new Map();
945
+ for (const page of pages) {
946
+ if (!page?.urlPath) continue;
947
+ try {
948
+ const slug = await projectOf(page.urlPath, page.project);
949
+ if (!enabled.has(slug)) enabled.set(slug, await isEnabled(slug));
950
+ if (!enabled.get(slug)) offline.add(page.urlPath);
951
+ } catch { /* project store unreadable - leave the page to the other checks */ }
952
+ }
953
+ return offline;
954
+ }
@@ -389,29 +389,9 @@ export function scorePage(page, query, words) {
389
389
  * @returns {Promise<{offline: Set<string>, noindex: Set<string>}>} urlPaths
390
390
  */
391
391
  export async function searchExclusions(pages = [], deps = {}) {
392
- const offline = new Set();
393
392
  const noindex = new Set();
394
-
395
- const projects = deps.projectOf && deps.isEnabled ? null : await import('./projects.js');
396
- const projectOf = deps.projectOf || projects.getProjectForPage;
397
- const isEnabled = deps.isEnabled || projects.isProjectEnabled;
398
- const listAll = deps.listProjects || projects?.listProjects;
399
- // Nothing is disabled on most sites - skip resolving every page's project.
400
- let anyDisabled = true;
401
- if (listAll) {
402
- try { anyDisabled = (await listAll()).some(p => p?.enabled === false); } catch { anyDisabled = true; }
403
- }
404
- if (anyDisabled) {
405
- const enabled = new Map();
406
- for (const page of pages) {
407
- if (!page?.urlPath) continue;
408
- try {
409
- const slug = await projectOf(page.urlPath, page.project);
410
- if (!enabled.has(slug)) enabled.set(slug, await isEnabled(slug));
411
- if (!enabled.get(slug)) offline.add(page.urlPath);
412
- } catch { /* project store unreadable - leave the page to the other checks */ }
413
- }
414
- }
393
+ const {offlinePageUrls} = await import('./projects.js');
394
+ const offline = await offlinePageUrls(pages, deps);
415
395
 
416
396
  let overrides;
417
397
  if (deps.seoOverrides) {
@@ -8,6 +8,7 @@
8
8
  * invalidates whenever a page is created, updated, renamed, or deleted.
9
9
  */
10
10
  import {listPages} from './content.js';
11
+ import {offlinePageUrls} from './projects.js';
11
12
  import {getConfig} from '../config.js';
12
13
  import {applyTransforms, getSitemapSources} from './hooks.js';
13
14
 
@@ -22,6 +23,7 @@ const validPriority = (p) => p !== undefined && p !== null && p !== '' && Number
22
23
  * - Must be publicly visible (role-gated pages never index)
23
24
  * - Must not be the error page
24
25
  * - Must not opt out via `seo.noindex`
26
+ * - (in listSitemapEntries) must not be in a switched-off project - it 404s
25
27
  *
26
28
  * @param {object} page - Parsed page from content service
27
29
  * @returns {boolean}
@@ -51,8 +53,9 @@ function pageEntry(page) {
51
53
  */
52
54
  export async function listSitemapEntries(baseUrl, {log = console} = {}) {
53
55
  const normalised = normaliseBaseUrl(baseUrl);
54
- const pages = await listPages();
55
- const entries = pages.filter(shouldIncludeInSitemap).map(pageEntry);
56
+ const pages = (await listPages()).filter(shouldIncludeInSitemap);
57
+ const offline = await offlinePageUrls(pages);
58
+ const entries = pages.filter(p => !offline.has(p.urlPath)).map(pageEntry);
56
59
  const seen = new Set(entries.map(e => e.urlPath));
57
60
 
58
61
  for (const source of getSitemapSources()) {