domma-cms 1.10.1 → 1.10.2

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/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## [1.10.2] - 2026-10-24
4
+
5
+ - Blocks, Components, Views and Content API now default to the Content menu. Existing menus move these entries from their former default folders once, preserving labels, permissions, settings and later admin rearrangements.
6
+
3
7
  ## [1.10.1] - 2026-10-24
4
8
 
5
9
  - **Format on save no longer puts a block's CSS into its HTML.** With Format on save on, saving a block formatted its hidden CSS through the browser's insertText, which types into whatever has focus - the HTML editor - so the formatted CSS was saved inside the HTML. Edits now go through insertText only when their own editor has focus (`applyEdit` in `code-format.js`, `replaceRange` in `markdown-toolbar.js`).
@@ -66,6 +66,30 @@
66
66
  "url": "#/theme",
67
67
  "icon": "droplet",
68
68
  "permission": "theme"
69
+ },
70
+ {
71
+ "text": "Views",
72
+ "url": "#/views",
73
+ "icon": "eye",
74
+ "permission": "views"
75
+ },
76
+ {
77
+ "text": "Blocks",
78
+ "url": "#/blocks",
79
+ "icon": "box",
80
+ "permission": "pages"
81
+ },
82
+ {
83
+ "text": "Components",
84
+ "url": "#/components",
85
+ "icon": "component",
86
+ "permission": "components"
87
+ },
88
+ {
89
+ "text": "Content API",
90
+ "url": "#/content-api",
91
+ "icon": "file-text",
92
+ "permission": "settings"
69
93
  }
70
94
  ],
71
95
  "key": "content"
@@ -87,30 +111,12 @@
87
111
  "icon": "layout",
88
112
  "permission": "collections"
89
113
  },
90
- {
91
- "text": "Views",
92
- "url": "#/views",
93
- "icon": "eye",
94
- "permission": "views"
95
- },
96
114
  {
97
115
  "text": "Actions",
98
116
  "url": "#/actions",
99
117
  "icon": "zap",
100
118
  "permission": "actions"
101
119
  },
