|
1 | 1 | export type * from 'decap-cms-core';
|
2 | 2 | import { DecapCmsCore as cms } from 'decap-cms-core';
|
3 | 3 |
|
4 |
| -import type { CMS, CmsBackendType, InitOptions } from 'decap-cms-core'; |
| 4 | +import type { CMS, CmsBackendType, CmsConfig, CmsField, InitOptions } from 'decap-cms-core'; |
5 | 5 | export { CMS };
|
6 | 6 |
|
7 |
| -// Backend registration functions |
8 |
| -export async function registerBackend(type: CmsBackendType) { |
9 |
| - switch (type) { |
10 |
| - case 'aws-cognito-github-proxy': |
11 |
| - cms.registerBackend( |
12 |
| - type, |
13 |
| - (await import('decap-cms-backend-aws-cognito-github-proxy')).AwsCognitoGitHubProxyBackend, |
14 |
| - ); |
15 |
| - break; |
16 |
| - case 'azure': |
17 |
| - cms.registerBackend(type, (await import('decap-cms-backend-azure')).AzureBackend); |
18 |
| - break; |
19 |
| - case 'bitbucket': |
20 |
| - cms.registerBackend(type, (await import('decap-cms-backend-bitbucket')).BitbucketBackend); |
21 |
| - break; |
22 |
| - case 'git-gateway': |
23 |
| - cms.registerBackend(type, (await import('decap-cms-backend-git-gateway')).GitGatewayBackend); |
24 |
| - break; |
25 |
| - case 'github': |
26 |
| - cms.registerBackend(type, (await import('decap-cms-backend-github')).GitHubBackend); |
27 |
| - break; |
28 |
| - case 'gitlab': |
29 |
| - cms.registerBackend(type, (await import('decap-cms-backend-gitlab')).GitLabBackend); |
30 |
| - break; |
31 |
| - case 'gitea': |
32 |
| - cms.registerBackend(type, (await import('decap-cms-backend-gitea')).GiteaBackend); |
33 |
| - break; |
34 |
| - case 'test-repo': |
35 |
| - cms.registerBackend(type, (await import('decap-cms-backend-test')).TestBackend); |
36 |
| - break; |
37 |
| - case 'proxy': |
38 |
| - cms.registerBackend(type, (await import('decap-cms-backend-proxy')).ProxyBackend); |
39 |
| - break; |
40 |
| - default: |
41 |
| - throw new Error(`Backend type '${type}' not supported`); |
| 7 | +// List of known backends, will be auto-loaded based on config |
| 8 | +const backends = { |
| 9 | + 'aws-cognito-github-proxy': async () => |
| 10 | + (await import('decap-cms-backend-aws-cognito-github-proxy')).AwsCognitoGitHubProxyBackend, |
| 11 | + azure: async () => (await import('decap-cms-backend-azure')).AzureBackend, |
| 12 | + bitbucket: async () => (await import('decap-cms-backend-bitbucket')).BitbucketBackend, |
| 13 | + 'git-gateway': async () => (await import('decap-cms-backend-git-gateway')).GitGatewayBackend, |
| 14 | + github: async () => (await import('decap-cms-backend-github')).GitHubBackend, |
| 15 | + gitlab: async () => (await import('decap-cms-backend-gitlab')).GitLabBackend, |
| 16 | + gitea: async () => (await import('decap-cms-backend-gitea')).GiteaBackend, |
| 17 | + 'test-repo': async () => (await import('decap-cms-backend-test')).TestBackend, |
| 18 | + proxy: async () => (await import('decap-cms-backend-proxy')).ProxyBackend, |
| 19 | +}; |
| 20 | + |
| 21 | +async function registerBackend(type: CmsBackendType) { |
| 22 | + const loader = backends[type]; |
| 23 | + if (!loader) { |
| 24 | + throw new Error(`Backend type '${type}' not supported`); |
42 | 25 | }
|
| 26 | + cms.registerBackend(type, await loader()); |
43 | 27 | }
|
44 | 28 |
|
45 |
| -// Widget registration functions |
46 |
| -export async function registerCoreWidgets() { |
47 |
| - const { widgets } = await import('./core-widgets'); |
48 |
| - cms.registerWidget(widgets); |
49 |
| -} |
| 29 | +// List of known widgets, will be auto-loaded based on config |
| 30 | +const widgets = { |
| 31 | + map: async () => (await import('decap-cms-widget-map')).default.Widget(), |
| 32 | + code: async () => (await import('decap-cms-widget-code')).default.Widget(), |
| 33 | + string: async () => (await import('decap-cms-widget-string')).default.Widget(), |
| 34 | + number: async () => (await import('decap-cms-widget-number')).default.Widget(), |
| 35 | + text: async () => (await import('decap-cms-widget-text')).default.Widget(), |
| 36 | + image: async () => (await import('decap-cms-widget-image')).default.Widget(), |
| 37 | + file: async () => (await import('decap-cms-widget-file')).default.Widget(), |
| 38 | + select: async () => (await import('decap-cms-widget-select')).default.Widget(), |
| 39 | + markdown: async () => (await import('decap-cms-widget-markdown')).default.Widget(), |
| 40 | + list: async () => (await import('decap-cms-widget-list')).default.Widget(), |
| 41 | + object: async () => (await import('decap-cms-widget-object')).default.Widget(), |
| 42 | + relation: async () => (await import('decap-cms-widget-relation')).default.Widget(), |
| 43 | + boolean: async () => (await import('decap-cms-widget-boolean')).default.Widget(), |
| 44 | + datetime: async () => (await import('decap-cms-widget-datetime')).default.Widget(), |
| 45 | + color: async () => (await import('decap-cms-widget-colorstring')).default.Widget(), |
| 46 | +}; |
50 | 47 |
|
51 |
| -export async function registerMapWidget() { |
52 |
| - const m = await import('decap-cms-widget-map'); |
53 |
| - cms.registerWidget(m.default.Widget() as any); |
54 |
| -} |
| 48 | +// List of known editor components, will be auto-loaded based on config |
| 49 | +const editorComponents = { |
| 50 | + image: async () => (await import('decap-cms-editor-component-image')).default, |
| 51 | + 'code-block': () => ({ |
| 52 | + id: 'code-block', |
| 53 | + label: 'Code Block', |
| 54 | + widget: 'code', |
| 55 | + type: 'code-block', |
| 56 | + }), |
| 57 | +}; |
| 58 | + |
| 59 | +function registerWidgetsAndEditorComponents(config: CmsConfig) { |
| 60 | + const usedWidgets = new Set<string>(); |
| 61 | + const usedEditorComponents = new Set<string>(); |
| 62 | + |
| 63 | + // Collect widgets and editor components used in collection fields |
| 64 | + for (const c of config.collections) { |
| 65 | + if (c.files) { |
| 66 | + for (const file of c.files) { |
| 67 | + if (file.fields) collectWidgets(file.fields, usedWidgets, usedEditorComponents); |
| 68 | + } |
| 69 | + } |
| 70 | + if (c.fields) collectWidgets(c.fields, usedWidgets, usedEditorComponents); |
| 71 | + } |
| 72 | + |
| 73 | + // Load and register all used editor components |
| 74 | + usedEditorComponents.values().map(async type => { |
| 75 | + const loader = editorComponents[type as keyof typeof editorComponents]; |
| 76 | + if (loader) { |
| 77 | + // Don't override manually registered components... |
| 78 | + if (!cms.getEditorComponents().has(type)) { |
| 79 | + cms.registerEditorComponent(await loader()); |
| 80 | + } |
| 81 | + } else { |
| 82 | + // Check if the component has been manually registered... |
| 83 | + if (!cms.getEditorComponents().has(type)) { |
| 84 | + throw new Error( |
| 85 | + `Unknown editor component "${type}". If this is a custom component, make sure to register it.`, |
| 86 | + ); |
| 87 | + } |
| 88 | + } |
| 89 | + }); |
55 | 90 |
|
56 |
| -export async function registerCodeWidget() { |
57 |
| - const m = await import('decap-cms-widget-code'); |
58 |
| - cms.registerWidget(m.default.Widget() as any); |
| 91 | + // Collect widgets from editor components (like the "code" widget from the code-block) |
| 92 | + cms |
| 93 | + .getEditorComponents() |
| 94 | + .valueSeq() |
| 95 | + .forEach(e => { |
| 96 | + if (e?.widget) usedWidgets.add(e.widget); |
| 97 | + }); |
| 98 | + |
| 99 | + // Load and register all used widgets |
| 100 | + return Promise.all( |
| 101 | + usedWidgets.values().map(async type => { |
| 102 | + const loader = widgets[type as keyof typeof widgets]; |
| 103 | + if (loader) { |
| 104 | + cms.registerWidget(await loader()); |
| 105 | + } else { |
| 106 | + if (!cms.getWidget(type)) { |
| 107 | + throw new Error( |
| 108 | + `Unknown widget type "${type}". If this is a custom widget, make sure to register it.`, |
| 109 | + ); |
| 110 | + } |
| 111 | + } |
| 112 | + }), |
| 113 | + ); |
59 | 114 | }
|
60 | 115 |
|
61 |
| -// Editor component registration functions |
62 |
| -export async function registerImageComponent() { |
63 |
| - const m = await import('decap-cms-editor-component-image'); |
64 |
| - cms.registerEditorComponent(m.default); |
| 116 | +function collectWidgets(fields: CmsField[], widgets: Set<string>, editorComponents: Set<string>) { |
| 117 | + for (const f of fields) { |
| 118 | + widgets.add(f.widget); |
| 119 | + if (f.widget === 'list') { |
| 120 | + collectWidgets(f.field ? [f.field] : f.fields ?? [], widgets, editorComponents); |
| 121 | + } |
| 122 | + if (f.widget === 'object') { |
| 123 | + collectWidgets(f.fields, widgets, editorComponents); |
| 124 | + } |
| 125 | + if (f.widget === 'markdown' && f.editor_components) { |
| 126 | + f.editor_components.forEach(c => editorComponents.add(c)); |
| 127 | + } |
| 128 | + } |
65 | 129 | }
|
66 | 130 |
|
67 |
| -// Locale registration functions |
68 | 131 | export async function registerLocale(locale: string) {
|
69 | 132 | const m = await import('decap-cms-locales');
|
70 | 133 | if (locale in m) {
|
@@ -111,33 +174,13 @@ export const availableLocales = [
|
111 | 174 | 'zh_Hant', // Traditional Chinese
|
112 | 175 | ] as const;
|
113 | 176 |
|
114 |
| -// Convenience function to register everything |
115 |
| -export async function registerAll() { |
116 |
| - await Promise.all([ |
117 |
| - registerBackend('git-gateway'), |
118 |
| - registerBackend('azure'), |
119 |
| - registerBackend('aws-cognito-github-proxy'), |
120 |
| - registerBackend('github'), |
121 |
| - registerBackend('gitlab'), |
122 |
| - registerBackend('gitea'), |
123 |
| - registerBackend('bitbucket'), |
124 |
| - registerBackend('test-repo'), |
125 |
| - registerBackend('proxy'), |
126 |
| - registerCoreWidgets(), |
127 |
| - registerMapWidget(), |
128 |
| - registerCodeWidget(), |
129 |
| - registerImageComponent(), |
130 |
| - registerLocale('en'), // Register English by default |
131 |
| - ]); |
132 |
| -} |
133 |
| - |
134 | 177 | type Options = InitOptions & { setup?: (cms: CMS) => void | Promise<void> };
|
135 | 178 |
|
136 | 179 | export async function init(options: Options) {
|
137 | 180 | const { config, setup } = options;
|
138 | 181 | await Promise.all([
|
139 | 182 | setup && setup(cms),
|
140 |
| - registerCoreWidgets(), |
| 183 | + registerWidgetsAndEditorComponents(config), |
141 | 184 | registerLocale(config.locale || 'en'),
|
142 | 185 | registerBackend(config.local_backend ? 'proxy' : config.backend.name),
|
143 | 186 | ]);
|
|
0 commit comments