Skip to content

Commit 6757440

Browse files
authored
Use injectRoute to inject admin dashboard (#30)
1 parent acf0732 commit 6757440

8 files changed

+87
-282
lines changed

.changeset/cold-olives-prove.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'astro-netlify-cms': minor
3+
---
4+
5+
Refactor to use Astro’s built-in `injectRoute` helper to add the admin dashboard.
6+
7+
Significantly simplifies the Vite plugin logic and should make future improvements easier to implement.

admin-dashboard.astro

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<title>Content Manager</title>
5+
<meta
6+
name="description"
7+
content="Admin dashboard for managing website content"
8+
/>
9+
<script>
10+
import options from 'virtual:astro-netlify-cms/user-config';
11+
import initCMS from './dist/cms';
12+
initCMS(options);
13+
</script>
14+
</head>
15+
<body></body>
16+
</html>

integration/cms.ts

+7-111
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,16 @@
1-
import type { CmsField, CmsConfig } from 'netlify-cms-core';
2-
import CMS from 'netlify-cms-app';
3-
import { initIdentity } from './identity-widget';
4-
import type { NormalizedPreviewStyle } from './types';
1+
import { InitCmsOptions } from './types';
52

63
export default function initCMS({
7-
adminPath,
4+
cms,
85
config,
9-
components = {},
106
previewStyles = [],
11-
}: {
12-
adminPath: string;
13-
config: CmsConfig;
14-
// collections: {
15-
// component;
16-
// css: string;
17-
// collection: CmsCollection;
18-
// }[];
19-
components: Record<
20-
string,
21-
{
22-
component: React.ComponentType<any>;
23-
fields: (CmsField & { name: keyof any })[];
24-
}
25-
>;
26-
previewStyles: NormalizedPreviewStyle[];
27-
}) {
28-
initIdentity(adminPath);
29-
7+
}: InitCmsOptions) {
308
// Provide default values given we can make a reasonable guess
319
const mediaDefaults = !config.media_folder
3210
? { media_folder: 'public', public_folder: '/' }
3311
: {};
3412

35-
CMS.init({
13+
cms.init({
3614
config: {
3715
// Don’t try to load config.yml as we’re providing the config below
3816
load_config_file: false,
@@ -44,97 +22,15 @@ export default function initCMS({
4422
});
4523

4624
/**
47-
* Another drawback of using Netlify CMS is that it registers all preview
25+
* One drawback of using Netlify CMS is that it registers all preview
4826
* styles globally — not scoped to a specific collection.
49-
* You’ve lost Astro component’s scoped styling anyway by being forced
27+
* You lose Astro components’ scoped styling anyway by being forced
5028
* to use React, but just be extra careful.
5129
*
5230
* The (undocumented?) `raw: true` setting treats the first argument as
5331
* a raw CSS string to inject instead of as a URL to load a stylesheet from.
5432
*/
5533
previewStyles.forEach(([style, opts]) =>
56-
CMS.registerPreviewStyle(style, opts)
34+
cms.registerPreviewStyle(style, opts)
5735
);
58-
59-
/**
60-
* Register each of our collections’ preview styles and components.
61-
*/
62-
// collections.forEach(({ component, collection }) => {
63-
// CMS.registerPreviewTemplate(
64-
// collection.name,
65-
// ({ entry, widgetFor, getAsset }) => {
66-
// // Netlify CMS gives us an Immutable.js object for entry data.
67-
// // Here we convert this into a plain JS object.
68-
// const props = entry.get('data').toJS();
69-
70-
// // Some data types need extra work before passing them to the component.
71-
// collection.fields.forEach(({ name, widget }) => {
72-
// switch (widget) {
73-
// // Images can be in-memory before they’re uploaded, so we use the
74-
// // `getAsset` helper to get a useable source URL.
75-
// case 'image':
76-
// props[name] = props[name] && getAsset(props[name]).toString();
77-
// break;
78-
// // The `widgetFor` helper hands us rendered Markdown content.
79-
// // We also map fields named `body` to `children` props.
80-
// case 'markdown':
81-
// props[name === 'body' ? 'children' : name] = widgetFor(name);
82-
// break;
83-
// }
84-
// });
85-
86-
// return component(props);
87-
// }
88-
// );
89-
// });
90-
91-
/**
92-
* Below implements the infrastructure for custom components in the Markdown
93-
* editor.
94-
*
95-
* Caveats:
96-
* - Components MUST be block-level rather than inline
97-
* - Accessing `frontmatter` is not supported.
98-
* - Components MUST be imported in a post’s `setup` front matter.
99-
* The default value for the hidden `setup` field above does this, but
100-
* can’t update the value if new components are added after a post is
101-
* created.
102-
* - No `client:...` directive support yet. This should be do-able, just
103-
* needs some more RegExp wrangling.
104-
* - Attributes *must* be strings for now. Should be possible to support
105-
* other data types eventually to some degree.
106-
*/
107-
108-
// for (const Name in components) {
109-
// const { component, fields } = components[Name];
110-
// CMS.registerEditorComponent({
111-
// id: Name,
112-
// label: Name,
113-
// fields,
114-
// pattern: new RegExp(`^<${Name} (.*?)/>$`),
115-
// fromBlock: (match) =>
116-
// match[1]
117-
// .split('" ')
118-
// .map((attr) => attr.split('="'))
119-
// .reduce((attrs, [attr, val]) => ({ ...attrs, [attr]: val }), {}),
120-
// toBlock: (obj) => {
121-
// const attrs = Object.entries(obj)
122-
// .map(([attr, val]) => `${attr}="${val}"`)
123-
// .join(' ');
124-
// return `<${Name} ${attrs} />`;
125-
// },
126-
// toPreview: component,
127-
// });
128-
// }
129-
130-
/**
131-
* Things that would be nice but are currently impossible:
132-
*
133-
* - Expression syntax:
134-
* i. Netlify CMS doesn’t support creating custom inline widgets.
135-
* ii. Even for a custom block widget, Netlify CMS won’t provide
136-
* `frontmatter`, so you’re limited to plain JS, like `{5 * 2}`,
137-
* which is not very useful. (Obviously Astro APIs are also
138-
* not available in the browser.)
139-
*/
14036
}

integration/index.ts

+23-2
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,26 @@ export default function NetlifyCMS({
2222
config: cmsConfig,
2323
previewStyles = [],
2424
}: NetlifyCMSOptions) {
25+
if (!adminPath.startsWith('/')) {
26+
throw new Error(
27+
'`adminPath` option must be a root-relative pathname, starting with "/", got "' +
28+
adminPath +
29+
'"'
30+
);
31+
}
32+
if (adminPath.endsWith('/')) {
33+
adminPath = adminPath.slice(0, -1);
34+
}
35+
2536
const NetlifyCMSIntegration: AstroIntegration = {
2637
name: 'netlify-cms',
2738
hooks: {
28-
'astro:config:setup': ({ config, injectScript, updateConfig }) => {
39+
'astro:config:setup': ({
40+
config,
41+
injectRoute,
42+
injectScript,
43+
updateConfig,
44+
}) => {
2945
const newConfig: AstroUserConfig = {
3046
// Default to the URL provided by Netlify when building there. See:
3147
// https://docs.netlify.com/configure-builds/environment-variables/#deploy-urls-and-metadata
@@ -34,7 +50,6 @@ export default function NetlifyCMS({
3450
plugins: [
3551
...(config.vite?.plugins || []),
3652
AdminDashboard({
37-
adminPath,
3853
config: cmsConfig,
3954
previewStyles,
4055
}),
@@ -43,11 +58,17 @@ export default function NetlifyCMS({
4358
};
4459
updateConfig(newConfig);
4560

61+
injectRoute({
62+
pattern: adminPath,
63+
entryPoint: 'astro-netlify-cms/admin-dashboard.astro',
64+
});
65+
4666
injectScript(
4767
'page',
4868
`import { initIdentity } from '${widgetPath}'; initIdentity('${adminPath}')`
4969
);
5070
},
71+
5172
'astro:server:start': () => {
5273
const proxy = spawn('netlify-cms-proxy-server', {
5374
stdio: 'inherit',

integration/types.ts

+9
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
1+
import type CMS from 'netlify-cms-app';
2+
import type { CmsConfig } from 'netlify-cms-core';
3+
14
export type NormalizedPreviewStyle =
25
| [pathOrUrl: string]
36
| [rawCSS: string, meta: { raw: boolean }];
47

58
export type PreviewStyle = string | NormalizedPreviewStyle;
9+
10+
export interface InitCmsOptions {
11+
cms: typeof CMS;
12+
config: CmsConfig;
13+
previewStyles?: NormalizedPreviewStyle[];
14+
}

integration/virtual.d.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
declare module 'virtual:astro-netlify-cms/user-config' {
2+
import type { InitCmsOptions } from './types';
3+
const CmsOptions: InitCmsOptions;
4+
export default CmsOptions;
5+
}

0 commit comments

Comments
 (0)