nextjs-cms 0.9.41 → 0.10.0

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.
Files changed (56) hide show
  1. package/dist/api/actions/pages.d.ts +4 -3
  2. package/dist/api/actions/pages.d.ts.map +1 -1
  3. package/dist/api/actions/pages.js +11 -4
  4. package/dist/api/trpc/root.d.ts +4 -3
  5. package/dist/api/trpc/root.d.ts.map +1 -1
  6. package/dist/api/trpc/routers/config.d.ts.map +1 -1
  7. package/dist/api/trpc/routers/hasItemsSection.d.ts +1 -0
  8. package/dist/api/trpc/routers/hasItemsSection.d.ts.map +1 -1
  9. package/dist/api/trpc/routers/navigation.d.ts +3 -3
  10. package/dist/api/trpc/server.d.ts +12 -9
  11. package/dist/api/trpc/server.d.ts.map +1 -1
  12. package/dist/cli/lib/update-sections.d.ts.map +1 -1
  13. package/dist/cli/lib/update-sections.js +19 -0
  14. package/dist/core/config/config-loader.d.ts +25 -6
  15. package/dist/core/config/config-loader.d.ts.map +1 -1
  16. package/dist/core/config/config-loader.js +9 -13
  17. package/dist/core/fields/photo.d.ts +80 -8
  18. package/dist/core/fields/photo.d.ts.map +1 -1
  19. package/dist/core/fields/photo.js +120 -31
  20. package/dist/core/fields/richText.d.ts +162 -42
  21. package/dist/core/fields/richText.d.ts.map +1 -1
  22. package/dist/core/fields/richText.js +135 -35
  23. package/dist/core/fields/select.d.ts +1 -1
  24. package/dist/core/fields/select.d.ts.map +1 -1
  25. package/dist/core/fields/select.js +18 -2
  26. package/dist/core/fields/selectMultiple.d.ts.map +1 -1
  27. package/dist/core/fields/selectMultiple.js +9 -0
  28. package/dist/core/helpers/background.d.ts +18 -0
  29. package/dist/core/helpers/background.d.ts.map +1 -0
  30. package/dist/core/helpers/background.js +18 -0
  31. package/dist/core/helpers/index.d.ts +5 -1
  32. package/dist/core/helpers/index.d.ts.map +1 -1
  33. package/dist/core/helpers/index.js +3 -1
  34. package/dist/core/helpers/watermark.d.ts +96 -0
  35. package/dist/core/helpers/watermark.d.ts.map +1 -0
  36. package/dist/core/helpers/watermark.js +61 -0
  37. package/dist/core/sections/category.d.ts +78 -42
  38. package/dist/core/sections/category.d.ts.map +1 -1
  39. package/dist/core/sections/hasItems.d.ts +132 -48
  40. package/dist/core/sections/hasItems.d.ts.map +1 -1
  41. package/dist/core/sections/section.d.ts +62 -25
  42. package/dist/core/sections/section.d.ts.map +1 -1
  43. package/dist/core/sections/section.js +2 -2
  44. package/dist/core/sections/simple.d.ts +44 -8
  45. package/dist/core/sections/simple.d.ts.map +1 -1
  46. package/dist/core/submit/gallery-order.d.ts +34 -0
  47. package/dist/core/submit/gallery-order.d.ts.map +1 -0
  48. package/dist/core/submit/gallery-order.js +50 -0
  49. package/dist/core/submit/submit.d.ts +8 -0
  50. package/dist/core/submit/submit.d.ts.map +1 -1
  51. package/dist/core/submit/submit.js +63 -3
  52. package/dist/core/types/index.d.ts +1 -0
  53. package/dist/core/types/index.d.ts.map +1 -1
  54. package/dist/translations/client.d.ts +4 -4
  55. package/dist/translations/server.d.ts +4 -4
  56. package/package.json +3 -3
