@delmaredigital/payload-puck 0.7.0 → 0.8.1
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/README.md +44 -0
- package/dist/plugin/index.d.ts +0 -1
- package/dist/plugin/index.js +5 -23
- package/dist/types/index.d.ts +29 -27
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -14
- package/dist/endpoints/postcss.d.js +0 -4
- package/dist/endpoints/styles.d.ts +0 -19
- package/dist/endpoints/styles.js +0 -153
- package/dist/next/index.d.ts +0 -64
- package/dist/next/index.js +0 -155
package/README.md
CHANGED
|
@@ -43,6 +43,50 @@ pnpm add @delmaredigital/payload-puck @puckeditor/core
|
|
|
43
43
|
|
|
44
44
|
> **Security:** If your app uses Next.js middleware (or proxy.ts) to protect dynamic routes, use `next` >= 15.5.16 / 16.2.5 to pick up the fix for [CVE-2026-44574](https://github.com/vercel/next.js/security/advisories/GHSA-492v-c6pp-mqqv) (middleware bypass via dynamic route parameter injection). Turbopack users need >= 15.5.18 / 16.2.6.
|
|
45
45
|
|
|
46
|
+
### Upgrading to 0.8.0 (breaking)
|
|
47
|
+
|
|
48
|
+
**Editor CSS is now built by your app, not by this plugin.** Three options collapse into one, and `withPuckCSS` is gone.
|
|
49
|
+
|
|
50
|
+
Add a build step using Tailwind's own CLI. Tailwind v4 ships the CLI as a separate package:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
pnpm add -D @tailwindcss/cli # v4 only; v3 already provides the `tailwindcss` binary
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
```jsonc
|
|
57
|
+
// package.json — quote the paths; App Router route groups like (frontend) are shell syntax
|
|
58
|
+
"scripts": {
|
|
59
|
+
"build:puck-css": "tailwindcss -i './src/app/(frontend)/globals.css' -o './public/puck-editor-styles.css'",
|
|
60
|
+
"dev:puck-css": "tailwindcss -i './src/app/(frontend)/globals.css' -o './public/puck-editor-styles.css' --watch",
|
|
61
|
+
"build": "pnpm build:puck-css && next build",
|
|
62
|
+
"dev": "pnpm build:puck-css && next dev"
|
|
63
|
+
}
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Add `public/puck-editor-styles.css` to `.gitignore` — it's a build artifact. Run `dev:puck-css` in a second terminal while actively editing theme CSS.
|
|
67
|
+
|
|
68
|
+
Then pass the URL:
|
|
69
|
+
|
|
70
|
+
```typescript
|
|
71
|
+
// before
|
|
72
|
+
createPuckPlugin({
|
|
73
|
+
editorStylesheet: 'src/app/(frontend)/globals.css',
|
|
74
|
+
editorStylesheetCompiled: '/puck-editor-styles.css',
|
|
75
|
+
editorStylesheetUrls: ['https://fonts.googleapis.com/css2?family=Inter'],
|
|
76
|
+
})
|
|
77
|
+
|
|
78
|
+
// after
|
|
79
|
+
createPuckPlugin({
|
|
80
|
+
editorStylesheets: ['/puck-editor-styles.css', 'https://fonts.googleapis.com/css2?family=Inter'],
|
|
81
|
+
})
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Finally, remove the `withPuckCSS` import and wrapper from `next.config.js`, and drop any `editorStylesheets` prop on `PuckConfigProvider` — the plugin wires it through automatically now.
|
|
85
|
+
|
|
86
|
+
> **Why:** the old approach compiled CSS at runtime in dev and via a **webpack plugin** in production. Next.js 16 defaults to Turbopack, which never runs `webpack()` hooks — so the production stylesheet was silently never generated and the editor rendered unstyled, while local dev looked perfect. One artifact, built by your own toolchain, now resolves identically everywhere.
|
|
87
|
+
|
|
88
|
+
Also removed: the `/api/puck/styles` endpoint, the `/next` entry point, and the `postcss` / `postcss-load-config` peer dependencies.
|
|
89
|
+
|
|
46
90
|
### Upgrading to 0.7.0 (breaking)
|
|
47
91
|
|
|
48
92
|
`0.7.0` raises two floors. Both are a one-line change for most projects:
|
package/dist/plugin/index.d.ts
CHANGED
|
@@ -42,7 +42,6 @@ export { generatePagesCollection } from './collections/Pages.js';
|
|
|
42
42
|
export { TemplatesCollection } from '../collections/Templates.js';
|
|
43
43
|
export { getPuckFields, getPuckCollectionConfig, puckDataField, editorVersionField, createEditorVersionField, pageLayoutField, createPageLayoutField, isHomepageField, seoFieldGroup, conversionFieldGroup, } from './fields/index.js';
|
|
44
44
|
export { generatePuckEditField };
|
|
45
|
-
export { PUCK_STYLES_ENDPOINT } from '../endpoints/styles.js';
|
|
46
45
|
export { createIsHomepageUniqueHook, unsetHomepage, HomepageConflictError, } from './hooks/index.js';
|
|
47
46
|
export type { IsHomepageUniqueHookOptions } from './hooks/index.js';
|
|
48
47
|
export type { PuckPluginOptions, PuckAdminConfig } from '../types/index.js';
|
package/dist/plugin/index.js
CHANGED
|
@@ -5,7 +5,6 @@ import { AiContextCollection } from '../ai/collections/AiContext.js';
|
|
|
5
5
|
import { getPuckFields } from './fields/index.js';
|
|
6
6
|
import { createIsHomepageUniqueHook } from './hooks/isHomepageUnique.js';
|
|
7
7
|
import { createListHandler, createCreateHandler, createGetHandler, createUpdateHandler, createDeleteHandler, createVersionsHandler, createRestoreHandler } from '../endpoints/index.js';
|
|
8
|
-
import { createStylesHandler, PUCK_STYLES_ENDPOINT } from '../endpoints/styles.js';
|
|
9
8
|
import { createAiEndpointHandler } from '../endpoints/ai.js';
|
|
10
9
|
import { createPromptsListHandler, createPromptsCreateHandler, createPromptsUpdateHandler, createPromptsDeleteHandler } from '../endpoints/prompts.js';
|
|
11
10
|
import { createContextListHandler, createContextCreateHandler, createContextUpdateHandler, createContextDeleteHandler } from '../endpoints/context.js';
|
|
@@ -105,7 +104,7 @@ import { createContextListHandler, createContextCreateHandler, createContextUpda
|
|
|
105
104
|
* })
|
|
106
105
|
* ```
|
|
107
106
|
*/ export function createPuckPlugin(options = {}) {
|
|
108
|
-
const { pagesCollection = 'pages', autoGenerateCollection = true, admin: pluginAdminConfig = {}, enableAdminView = true, adminViewPath = '/puck-editor', enableEndpoints = true, pageTreeIntegration,
|
|
107
|
+
const { pagesCollection = 'pages', autoGenerateCollection = true, admin: pluginAdminConfig = {}, enableAdminView = true, adminViewPath = '/puck-editor', enableEndpoints = true, pageTreeIntegration, editorStylesheets: editorStylesheetsOption = [], ai: aiConfig, previewUrl, rootPropsMapping } = options;
|
|
109
108
|
const { addEditButton = true } = pluginAdminConfig;
|
|
110
109
|
// Parse page-tree integration config
|
|
111
110
|
// - undefined: auto-detect at runtime (null stored, view will check for pageSegment field)
|
|
@@ -274,32 +273,17 @@ import { createContextListHandler, createContextCreateHandler, createContextUpda
|
|
|
274
273
|
'/puck/:collection/:id/versions',
|
|
275
274
|
'/puck/:collection/:id/restore'
|
|
276
275
|
]);
|
|
277
|
-
//
|
|
278
|
-
//
|
|
279
|
-
//
|
|
280
|
-
const isProduction = process.env.NODE_ENV === 'production';
|
|
281
|
-
const useCompiledCss = isProduction && editorStylesheetCompiled;
|
|
276
|
+
// Stylesheet URLs for the editor preview iframe. These are passed straight
|
|
277
|
+
// through: the same URLs resolve in development and production, so the
|
|
278
|
+
// editor can no longer look correct locally and unstyled in production.
|
|
282
279
|
const editorStylesheets = [
|
|
283
|
-
...
|
|
284
|
-
editorStylesheetCompiled
|
|
285
|
-
] : editorStylesheet ? [
|
|
286
|
-
PUCK_STYLES_ENDPOINT
|
|
287
|
-
] : [],
|
|
288
|
-
...editorStylesheetUrls
|
|
280
|
+
...editorStylesheetsOption
|
|
289
281
|
];
|
|
290
282
|
// Filter out parameterized puck endpoints from previous plugin instances
|
|
291
283
|
// so we can re-register them with the merged collections list
|
|
292
284
|
const incomingEndpoints = (incomingConfig.endpoints || []).filter((ep)=>!parameterizedPuckPaths.has(ep.path));
|
|
293
285
|
const endpoints = enableEndpoints ? [
|
|
294
286
|
...incomingEndpoints,
|
|
295
|
-
// Styles endpoint MUST be first - exact match before parameterized routes
|
|
296
|
-
...editorStylesheet ? [
|
|
297
|
-
{
|
|
298
|
-
path: '/puck/styles',
|
|
299
|
-
method: 'get',
|
|
300
|
-
handler: createStylesHandler(editorStylesheet)
|
|
301
|
-
}
|
|
302
|
-
] : [],
|
|
303
287
|
// AI endpoint (exact match, before parameterized routes)
|
|
304
288
|
...aiConfig?.enabled ? [
|
|
305
289
|
{
|
|
@@ -441,7 +425,5 @@ export { TemplatesCollection } from '../collections/Templates.js';
|
|
|
441
425
|
export { getPuckFields, getPuckCollectionConfig, puckDataField, editorVersionField, createEditorVersionField, pageLayoutField, createPageLayoutField, isHomepageField, seoFieldGroup, conversionFieldGroup } from './fields/index.js';
|
|
442
426
|
// Export the edit button generator for hybrid collections
|
|
443
427
|
export { generatePuckEditField };
|
|
444
|
-
// Export styles endpoint constant
|
|
445
|
-
export { PUCK_STYLES_ENDPOINT } from '../endpoints/styles.js';
|
|
446
428
|
// Re-export hooks for hybrid collection integration
|
|
447
429
|
export { createIsHomepageUniqueHook, unsetHomepage, HomepageConflictError } from './hooks/index.js';
|
package/dist/types/index.d.ts
CHANGED
|
@@ -141,42 +141,44 @@ export interface PuckPluginOptions {
|
|
|
141
141
|
*/
|
|
142
142
|
pageTreeIntegration?: boolean | PageTreeIntegrationOptions;
|
|
143
143
|
/**
|
|
144
|
-
*
|
|
145
|
-
* The plugin compiles this file with PostCSS/Tailwind and serves it at /api/puck/styles.
|
|
146
|
-
* This allows the editor preview to display your frontend styles (CSS variables, Tailwind utilities).
|
|
144
|
+
* Stylesheet URLs to load inside the editor preview iframe, in order.
|
|
147
145
|
*
|
|
148
|
-
*
|
|
149
|
-
*
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
* Additional stylesheet URLs to load in the editor iframe.
|
|
154
|
-
* Use this for external stylesheets like Google Fonts that can't be compiled.
|
|
146
|
+
* These are plain URLs the browser fetches — a static file your build emits,
|
|
147
|
+
* or any external stylesheet. The plugin does not compile CSS: your app's own
|
|
148
|
+
* toolchain already does that far better than we can, and compiling it a
|
|
149
|
+
* second time was the source of a dev/production split where the editor
|
|
150
|
+
* looked correct locally and unstyled in production.
|
|
155
151
|
*
|
|
156
|
-
*
|
|
157
|
-
|
|
158
|
-
editorStylesheetUrls?: string[];
|
|
159
|
-
/**
|
|
160
|
-
* Path to pre-compiled CSS file for production use.
|
|
161
|
-
* When set, the editor will load this static file instead of using the runtime compilation endpoint.
|
|
162
|
-
* Use with `withPuckCSS()` from `@delmaredigital/payload-puck/next` to compile CSS at build time.
|
|
152
|
+
* Generate the file with Tailwind's own CLI as part of your build, so the
|
|
153
|
+
* editor loads byte-identical CSS in every environment:
|
|
163
154
|
*
|
|
164
|
-
*
|
|
155
|
+
* ```jsonc
|
|
156
|
+
* // package.json
|
|
157
|
+
* {
|
|
158
|
+
* "scripts": {
|
|
159
|
+
* "build:puck-css": "tailwindcss -i ./src/app/(frontend)/globals.css -o ./public/puck-editor-styles.css",
|
|
160
|
+
* "build": "pnpm build:puck-css && next build",
|
|
161
|
+
* "dev": "pnpm build:puck-css --watch & next dev"
|
|
162
|
+
* }
|
|
163
|
+
* }
|
|
164
|
+
* ```
|
|
165
165
|
*
|
|
166
|
-
* @example
|
|
167
166
|
* ```typescript
|
|
168
|
-
* // next.config.js
|
|
169
|
-
* import { withPuckCSS } from '@delmaredigital/payload-puck/next'
|
|
170
|
-
* export default withPuckCSS({ cssInput: 'src/globals.css' })(nextConfig)
|
|
171
|
-
*
|
|
172
|
-
* // payload.config.ts
|
|
173
167
|
* createPuckPlugin({
|
|
174
|
-
*
|
|
175
|
-
*
|
|
168
|
+
* editorStylesheets: [
|
|
169
|
+
* '/puck-editor-styles.css',
|
|
170
|
+
* 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700',
|
|
171
|
+
* ],
|
|
176
172
|
* })
|
|
177
173
|
* ```
|
|
174
|
+
*
|
|
175
|
+
* Resolved URLs are published on `config.custom.puck.editorStylesheets` and
|
|
176
|
+
* passed to the editor automatically — you do not need to repeat them on
|
|
177
|
+
* `PuckConfigProvider`.
|
|
178
|
+
*
|
|
179
|
+
* @example ['/puck-editor-styles.css']
|
|
178
180
|
*/
|
|
179
|
-
|
|
181
|
+
editorStylesheets?: string[];
|
|
180
182
|
/**
|
|
181
183
|
* AI configuration for the plugin.
|
|
182
184
|
* Enables AI-powered page generation in the editor.
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.8.1";
|
package/dist/version.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// Auto-generated by scripts/generate-version.js - do not edit manually
|
|
2
|
-
export const VERSION = '0.
|
|
2
|
+
export const VERSION = '0.8.1';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@delmaredigital/payload-puck",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "Puck visual page builder plugin for Payload CMS",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -82,11 +82,6 @@
|
|
|
82
82
|
"types": "./dist/ai/index.d.ts",
|
|
83
83
|
"default": "./dist/ai/index.js"
|
|
84
84
|
},
|
|
85
|
-
"./next": {
|
|
86
|
-
"import": "./dist/next/index.js",
|
|
87
|
-
"types": "./dist/next/index.d.ts",
|
|
88
|
-
"default": "./dist/next/index.js"
|
|
89
|
-
},
|
|
90
85
|
"./email": {
|
|
91
86
|
"import": "./dist/email/index.js",
|
|
92
87
|
"types": "./dist/email/index.d.ts",
|
|
@@ -123,8 +118,6 @@
|
|
|
123
118
|
"@tailwindcss/postcss": ">=4.0.0",
|
|
124
119
|
"next": ">=15.4.8",
|
|
125
120
|
"payload": ">=3.69.0",
|
|
126
|
-
"postcss": ">=8.0.0",
|
|
127
|
-
"postcss-load-config": ">=4.0.0",
|
|
128
121
|
"react": ">=19.2.1",
|
|
129
122
|
"react-dom": ">=19.2.1",
|
|
130
123
|
"tailwindcss": ">=3.0.0 || >=4.0.0",
|
|
@@ -137,12 +130,6 @@
|
|
|
137
130
|
"@payloadcms/next": {
|
|
138
131
|
"optional": true
|
|
139
132
|
},
|
|
140
|
-
"postcss": {
|
|
141
|
-
"optional": true
|
|
142
|
-
},
|
|
143
|
-
"postcss-load-config": {
|
|
144
|
-
"optional": true
|
|
145
|
-
},
|
|
146
133
|
"tailwindcss": {
|
|
147
134
|
"optional": true
|
|
148
135
|
},
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Styles Endpoint Handler
|
|
3
|
-
*
|
|
4
|
-
* Compiles and serves CSS for the editor iframe.
|
|
5
|
-
* Uses the consumer's PostCSS/Tailwind installation via peer dependencies.
|
|
6
|
-
* Loads the project's postcss.config.js for proper plugin configuration.
|
|
7
|
-
*/
|
|
8
|
-
import type { PayloadHandler } from 'payload';
|
|
9
|
-
/**
|
|
10
|
-
* Creates a handler that serves compiled CSS for the editor iframe
|
|
11
|
-
*
|
|
12
|
-
* @param cssFilePath - Path to CSS file relative to project root
|
|
13
|
-
* @returns PayloadHandler that serves compiled CSS
|
|
14
|
-
*/
|
|
15
|
-
export declare function createStylesHandler(cssFilePath: string): PayloadHandler;
|
|
16
|
-
/**
|
|
17
|
-
* Helper constant for the styles endpoint URL
|
|
18
|
-
*/
|
|
19
|
-
export declare const PUCK_STYLES_ENDPOINT = "/api/puck/styles";
|
package/dist/endpoints/styles.js
DELETED
|
@@ -1,153 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Styles Endpoint Handler
|
|
3
|
-
*
|
|
4
|
-
* Compiles and serves CSS for the editor iframe.
|
|
5
|
-
* Uses the consumer's PostCSS/Tailwind installation via peer dependencies.
|
|
6
|
-
* Loads the project's postcss.config.js for proper plugin configuration.
|
|
7
|
-
*/ import { readFileSync, statSync, existsSync } from 'fs';
|
|
8
|
-
import { join } from 'path';
|
|
9
|
-
const cssCache = new Map();
|
|
10
|
-
/**
|
|
11
|
-
* Compile CSS using PostCSS with the project's configuration
|
|
12
|
-
* Loads postcss.config.js from project root for proper plugin setup
|
|
13
|
-
* Falls back to minimal Tailwind-only config if no config file found
|
|
14
|
-
*/ async function compileCss(css, filePath) {
|
|
15
|
-
try {
|
|
16
|
-
// Dynamic import to use consumer's PostCSS installation
|
|
17
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
-
let postcss;
|
|
19
|
-
try {
|
|
20
|
-
postcss = (await import(/* webpackIgnore: true */ 'postcss')).default;
|
|
21
|
-
} catch {
|
|
22
|
-
console.warn('[payload-puck] PostCSS not found. CSS will not be processed. Install postcss as a dependency.');
|
|
23
|
-
return css;
|
|
24
|
-
}
|
|
25
|
-
// Try to load the project's postcss.config.js using postcss-load-config
|
|
26
|
-
// This ensures all plugins (typography, etc.) are properly loaded
|
|
27
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
28
|
-
let processor;
|
|
29
|
-
let usedProjectConfig = false;
|
|
30
|
-
try {
|
|
31
|
-
// Dynamic import of postcss-load-config (optional peer dependency)
|
|
32
|
-
// This package is commonly installed alongside PostCSS
|
|
33
|
-
const loadConfigModule = await import(/* webpackIgnore: true */ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
34
|
-
// @ts-ignore - optional dependency may not have types
|
|
35
|
-
'postcss-load-config');
|
|
36
|
-
const postcssLoadConfig = loadConfigModule.default;
|
|
37
|
-
// Load config from project root (where postcss.config.js lives)
|
|
38
|
-
const { plugins } = await postcssLoadConfig({}, process.cwd());
|
|
39
|
-
processor = postcss(plugins);
|
|
40
|
-
usedProjectConfig = true;
|
|
41
|
-
} catch {
|
|
42
|
-
// postcss-load-config not available or no config found - this is fine
|
|
43
|
-
// Fall back to direct Tailwind import silently
|
|
44
|
-
// Try Tailwind v4 first (@tailwindcss/postcss)
|
|
45
|
-
try {
|
|
46
|
-
const tailwindcss = (await import(/* webpackIgnore: true */ '@tailwindcss/postcss')).default;
|
|
47
|
-
processor = postcss([
|
|
48
|
-
tailwindcss
|
|
49
|
-
]);
|
|
50
|
-
} catch {
|
|
51
|
-
// Fall back to Tailwind v3 (tailwindcss)
|
|
52
|
-
try {
|
|
53
|
-
const tailwindcss = (await import(/* webpackIgnore: true */ 'tailwindcss')).default;
|
|
54
|
-
processor = postcss([
|
|
55
|
-
tailwindcss
|
|
56
|
-
]);
|
|
57
|
-
} catch {
|
|
58
|
-
// No Tailwind available - just return the CSS as-is
|
|
59
|
-
console.warn('[payload-puck] No Tailwind CSS installation found. CSS will not be processed.');
|
|
60
|
-
return css;
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
const result = await processor.process(css, {
|
|
65
|
-
from: filePath
|
|
66
|
-
});
|
|
67
|
-
return result.css;
|
|
68
|
-
} catch (error) {
|
|
69
|
-
console.error('[payload-puck] CSS compilation error:', error);
|
|
70
|
-
throw error;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Creates a handler that serves compiled CSS for the editor iframe
|
|
75
|
-
*
|
|
76
|
-
* @param cssFilePath - Path to CSS file relative to project root
|
|
77
|
-
* @returns PayloadHandler that serves compiled CSS
|
|
78
|
-
*/ export function createStylesHandler(cssFilePath) {
|
|
79
|
-
return async (req)=>{
|
|
80
|
-
try {
|
|
81
|
-
const fullPath = join(process.cwd(), cssFilePath);
|
|
82
|
-
// Check if file exists
|
|
83
|
-
if (!existsSync(fullPath)) {
|
|
84
|
-
console.error(`[payload-puck] CSS file not found: ${fullPath}`);
|
|
85
|
-
return new Response(`/* CSS file not found: ${cssFilePath} */`, {
|
|
86
|
-
status: 404,
|
|
87
|
-
headers: {
|
|
88
|
-
'Content-Type': 'text/css'
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
}
|
|
92
|
-
// Get file modification time for cache invalidation
|
|
93
|
-
const stats = statSync(fullPath);
|
|
94
|
-
const mtime = stats.mtimeMs;
|
|
95
|
-
// ETag derived from mtime - changes whenever the source file changes,
|
|
96
|
-
// whether from a dev-mode edit or a version upgrade recompiling output.
|
|
97
|
-
const etag = `"${mtime}"`;
|
|
98
|
-
// If the browser's cached copy is still fresh, tell it so without
|
|
99
|
-
// doing any file read/compilation work.
|
|
100
|
-
const ifNoneMatch = req.headers?.get('if-none-match');
|
|
101
|
-
if (ifNoneMatch === etag) {
|
|
102
|
-
return new Response(null, {
|
|
103
|
-
status: 304,
|
|
104
|
-
headers: {
|
|
105
|
-
ETag: etag,
|
|
106
|
-
'Cache-Control': 'no-cache'
|
|
107
|
-
}
|
|
108
|
-
});
|
|
109
|
-
}
|
|
110
|
-
// Check cache
|
|
111
|
-
const cached = cssCache.get(cssFilePath);
|
|
112
|
-
if (cached && cached.mtime === mtime) {
|
|
113
|
-
return new Response(cached.css, {
|
|
114
|
-
headers: {
|
|
115
|
-
'Content-Type': 'text/css',
|
|
116
|
-
'Cache-Control': 'no-cache',
|
|
117
|
-
ETag: etag,
|
|
118
|
-
'Last-Modified': new Date(mtime).toUTCString(),
|
|
119
|
-
'X-Puck-Cache': 'hit'
|
|
120
|
-
}
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
// Read and compile CSS
|
|
124
|
-
const rawCss = readFileSync(fullPath, 'utf-8');
|
|
125
|
-
const compiledCss = await compileCss(rawCss, fullPath);
|
|
126
|
-
// Update cache
|
|
127
|
-
cssCache.set(cssFilePath, {
|
|
128
|
-
css: compiledCss,
|
|
129
|
-
mtime
|
|
130
|
-
});
|
|
131
|
-
return new Response(compiledCss, {
|
|
132
|
-
headers: {
|
|
133
|
-
'Content-Type': 'text/css',
|
|
134
|
-
'Cache-Control': 'no-cache',
|
|
135
|
-
ETag: etag,
|
|
136
|
-
'Last-Modified': new Date(mtime).toUTCString(),
|
|
137
|
-
'X-Puck-Cache': 'miss'
|
|
138
|
-
}
|
|
139
|
-
});
|
|
140
|
-
} catch (error) {
|
|
141
|
-
console.error('[payload-puck] Styles endpoint error:', error);
|
|
142
|
-
return new Response(`/* Error compiling CSS: ${error instanceof Error ? error.message : 'Unknown error'} */`, {
|
|
143
|
-
status: 500,
|
|
144
|
-
headers: {
|
|
145
|
-
'Content-Type': 'text/css'
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
};
|
|
150
|
-
}
|
|
151
|
-
/**
|
|
152
|
-
* Helper constant for the styles endpoint URL
|
|
153
|
-
*/ export const PUCK_STYLES_ENDPOINT = '/api/puck/styles';
|
package/dist/next/index.d.ts
DELETED
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Next.js Configuration Wrapper for Puck CSS
|
|
3
|
-
*
|
|
4
|
-
* Compiles CSS at build time using the project's PostCSS/Tailwind configuration.
|
|
5
|
-
* This ensures the editor iframe styles work in production (Vercel, etc.) where
|
|
6
|
-
* source files aren't available at runtime.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```js
|
|
10
|
-
* // next.config.js
|
|
11
|
-
* import { withPuckCSS } from '@delmaredigital/payload-puck/next'
|
|
12
|
-
* import { withPayload } from '@payloadcms/next/withPayload'
|
|
13
|
-
*
|
|
14
|
-
* export default withPuckCSS({
|
|
15
|
-
* cssInput: 'src/app/(frontend)/globals.css',
|
|
16
|
-
* })(withPayload(nextConfig))
|
|
17
|
-
* ```
|
|
18
|
-
*/
|
|
19
|
-
import type { NextConfig } from 'next';
|
|
20
|
-
/**
|
|
21
|
-
* Options for the withPuckCSS wrapper
|
|
22
|
-
*/
|
|
23
|
-
export interface WithPuckCSSOptions {
|
|
24
|
-
/**
|
|
25
|
-
* Path to the source CSS file (relative to project root)
|
|
26
|
-
* @example 'src/app/(frontend)/globals.css'
|
|
27
|
-
*/
|
|
28
|
-
cssInput: string;
|
|
29
|
-
/**
|
|
30
|
-
* Output path for compiled CSS (relative to public/)
|
|
31
|
-
* @default 'puck-editor-styles.css'
|
|
32
|
-
*/
|
|
33
|
-
cssOutput?: string;
|
|
34
|
-
/**
|
|
35
|
-
* Whether to skip compilation in development
|
|
36
|
-
* @default true
|
|
37
|
-
*/
|
|
38
|
-
skipInDev?: boolean;
|
|
39
|
-
}
|
|
40
|
-
/**
|
|
41
|
-
* Default output filename for compiled CSS
|
|
42
|
-
*/
|
|
43
|
-
export declare const PUCK_CSS_OUTPUT_DEFAULT = "puck-editor-styles.css";
|
|
44
|
-
/**
|
|
45
|
-
* Next.js configuration wrapper that compiles Puck editor CSS at build time
|
|
46
|
-
*
|
|
47
|
-
* @param options - Configuration options
|
|
48
|
-
* @returns A function that wraps your Next.js config
|
|
49
|
-
*
|
|
50
|
-
* @example
|
|
51
|
-
* ```js
|
|
52
|
-
* import { withPuckCSS } from '@delmaredigital/payload-puck/next'
|
|
53
|
-
*
|
|
54
|
-
* export default withPuckCSS({
|
|
55
|
-
* cssInput: 'src/app/(frontend)/globals.css',
|
|
56
|
-
* })(nextConfig)
|
|
57
|
-
* ```
|
|
58
|
-
*/
|
|
59
|
-
export declare function withPuckCSS(options: WithPuckCSSOptions): (nextConfig: NextConfig) => NextConfig;
|
|
60
|
-
/**
|
|
61
|
-
* Get the URL path for the compiled CSS file
|
|
62
|
-
* Use this in your plugin configuration
|
|
63
|
-
*/
|
|
64
|
-
export declare function getPuckCSSPath(cssOutput?: string): string;
|
package/dist/next/index.js
DELETED
|
@@ -1,155 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Next.js Configuration Wrapper for Puck CSS
|
|
3
|
-
*
|
|
4
|
-
* Compiles CSS at build time using the project's PostCSS/Tailwind configuration.
|
|
5
|
-
* This ensures the editor iframe styles work in production (Vercel, etc.) where
|
|
6
|
-
* source files aren't available at runtime.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```js
|
|
10
|
-
* // next.config.js
|
|
11
|
-
* import { withPuckCSS } from '@delmaredigital/payload-puck/next'
|
|
12
|
-
* import { withPayload } from '@payloadcms/next/withPayload'
|
|
13
|
-
*
|
|
14
|
-
* export default withPuckCSS({
|
|
15
|
-
* cssInput: 'src/app/(frontend)/globals.css',
|
|
16
|
-
* })(withPayload(nextConfig))
|
|
17
|
-
* ```
|
|
18
|
-
*/ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'fs';
|
|
19
|
-
import { dirname, resolve } from 'path';
|
|
20
|
-
/**
|
|
21
|
-
* Default output filename for compiled CSS
|
|
22
|
-
*/ export const PUCK_CSS_OUTPUT_DEFAULT = 'puck-editor-styles.css';
|
|
23
|
-
/**
|
|
24
|
-
* Compile CSS using PostCSS with the project's configuration
|
|
25
|
-
*/ async function compileCss(css, filePath) {
|
|
26
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
-
let postcss;
|
|
28
|
-
try {
|
|
29
|
-
postcss = (await import('postcss')).default;
|
|
30
|
-
} catch {
|
|
31
|
-
console.warn('[payload-puck] PostCSS not found. CSS will not be compiled.');
|
|
32
|
-
return css;
|
|
33
|
-
}
|
|
34
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
35
|
-
let processor;
|
|
36
|
-
try {
|
|
37
|
-
// Try to load project's postcss.config.js
|
|
38
|
-
const loadConfigModule = await import('postcss-load-config');
|
|
39
|
-
const postcssLoadConfig = loadConfigModule.default;
|
|
40
|
-
const { plugins } = await postcssLoadConfig({}, process.cwd());
|
|
41
|
-
processor = postcss(plugins);
|
|
42
|
-
} catch {
|
|
43
|
-
// Fall back to direct Tailwind import
|
|
44
|
-
try {
|
|
45
|
-
const tailwindcss = (await import('@tailwindcss/postcss')).default;
|
|
46
|
-
processor = postcss([
|
|
47
|
-
tailwindcss
|
|
48
|
-
]);
|
|
49
|
-
} catch {
|
|
50
|
-
try {
|
|
51
|
-
const tailwindcss = (await import('tailwindcss')).default;
|
|
52
|
-
processor = postcss([
|
|
53
|
-
tailwindcss
|
|
54
|
-
]);
|
|
55
|
-
} catch {
|
|
56
|
-
console.warn('[payload-puck] No Tailwind CSS found. CSS will not be compiled.');
|
|
57
|
-
return css;
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
const result = await processor.process(css, {
|
|
62
|
-
from: filePath
|
|
63
|
-
});
|
|
64
|
-
return result.css;
|
|
65
|
-
}
|
|
66
|
-
/**
|
|
67
|
-
* Webpack plugin that compiles CSS at build time
|
|
68
|
-
*/ class PuckCSSWebpackPlugin {
|
|
69
|
-
options;
|
|
70
|
-
compiled = false;
|
|
71
|
-
constructor(options){
|
|
72
|
-
this.options = options;
|
|
73
|
-
}
|
|
74
|
-
apply(compiler) {
|
|
75
|
-
compiler.hooks.beforeCompile.tapPromise('PuckCSSWebpackPlugin', async ()=>{
|
|
76
|
-
// Only compile once per build
|
|
77
|
-
if (this.compiled) return;
|
|
78
|
-
this.compiled = true;
|
|
79
|
-
const { cssInput, cssOutput, skipInDev } = this.options;
|
|
80
|
-
// Skip in development if configured
|
|
81
|
-
if (skipInDev && process.env.NODE_ENV === 'development') {
|
|
82
|
-
console.log('[payload-puck] Skipping CSS compilation in development');
|
|
83
|
-
return;
|
|
84
|
-
}
|
|
85
|
-
const inputPath = resolve(process.cwd(), cssInput);
|
|
86
|
-
const outputPath = resolve(process.cwd(), 'public', cssOutput);
|
|
87
|
-
// Check if source file exists
|
|
88
|
-
if (!existsSync(inputPath)) {
|
|
89
|
-
console.error(`[payload-puck] CSS source file not found: ${inputPath}`);
|
|
90
|
-
return;
|
|
91
|
-
}
|
|
92
|
-
try {
|
|
93
|
-
console.log(`[payload-puck] Compiling CSS: ${cssInput} -> public/${cssOutput}`);
|
|
94
|
-
// Read source CSS
|
|
95
|
-
const rawCss = readFileSync(inputPath, 'utf-8');
|
|
96
|
-
// Compile with PostCSS/Tailwind
|
|
97
|
-
const compiledCss = await compileCss(rawCss, inputPath);
|
|
98
|
-
// Ensure public directory exists
|
|
99
|
-
const outputDir = dirname(outputPath);
|
|
100
|
-
if (!existsSync(outputDir)) {
|
|
101
|
-
mkdirSync(outputDir, {
|
|
102
|
-
recursive: true
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
// Write compiled CSS
|
|
106
|
-
writeFileSync(outputPath, compiledCss, 'utf-8');
|
|
107
|
-
console.log(`[payload-puck] CSS compiled successfully (${(compiledCss.length / 1024).toFixed(1)}KB)`);
|
|
108
|
-
} catch (error) {
|
|
109
|
-
console.error('[payload-puck] CSS compilation failed:', error);
|
|
110
|
-
}
|
|
111
|
-
});
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Next.js configuration wrapper that compiles Puck editor CSS at build time
|
|
116
|
-
*
|
|
117
|
-
* @param options - Configuration options
|
|
118
|
-
* @returns A function that wraps your Next.js config
|
|
119
|
-
*
|
|
120
|
-
* @example
|
|
121
|
-
* ```js
|
|
122
|
-
* import { withPuckCSS } from '@delmaredigital/payload-puck/next'
|
|
123
|
-
*
|
|
124
|
-
* export default withPuckCSS({
|
|
125
|
-
* cssInput: 'src/app/(frontend)/globals.css',
|
|
126
|
-
* })(nextConfig)
|
|
127
|
-
* ```
|
|
128
|
-
*/ export function withPuckCSS(options) {
|
|
129
|
-
const resolvedOptions = {
|
|
130
|
-
cssInput: options.cssInput,
|
|
131
|
-
cssOutput: options.cssOutput ?? PUCK_CSS_OUTPUT_DEFAULT,
|
|
132
|
-
skipInDev: options.skipInDev ?? true
|
|
133
|
-
};
|
|
134
|
-
return (nextConfig)=>{
|
|
135
|
-
return {
|
|
136
|
-
...nextConfig,
|
|
137
|
-
webpack: (webpackConfig, context)=>{
|
|
138
|
-
// Add our CSS compilation plugin
|
|
139
|
-
webpackConfig.plugins = webpackConfig.plugins || [];
|
|
140
|
-
webpackConfig.plugins.push(new PuckCSSWebpackPlugin(resolvedOptions));
|
|
141
|
-
// Call existing webpack config if present
|
|
142
|
-
if (typeof nextConfig.webpack === 'function') {
|
|
143
|
-
return nextConfig.webpack(webpackConfig, context);
|
|
144
|
-
}
|
|
145
|
-
return webpackConfig;
|
|
146
|
-
}
|
|
147
|
-
};
|
|
148
|
-
};
|
|
149
|
-
}
|
|
150
|
-
/**
|
|
151
|
-
* Get the URL path for the compiled CSS file
|
|
152
|
-
* Use this in your plugin configuration
|
|
153
|
-
*/ export function getPuckCSSPath(cssOutput) {
|
|
154
|
-
return `/${cssOutput ?? PUCK_CSS_OUTPUT_DEFAULT}`;
|
|
155
|
-
}
|