@actuate-media/cms-core 0.56.0 → 0.57.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 (48) hide show
  1. package/dist/__tests__/api/page-sections-routes.test.js +31 -0
  2. package/dist/__tests__/api/page-sections-routes.test.js.map +1 -1
  3. package/dist/api/handler-factory.d.ts.map +1 -1
  4. package/dist/api/handler-factory.js +2 -2
  5. package/dist/api/handler-factory.js.map +1 -1
  6. package/dist/api/handlers.js +4 -4
  7. package/dist/api/handlers.js.map +1 -1
  8. package/dist/config/types.d.ts +4 -4
  9. package/dist/fields/__tests__/presets.test.d.ts +2 -0
  10. package/dist/fields/__tests__/presets.test.d.ts.map +1 -0
  11. package/dist/fields/__tests__/presets.test.js +29 -0
  12. package/dist/fields/__tests__/presets.test.js.map +1 -0
  13. package/dist/fields/index.d.ts +1 -1
  14. package/dist/fields/index.d.ts.map +1 -1
  15. package/dist/fields/index.js +1 -1
  16. package/dist/fields/index.js.map +1 -1
  17. package/dist/fields/presets.d.ts +11 -0
  18. package/dist/fields/presets.d.ts.map +1 -1
  19. package/dist/fields/presets.js +20 -0
  20. package/dist/fields/presets.js.map +1 -1
  21. package/dist/index.d.ts +1 -1
  22. package/dist/index.d.ts.map +1 -1
  23. package/dist/index.js +1 -1
  24. package/dist/index.js.map +1 -1
  25. package/dist/sections/__tests__/sections.test.js +120 -2
  26. package/dist/sections/__tests__/sections.test.js.map +1 -1
  27. package/dist/sections/fields.d.ts +37 -0
  28. package/dist/sections/fields.d.ts.map +1 -0
  29. package/dist/sections/fields.js +50 -0
  30. package/dist/sections/fields.js.map +1 -0
  31. package/dist/sections/helpers.d.ts +59 -12
  32. package/dist/sections/helpers.d.ts.map +1 -1
  33. package/dist/sections/helpers.js +90 -28
  34. package/dist/sections/helpers.js.map +1 -1
  35. package/dist/sections/index.d.ts +3 -2
  36. package/dist/sections/index.d.ts.map +1 -1
  37. package/dist/sections/index.js +3 -2
  38. package/dist/sections/index.js.map +1 -1
  39. package/dist/sections/registry.d.ts +9 -1
  40. package/dist/sections/registry.d.ts.map +1 -1
  41. package/dist/sections/registry.js +14 -1
  42. package/dist/sections/registry.js.map +1 -1
  43. package/dist/sections/types.d.ts +26 -3
  44. package/dist/sections/types.d.ts.map +1 -1
  45. package/dist/sections/validate.d.ts.map +1 -1
  46. package/dist/sections/validate.js +51 -13
  47. package/dist/sections/validate.js.map +1 -1
  48. package/package.json +1 -1
@@ -13,6 +13,7 @@
13
13
  * ...`) without double-labelling.
14
14
  */
15
15
  import { getSectionType } from './registry.js';
16
+ import { resolveRepeaterField } from './fields.js';
16
17
  const URL_OK = /^(https?:\/\/|\/|#|mailto:|tel:)/i;
17
18
  function isBlank(v) {
18
19
  return v === undefined || v === null || (typeof v === 'string' && v.trim() === '');
@@ -43,6 +44,11 @@ export function validateSectionContent(sectionType, content, _settings) {
43
44
  }
44
45
  const data = content ?? {};
45
46
  for (const field of def.fields) {
47
+ const repeater = resolveRepeaterField(field);
48
+ if (repeater) {
49
+ validateRepeater(sectionType, field.key, repeater, data[field.key], errors, warnings);
50
+ continue;
51
+ }
46
52
  if (field.required && isBlank(data[field.key])) {
47
53
  errors.push({ sectionType, field: field.key, message: `"${field.label}" is required.` });
48
54
  }
@@ -70,23 +76,55 @@ export function validateSectionContent(sectionType, content, _settings) {
70
76
  message: 'image needs alt text for accessibility.',
71
77
  });
72
78
  }
73
- // Gallery images should each carry alt text (accessibility) — advisory so
74
- // it never blocks publish, but surfaced so it can be fixed.
75
- if (Array.isArray(data.images)) {
76
- const missingAlt = data.images.some((img) => {
77
- if (!img || typeof img !== 'object')
78
- return false;
79
- const row = img;
80
- return !isBlank(row.url) && isBlank(row.alt);
81
- });
82
- if (missingAlt) {
79
+ return { valid: errors.length === 0, errors, warnings };
80
+ }
81
+ /**
82
+ * Validate one repeater field's rows against its sub-field schema. Covers the
83
+ * generic `repeater` type and the `stats` / `gallery` shorthands (resolved to
84
+ * the same row model). Required sub-fields are hard errors; an image row
85
+ * missing alt text is an advisory warning (accessibility). `minRows` is
86
+ * advisory; exceeding `maxRows` is an error (the editor enforces the cap, so
87
+ * over-cap data only arrives via the API/agent).
88
+ */
89
+ function validateRepeater(sectionType, key, repeater, value, errors, warnings) {
90
+ const rows = Array.isArray(value) ? value : [];
91
+ const mediaField = repeater.fields.find((f) => f.type === 'media');
92
+ const altField = repeater.fields.find((f) => f.key === 'alt');
93
+ rows.forEach((raw, i) => {
94
+ if (!raw || typeof raw !== 'object')
95
+ return;
96
+ const row = raw;
97
+ for (const sub of repeater.fields) {
98
+ if (sub.required && isBlank(row[sub.key])) {
99
+ errors.push({
100
+ sectionType,
101
+ field: `${key}[${i}].${sub.key}`,
102
+ message: `"${sub.label}" is required in ${repeater.rowLabel} ${i + 1}.`,
103
+ });
104
+ }
105
+ }
106
+ // An image row with a set image but no alt text is an accessibility gap.
107
+ if (mediaField && altField && !isBlank(row[mediaField.key]) && isBlank(row[altField.key])) {
83
108
  warnings.push({
84
109
  sectionType,
85
- field: 'images',
86
- message: 'One or more gallery images are missing alt text for accessibility.',
110
+ field: `${key}[${i}].${altField.key}`,
111
+ message: `${repeater.rowLabel} ${i + 1} is missing alt text for accessibility.`,
87
112
  });
88
113
  }
114
+ });
115
+ if (typeof repeater.minRows === 'number' && rows.length < repeater.minRows) {
116
+ warnings.push({
117
+ sectionType,
118
+ field: key,
119
+ message: `Add at least ${repeater.minRows} ${repeater.rowLabel.toLowerCase()}(s).`,
120
+ });
121
+ }
122
+ if (typeof repeater.maxRows === 'number' && rows.length > repeater.maxRows) {
123
+ errors.push({
124
+ sectionType,
125
+ field: key,
126
+ message: `No more than ${repeater.maxRows} ${repeater.rowLabel.toLowerCase()}(s) are allowed.`,
127
+ });
89
128
  }
90
- return { valid: errors.length === 0, errors, warnings };
91
129
  }
92
130
  //# sourceMappingURL=validate.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/sections/validate.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validate.js","sourceRoot":"","sources":["../../src/sections/validate.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@actuate-media/cms-core",
3
- "version": "0.56.0",
3
+ "version": "0.57.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "https://github.com/actuate-media/actuatecms.git",