@@ -1 +1 @@
1
- {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../../src/core/config/config-loader.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../../src/core/config/config-loader.ts"],"names":[],"mappings":"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"}
@@ -1,12 +1,11 @@
1
+ import chalk from 'chalk';
2
+ import * as z from 'zod';
3
+ import { setConfigDicts } from '../../translations/dict-store.js';
4
+ import { watermarkConfigSchema } from '../helpers/index.js';
5
+ import { getConfigImportVersion, loadConfigModule } from './loader.js';
1
6
  if (typeof window !== 'undefined') {
2
7
  throw new Error('This module can only run on the server');
3
8
  }
4
- // import 'server-only'
5
- // import chalk from 'chalk'
6
- import * as z from 'zod';
7
- import { loadConfigModule, getConfigImportVersion } from './loader.js';
8
- import { setConfigDicts } from '../../translations/dict-store.js';
9
- import chalk from 'chalk';
10
9
  /** Locale codes for which we ship dictionaries in core. */
11
10
  export const AVAILABLE_I18N_LANGUAGES = ['en'];
12
11
  // 1. Define config schema
@@ -135,9 +134,10 @@ const cmsConfigSchema = z.object({
135
134
  })
136
135
  .optional(),
137
136
  /**
138
- * Global images watermark configuration
137
+ * Global images watermark configuration.
138
+ * `false` = off; object = watermark asset + defaults. See core/helpers/watermark.
139
139
  */
140
- watermark: z.boolean().optional(),
140
+ watermark: watermarkConfigSchema.optional(),
141
141
  })
142
142
  .optional(),
143
143
  })
@@ -315,11 +315,7 @@ function isPluginConfigWithOverrides(input) {
315
315
  return typeof input === 'object' && input !== null && 'plugin' in input;
316
316
  }
317
317
  function isPluginDescriptor(input) {
318
- return (typeof input === 'object' &&
319
- input !== null &&
320
- 'package' in input &&
321
- 'title' in input &&
322
- !('plugin' in input));
318
+ return typeof input === 'object' && input !== null && 'package' in input && 'title' in input && !('plugin' in input);
323
319
  }