102
- {
103
- "text": "Blocks",
104
- "url": "#/blocks",
105
- "icon": "box",
106
- "permission": "pages"
107
- },
108
- {
109
- "text": "Components",
110
- "url": "#/components",
111
- "icon": "component",
112
- "permission": "components"
113
- },
114
120
  {
115
121
  "text": "API Builder",
116
122
  "url": "#/api-endpoints",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "domma-cms",
3
- "version": "1.10.1",
3
+ "version": "1.10.2",
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",
package/server/server.js CHANGED
@@ -682,11 +682,11 @@ registerSidebarItem({folder: 'content', item: {source: 'Built in', text: 'Contex
682
682
  registerSidebarItem({folder: 'content', item: {source: 'Built in', text: 'Theme', url: '#/theme', icon: 'droplet', permission: 'theme', countUrl: '/api/theme/count', inventory: true}});
683
683
  registerSidebarItem({folder: 'data', item: {source: 'Built in', text: 'Collections', url: '#/collections', icon: 'database', permission: 'collections', countUrl: '/api/collections/_count', inventory: true}});
684
684
  registerSidebarItem({folder: 'data', item: {source: 'Built in', text: 'Forms', url: '#/forms', icon: 'layout', permission: 'collections', countUrl: '/api/forms/_count', inventory: true}});
685
- registerSidebarItem({folder: 'data', item: {source: 'Built in', text: 'Views', url: '#/views', icon: 'eye', permission: 'views', countUrl: '/api/views/_count', inventory: true}});
685
+ registerSidebarItem({folder: 'content', item: {source: 'Built in', text: 'Views', url: '#/views', icon: 'eye', permission: 'views', countUrl: '/api/views/_count', inventory: true}});
686
686
  registerSidebarItem({folder: 'data', item: {source: 'Built in', text: 'Actions', url: '#/actions', icon: 'zap', permission: 'actions', countUrl: '/api/actions/_count', inventory: true}});
687
687
  registerSidebarItem({folder: 'data', item: {source: 'Built in', text: 'API Builder', url: '#/api-endpoints', icon: 'code', permission: 'api-endpoints', countUrl: '/api/api-endpoints/_count', inventory: true}});
688
- registerSidebarItem({folder: 'data', item: {source: 'Built in', text: 'Blocks', url: '#/blocks', icon: 'box', permission: 'pages', countUrl: '/api/blocks/_count', inventory: true}});
689
- registerSidebarItem({folder: 'data', item: {source: 'Built in', text: 'Components', url: '#/components', icon: 'component', permission: 'components', countUrl: '/api/components/_count', inventory: true}});
688
+ registerSidebarItem({folder: 'content', item: {source: 'Built in', text: 'Blocks', url: '#/blocks', icon: 'box', permission: 'pages', countUrl: '/api/blocks/_count', inventory: true}});
689
+ registerSidebarItem({folder: 'content', item: {source: 'Built in', text: 'Components', url: '#/components', icon: 'component', permission: 'components', countUrl: '/api/components/_count', inventory: true}});
690
690
  // System. Notifications, Site Settings and My Profile are signals (unread, something quietly wrong,
691
691
  // details not filled in); Layouts and API Tokens are a count while all is well and a signal when not
692
692
  // (pages on a missing layout, tokens expiring - the answer says `inventory` in the calm case); Effects
@@ -701,7 +701,7 @@ registerSidebarItem({folder: 'system', item: {source: 'Built in', text: 'Layouts
701
701
  registerSidebarItem({folder: 'system', item: {source: 'Built in', text: 'Plugins', url: '#/plugins', icon: 'package', permission: 'plugins', countUrl: '/api/plugins/_count', inventory: true}});
702
702
  registerSidebarItem({folder: 'system', item: {source: 'Built in', text: 'API Tokens', url: '#/api-tokens', icon: 'key', permission: 'api-tokens', countUrl: '/api/api-tokens/_count'}});
703
703
  registerSidebarItem({folder: 'system', item: {source: 'Built in', text: 'Search', url: '#/search', icon: 'search', permission: 'settings', countUrl: '/api/search/_count', inventory: true}});
704
- registerSidebarItem({folder: 'system', item: {source: 'Built in', text: 'Content API', url: '#/content-api', icon: 'file-text', permission: 'settings', countUrl: '/api/content-api/_count', inventory: true}});
704
+ registerSidebarItem({folder: 'content', item: {source: 'Built in', text: 'Content API', url: '#/content-api', icon: 'file-text', permission: 'settings', countUrl: '/api/content-api/_count', inventory: true}});
705
705
  // Documentation pages added after the sidebar menu was seeded (0.93.1). The menu is
706
706
  // seeded once, so new pages reach existing sites only by registering here. The two
707
707
  // sub-folders have no key in older menus; findFolder() falls back to their name.
@@ -37,7 +37,11 @@ const SEED_ITEMS = [
37
37
  items: [
38
38
  {text: 'Pages', url: '#/pages', icon: 'file-text', permission: 'pages'},
39
39
  {text: 'Media', url: '#/media', icon: 'image', permission: 'media'},
40
- {text: 'Site menus', url: '#/menus', icon: 'menu', permission: 'menus'}
40
+ {text: 'Site menus', url: '#/menus', icon: 'menu', permission: 'menus'},
41
+ {text: 'Blocks', url: '#/blocks', icon: 'box', permission: 'pages'},
42
+ {text: 'Components', url: '#/components', icon: 'component', permission: 'components'},
43
+ {text: 'Views', url: '#/views', icon: 'eye', permission: 'views'},
44
+ {text: 'Content API', url: '#/content-api', icon: 'file-text', permission: 'settings'}
41
45
  ]
42
46
  },
43
47
  {
@@ -45,11 +49,8 @@ const SEED_ITEMS = [
45
49
  items: [
46
50
  {text: 'Collections', url: '#/collections', icon: 'database', permission: 'collections'},
47
51
  {text: 'Forms', url: '#/forms', icon: 'layout', permission: 'collections'},
48
- {text: 'Views', url: '#/views', icon: 'eye', permission: 'views'},
49
52
  {text: 'Actions', url: '#/actions', icon: 'zap', permission: 'actions'},
50
- {text: 'API Builder', url: '#/api-endpoints', icon: 'code', permission: 'api-endpoints'},
51
- {text: 'Blocks', url: '#/blocks', icon: 'box', permission: 'pages'},
52
- {text: 'Components', url: '#/components', icon: 'component', permission: 'components'}
53
+ {text: 'API Builder', url: '#/api-endpoints', icon: 'code', permission: 'api-endpoints'}
53
54
  ]
54
55
  },
55
56
  // Enabled Tools are placed here at render time (placeTools in
@@ -413,6 +414,33 @@ export async function ensureFolderKeys(opts = {}) {
413
414
  changed = true;
414
415
  }
415
416
 
417
+ // Move content-building entries from their old default folders once. Keep
418
+ // their full saved settings, and respect later admin rearrangements.
419
+ if (!menu.meta?.contentMenuItems && items.length) {
420
+ const oldFolders = {'#/blocks': 'data', '#/components': 'data', '#/views': 'data', '#/content-api': 'system'};
421
+ const moving = [];
422
+ for (const folder of items.filter(n => isFolder(n) && ['data', 'system'].includes(n.key))) {
423
+ const matches = n => oldFolders[n?.url] === folder.key;
424
+ moving.push(...(folder.items || []).filter(matches));
425
+ if (Array.isArray(folder.items)) folder.items = folder.items.filter(n => !matches(n));
426
+ }
427
+ const hasUrl = (nodes, url) => nodes.some(n => n?.url === url
428
+ || (Array.isArray(n?.items) && hasUrl(n.items, url)));
429
+ let content = items.find(n => isFolder(n) && n.key === 'content');
430
+ for (const item of moving) {
431
+ if (hasUrl(items, item.url)) continue;
432
+ if (!content) {
433
+ content = {text: 'Content', key: 'content', icon: 'edit', items: []};
434
+ const idx = items.findIndex(n => isFolder(n) && ['data', 'system'].includes(n.key));
435
+ items.splice(idx === -1 ? items.length : idx, 0, content);
436
+ }
437
+ if (!Array.isArray(content.items)) content.items = [];
438
+ content.items.push(item);
439
+ }
440
+ menu.meta = {...(menu.meta || {}), contentMenuItems: true};
441
+ changed = true;
442
+ }
443
+
416
444
  // An empty menu is left empty: the renderer's minimal fallback (Dashboard,
417
445
  // Menus) is what an admin needs to repair it, and a lone Tools folder would
418
446
  // stop that fallback from applying.