324
320
  function normalizePluginConfigInputs(plugins) {
325
321
  return plugins?.map((entry) => {
@@ -1,6 +1,8 @@
1
+ import sharp from 'sharp';
2
+ import * as z from 'zod';
3
+ import type { ResolvedWatermark, WatermarkConfig, WatermarkPosition } from '../helpers/index.js';
1
4
  import type { BaseFieldConfig } from './field.js';
2
5
  import { entityKind } from '../helpers/index.js';
3
- import * as z from 'zod';
4
6
  import { FileField } from './fileField.js';
5
7
  declare const sizeSchema: z.ZodUnion<readonly [z.ZodObject<{
6
8
  width: z.ZodNumber;
@@ -29,9 +31,43 @@ declare const sizeSchema: z.ZodUnion<readonly [z.ZodObject<{
29
31
  }, z.core.$strict>>;
30
32
  }, z.core.$strict>], "fit">]>;
31
33
  type SizeConfig = z.infer<typeof sizeSchema>;
34
+ /**
35
+ * Watermark position → sharp gravity. Kept here (server-only) with the rest of the sharp logic;
36
+ * the pure config schema lives in core/helpers/watermark.
37
+ */
38
+ export declare const positionToGravity: Record<WatermarkPosition, string>;
39
+ /**
40
+ * Load and validate a watermark image once, caching by path. Fail-fast: throws a clear
41
+ * error if the file cannot be read or decoded.
42
+ */
43
+ export declare function loadWatermarkSource(imagePath: string): Promise<Buffer>;
44
+ /**
45
+ * Build a sharp composite overlay for a resolved watermark against a base image of `outputWidth`.
46
+ * Resizes the mark to `size * outputWidth`, applies opacity, and (for non-tiled marks with a
47
+ * margin) pads a transparent border so `gravity` insets the mark from the edge/corner.
48
+ */
49
+ export declare function buildOverlay(watermark: ResolvedWatermark, outputWidth: number): Promise<sharp.OverlayOptions>;
32
50
  declare const configSchema: z.ZodObject<{
33
- /** Whether to add watermark to images */
34
- watermark: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
51
+ /** Watermark config: false = off, or a watermark object. See core/helpers/watermark. */
52
+ watermark: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
53
+ imagePath: z.ZodString;
54
+ position: z.ZodOptional<z.ZodEnum<{
55
+ "top-left": "top-left";
56
+ top: "top";
57
+ "top-right": "top-right";
58
+ left: "left";
59
+ center: "center";
60
+ right: "right";
61
+ "bottom-left": "bottom-left";
62
+ bottom: "bottom";
63
+ "bottom-right": "bottom-right";
64
+ }>>;
65
+ size: z.ZodOptional<z.ZodNumber>;
66
+ opacity: z.ZodOptional<z.ZodNumber>;
67
+ margin: z.ZodOptional<z.ZodNumber>;
68
+ tile: z.ZodOptional<z.ZodBoolean>;
69
+ applyToThumbnail: z.ZodOptional<z.ZodBoolean>;
70
+ }, z.core.$strict>]>>;
35
71
  blurPlaceholder: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
36
72
  size: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
37
73
  width: z.ZodNumber;
@@ -118,7 +154,7 @@ declare const configSchema: z.ZodObject<{
118
154
  type Config = z.infer<typeof configSchema>;
119
155
  export declare class PhotoField extends FileField<'photo', Config> {
120
156
  static readonly [entityKind]: string;
121
- readonly watermark: boolean | null | undefined;
157
+ readonly watermark: WatermarkConfig | undefined;
122
158
  readonly blurPlaceholder: boolean | null | undefined;
123
159
  readonly size: SizeConfig | undefined;
124
160
  readonly maxFileSize: {
@@ -225,8 +261,26 @@ export declare class PhotoField extends FileField<'photo', Config> {
225
261
  }
226
262
  export type PhotoFieldClientConfig = ReturnType<PhotoField['exportForClient']>;
227
263
  declare const optionsSchema: z.ZodObject<{
228
- /** Whether to add watermark to images */
229
- watermark: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
264
+ /** Watermark config: false = off, or a watermark object. See core/helpers/watermark. */
265
+ watermark: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
266
+ imagePath: z.ZodString;
267
+ position: z.ZodOptional<z.ZodEnum<{
268
+ "top-left": "top-left";
269
+ top: "top";
270
+ "top-right": "top-right";
271
+ left: "left";
272
+ center: "center";
273
+ right: "right";
274
+ "bottom-left": "bottom-left";
275
+ bottom: "bottom";
276
+ "bottom-right": "bottom-right";
277
+ }>>;
278
+ size: z.ZodOptional<z.ZodNumber>;
279
+ opacity: z.ZodOptional<z.ZodNumber>;
280
+ margin: z.ZodOptional<z.ZodNumber>;
281
+ tile: z.ZodOptional<z.ZodBoolean>;
282
+ applyToThumbnail: z.ZodOptional<z.ZodBoolean>;
283
+ }, z.core.$strict>]>>;
230
284
  blurPlaceholder: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
231
285
  size: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
232
286
  width: z.ZodNumber;
@@ -321,8 +375,26 @@ declare const optionsSchema: z.ZodObject<{
321
375
  declare const photoFieldConfigSchema: z.ZodObject<{
322
376
  type: z.ZodLiteral<"photo">;
323
377
  build: z.ZodFunction<z.core.$ZodFunctionArgs, z.ZodCustom<PhotoField, PhotoField>>;
324
- /** Whether to add watermark to images */
325
- watermark: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
378
+ /** Watermark config: false = off, or a watermark object. See core/helpers/watermark. */
379
+ watermark: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<false>, z.ZodObject<{
380
+ imagePath: z.ZodString;
381
+ position: z.ZodOptional<z.ZodEnum<{
382
+ "top-left": "top-left";
383
+ top: "top";
384
+ "top-right": "top-right";
385
+ left: "left";
386
+ center: "center";
387
+ right: "right";
388
+ "bottom-left": "bottom-left";
389
+ bottom: "bottom";
390
+ "bottom-right": "bottom-right";
391
+ }>>;
392
+ size: z.ZodOptional<z.ZodNumber>;
393
+ opacity: z.ZodOptional<z.ZodNumber>;
394
+ margin: z.ZodOptional<z.ZodNumber>;
395
+ tile: z.ZodOptional<z.ZodBoolean>;
396
+ applyToThumbnail: z.ZodOptional<z.ZodBoolean>;
397
+ }, z.core.$strict>]>>;
326
398
  blurPlaceholder: z.ZodOptional<z.ZodNullable<z.ZodBoolean>>;
327
399
  size: z.ZodOptional<z.ZodUnion<readonly [z.ZodObject<{
328
400
  width: z.ZodNumber;
@@ -1 +1 @@
1
- {"version":3,"file":"photo.d.ts","sourceRoot":"","sources":["../../../src/core/fields/photo.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"photo.d.ts","sourceRoot":"","sources":["../../../src/core/fields/photo.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,KAAK,CAAC,MAAM,KAAK,CAAA;AAExB,OAAO,KAAK,EAAE,iBAAiB,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAChG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAIjD,OAAO,EAAoB,UAAU,EAA2C,MAAM,qBAAqB,CAAA;AAE3G,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAkC1C,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;IAPZ;;;OAGG;;;;;;;6BAI0G,CAAA;AAEjH,KAAK,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,UAAU,CAAC,CAAA;AAkC5C;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,EAAE,MAAM,CAU/D,CAAA;AAKD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAiBtE;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,SAAS,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,cAAc,CAAC,CAkCnH;AAED,QAAA,MAAM,YAAY;IACd,wFAAwF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA/HxF;;;WAGG;;;;;;;;;;;;;;;;;;QAyBC;;;WAGG;;;;;;;;IAqGP;;;;;;;OAOG;;;;;;;;IAEH;;;;;;;OAOG;;;;;;;IAEH;;;OAGG;;kBAEL,CAAA;AAEF,KAAK,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAA;AAE1C,qBAAa,UAAW,SAAQ,SAAS,CAAC,OAAO,EAAE,MAAM,CAAC;IACtD,gBAAyB,CAAC,UAAU,CAAC,EAAE,MAAM,CAAe;IAC5D,QAAQ,CAAC,SAAS,EAAE,eAAe,GAAG,SAAS,CAAA;IAC/C,QAAQ,CAAC,eAAe,EAAE,OAAO,GAAG,IAAI,GAAG,SAAS,CAAA;IACpD,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,SAAS,CAAA;IACrC,QAAQ,CAAC,WAAW,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,IAAI,GAAG,IAAI,CAAA;KAAE,CAAA;IACzD,QAAQ,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;IAC3B,QAAQ,CAAC,UAAU,EAAE,MAAM,EAAE,CAAA;IAC7B,OAAO,CAAC,UAAU,CAAyC;IAC3D,yFAAyF;IACzF,OAAO,CAAC,gBAAgB,CAAyC;IACjE,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAA;IAEjC;;;OAGG;IACH,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,WAAW,CAAqC;IACxD,OAAO,CAAC,OAAO,CAAoB;IACnC,OAAO,CAAC,kBAAkB,CAAU;gBAExB,MAAM,EAAE,eAAe,CAAC,MAAM,CAAC,EAAE,IAAI,CAAC,EAAE,IAAI;IAoCxD;;;;OAIG;YACW,YAAY;IAkBX,KAAK;IAOJ,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;kBAnFD,MAAM;kBAAQ,IAAI,GAAG,IAAI;;;;;;;;;;;;;;IAmGvD;;OAEG;IACG,WAAW;IAqGK,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzC,kBAAkB,IAAI,OAAO,CAAC,IAAI,CAAC;IAcnC,mBAAmB,CAAC,aAAa,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOpG;;OAEG;IACH,QAAQ,IAAI,MAAM;IAIX,WAAW,CAAC,KAAK,EAAE,MAAM;IAIvB,QAAQ,CAAC,KAAK,EAAE,GAAG;IAQ5B,OAAO,CAAC,IAAI,EAAE,IAAI;IAKlB,aAAa;IAab;;OAEG;IACG,oBAAoB;CA6J7B;AAED,MAAM,MAAM,sBAAsB,GAAG,UAAU,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAA;AAE9E,QAAA,MAAM,aAAa;IApdf,wFAAwF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA/HxF;;;WAGG;;;;;;;;;;;;;;;;;;QAyBC;;;WAGG;;;;;;;;IAqGP;;;;;;;OAOG;;;;;;;;IAEH;;;;;;;OAOG;;;;;;;IAEH;;;OAGG;;;;;;;;;;kBA6bL,CAAA;AAEF,QAAA,MAAM,sBAAsB;;;IAzdxB,wFAAwF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QA/HxF;;;WAGG;;;;;;;;;;;;;;;;;;QAyBC;;;WAGG;;;;;;;;IAqGP;;;;;;;OAOG;;;;;;;;IAEH;;;;;;;OAOG;;;;;;;IAEH;;;OAGG;;;;;;;;;;kBAmcL,CAAA;AAEF;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,sBAAsB,CAAC,CAAA;AAErE;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,GAAG,gBAAgB,CAmBjF"}
@@ -1,22 +1,14 @@
1
- import { baseFieldConfigSchema } from './field.js';
2
- import { entityKind } from '../helpers/index.js';
3
- import * as z from 'zod';
4
- import sharp from 'sharp';
5
- import path from 'path';
6
1
  import fs from 'fs';
2
+ import path from 'path';
7
3
  import { customAlphabet } from 'nanoid';
8
- import { FileField } from './fileField.js';
4
+ import sharp from 'sharp';
5
+ import * as z from 'zod';
6
+ import getString from '../../translations/index.js';
9
7
  import { humanReadableFileSize } from '../../utils/index.js';
10
8
  import { getCMSConfig } from '../config/index.js';
11
- import getString from '../../translations/index.js';
12
- const backgroundSchema = z
13
- .strictObject({
14
- r: z.number().min(0).max(255).describe('Red channel (0-255)'),
15
- g: z.number().min(0).max(255).describe('Green channel (0-255)'),
16
- b: z.number().min(0).max(255).describe('Blue channel (0-255)'),
17
- alpha: z.number().min(0).max(1).describe('Alpha channel (0-1)'),
18
- })
19
- .describe('Background color for image padding (used with fit: contain)');
9
+ import { backgroundSchema, entityKind, resolveWatermark, watermarkConfigSchema } from '../helpers/index.js';
10
+ import { baseFieldConfigSchema } from './field.js';
11
+ import { FileField } from './fileField.js';
20
12
  /**
21
13
  * Size schema — discriminated union of three variants:
22
14
  * - strict: true — user must upload exact dimensions, no server resize
@@ -75,9 +67,85 @@ const maxFileSizeSchema = z.strictObject({
75
67
  size: z.number().describe('Maximum file size'),
76
68
  unit: z.enum(['kb', 'mb']).describe('Size unit'),
77
69
  });
70
+ /**
71
+ * Watermark position → sharp gravity. Kept here (server-only) with the rest of the sharp logic;
72
+ * the pure config schema lives in core/helpers/watermark.
73
+ */
74
+ export const positionToGravity = {
75
+ 'top-left': 'northwest',
76
+ top: 'north',
77
+ 'top-right': 'northeast',
78
+ left: 'west',
79
+ center: 'centre',
80
+ right: 'east',
81
+ 'bottom-left': 'southwest',
82
+ bottom: 'south',
83
+ 'bottom-right': 'southeast',
84
+ };
85
+ /** Cache of validated watermark source buffers, keyed by resolved absolute path. */
86
+ const watermarkSourceCache = new Map();
87
+ /**
88
+ * Load and validate a watermark image once, caching by path. Fail-fast: throws a clear
89
+ * error if the file cannot be read or decoded.
90
+ */
91
+ export function loadWatermarkSource(imagePath) {
92
+ const resolved = path.isAbsolute(imagePath) ? imagePath : path.join(process.cwd(), imagePath);
93
+ let cached = watermarkSourceCache.get(resolved);
94
+ if (!cached) {
95
+ cached = (async () => {
96
+ try {
97
+ const buffer = await fs.promises.readFile(resolved);
98
+ await sharp(buffer).metadata();
99
+ return buffer;
100
+ }
101
+ catch (error) {
102
+ watermarkSourceCache.delete(resolved);
103
+ throw new Error(`Watermark image could not be loaded: ${resolved} (${error.message})`);
104
+ }
105
+ })();
106
+ watermarkSourceCache.set(resolved, cached);
107
+ }
108
+ return cached;
109
+ }
110
+ /**
111
+ * Build a sharp composite overlay for a resolved watermark against a base image of `outputWidth`.
112
+ * Resizes the mark to `size * outputWidth`, applies opacity, and (for non-tiled marks with a
113
+ * margin) pads a transparent border so `gravity` insets the mark from the edge/corner.
114
+ */
115
+ export async function buildOverlay(watermark, outputWidth) {
116
+ const source = await loadWatermarkSource(watermark.imagePath);
117
+ const targetWidth = Math.max(1, Math.round(watermark.size * outputWidth));
118
+ let overlay = sharp(source).resize({ width: targetWidth });
119
+ // Apply opacity via the dest-in alpha trick: multiply the mark's alpha by `opacity`.
120
+ if (watermark.opacity < 1) {
121
+ overlay = overlay.ensureAlpha().composite([
122
+ {
123
+ input: Buffer.from([255, 255, 255, Math.round(watermark.opacity * 255)]),
124
+ raw: { width: 1, height: 1, channels: 4 },
125
+ tile: true,
126
+ blend: 'dest-in',
127
+ },
128
+ ]);
129
+ }
130
+ // Inset from edge/corner: pad the mark with a transparent margin, then let gravity place it flush.
131
+ if (!watermark.tile && watermark.margin > 0) {
132
+ overlay = overlay.extend({
133
+ top: watermark.margin,
134
+ bottom: watermark.margin,
135
+ left: watermark.margin,
136
+ right: watermark.margin,
137
+ background: { r: 0, g: 0, b: 0, alpha: 0 },
138
+ });
139
+ }
140
+ return {
141
+ input: await overlay.png().toBuffer(),
142
+ gravity: positionToGravity[watermark.position],
143
+ tile: watermark.tile,
144
+ };
145
+ }
78
146
  const configSchema = z.strictObject({
79
- /** Whether to add watermark to images */
80
- watermark: z.boolean().nullable().optional(),
147
+ /** Watermark config: false = off, or a watermark object. See core/helpers/watermark. */
148
+ watermark: watermarkConfigSchema.optional(),
81
149
  blurPlaceholder: z.boolean().nullable().optional(),
82
150
  size: sizeSchema.optional(),
83
151
  thumbnail: thumbnailSchema.optional(),
@@ -237,45 +305,66 @@ export class PhotoField extends FileField {
237
305
  * - fit: 'contain' -> pad with background to fill dimensions
238
306
  */
239
307
  const cmsImageQuality = cmsConfig.media.images.image.quality ?? 80;
308
+ /**
309
+ * Resolve the watermark once (field overrides gallery-resolved value overrides global).
310
+ * The overlay is sized against the final output width so it scales with the image.
311
+ */
312
+ const resolvedWatermark = resolveWatermark(this.watermark, cmsConfig.media.images.watermark);
313
+ const mainOutputWidth = this.size
314
+ ? this.size.width
315
+ : ((await this._sharpImage.clone().metadata()).width ?? 0);
316
+ const mainOverlay = resolvedWatermark && mainOutputWidth > 0 ? await buildOverlay(resolvedWatermark, mainOutputWidth) : null;
240
317
  if (this.size) {
241
318
  const quality = this.size.quality ?? cmsImageQuality;
242
319
  const outputPath = path.join(uploadsFolder, '.photos', this._folder, this.value);
243
320
  if ('strict' in this.size) {
244
321
  // Strict mode: exact dimensions already validated, just convert to webp
245
- await this._sharpImage.clone().webp({ quality }).toFile(outputPath);
322
+ let pipeline = this._sharpImage.clone();
323
+ if (mainOverlay)
324
+ pipeline = pipeline.composite([mainOverlay]);
325
+ await pipeline.webp({ quality }).toFile(outputPath);
246
326
  }
247
327
  else if (this.size.fit === 'cover') {
248
- await this._sharpImage
328
+ let pipeline = this._sharpImage
249
329
  .clone()
250
- .resize({ width: this.size.width, height: this.size.height, fit: 'cover' })
251
- .webp({ quality })
252
- .toFile(outputPath);
330
+ .resize({ width: this.size.width, height: this.size.height, fit: 'cover' });
331
+ if (mainOverlay)
332
+ pipeline = pipeline.composite([mainOverlay]);
333
+ await pipeline.webp({ quality }).toFile(outputPath);
253
334
  }
254
335
  else {
255
336
  // contain: pad with background
256
337
  const background = this.size.background ?? cmsBackground;
257
- await this._sharpImage
338
+ let pipeline = this._sharpImage
258
339
  .clone()
259
- .resize({ width: this.size.width, height: this.size.height, fit: 'contain', background })
260
- .webp({ quality })
261
- .toFile(outputPath);
340
+ .resize({ width: this.size.width, height: this.size.height, fit: 'contain', background });
341
+ if (mainOverlay)
342
+ pipeline = pipeline.composite([mainOverlay]);
343
+ await pipeline.webp({ quality }).toFile(outputPath);
262
344
  }
263
345
  }
264
346
  else {
265
- await this._sharpImage.clone().toFile(path.join(uploadsFolder, '.photos', this._folder, this.value));
347
+ let pipeline = this._sharpImage.clone();
348
+ if (mainOverlay)
349
+ pipeline = pipeline.composite([mainOverlay]);
350
+ await pipeline.toFile(path.join(uploadsFolder, '.photos', this._folder, this.value));
266
351
  }
267
352
  /**
268
353
  * Write a thumbnail
269
354
  */
270
355
  const thumbBackground = ('background' in thumbnail ? thumbnail.background : undefined) ?? cmsBackground;
271
- await this._sharpImage
272
- .clone()
273
- .resize({
356
+ const thumbOverlay = resolvedWatermark && resolvedWatermark.applyToThumbnail
357
+ ? await buildOverlay(resolvedWatermark, thumbnail.width)
358
+ : null;
359
+ let thumbPipeline = this._sharpImage.clone().resize({
274
360
  width: thumbnail.width,
275
361
  height: thumbnail.height,
276
362
  fit: thumbnail.fit,
277
363
  ...(thumbnail.fit === 'contain' ? { background: thumbBackground } : {}),
278
- })
364
+ });
365
+ if (thumbOverlay)
366
+ thumbPipeline = thumbPipeline.composite([thumbOverlay]);
367
+ await thumbPipeline
279
368
  .webp({
280
369
  quality: thumbnail.quality ?? cmsImageQuality,
281
370
  })