@squiz/dxp-cli-next 5.31.0-develop.4 → 5.31.0-develop.6

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 (34) hide show
  1. package/lib/page/layouts/deploy/deploy.js +44 -9
  2. package/lib/page/layouts/deploy/deploy.spec.js +110 -19
  3. package/lib/page/layouts/dev/dev.js +18 -4
  4. package/lib/page/layouts/dev/dev.spec.js +117 -8
  5. package/lib/page/layouts/validation/index.d.ts +2 -0
  6. package/lib/page/layouts/validation/index.js +5 -1
  7. package/lib/page/layouts/validation/property-consistency.d.ts +7 -0
  8. package/lib/page/layouts/validation/property-consistency.js +92 -0
  9. package/lib/page/layouts/validation/property-consistency.spec.d.ts +1 -0
  10. package/lib/page/layouts/validation/property-consistency.spec.js +305 -0
  11. package/lib/page/layouts/validation/validateLayoutFormat.d.ts +2 -0
  12. package/lib/page/layouts/validation/validateLayoutFormat.js +27 -0
  13. package/lib/page/layouts/validation/validateLayoutFormat.spec.d.ts +1 -0
  14. package/lib/page/layouts/validation/validateLayoutFormat.spec.js +42 -0
  15. package/lib/page/layouts/validation/zone-consistency.d.ts +1 -1
  16. package/lib/page/layouts/validation/zone-consistency.js +10 -9
  17. package/lib/page/layouts/validation/zone-consistency.spec.js +32 -34
  18. package/lib/page/utils/definitions.d.ts +347 -50
  19. package/lib/page/utils/definitions.js +103 -22
  20. package/lib/page/utils/definitions.spec.js +516 -267
  21. package/lib/page/utils/normalize.d.ts +8 -0
  22. package/lib/page/utils/normalize.js +61 -0
  23. package/lib/page/utils/normalize.spec.d.ts +1 -0
  24. package/lib/page/utils/normalize.spec.js +315 -0
  25. package/lib/page/utils/parse-args.d.ts +20 -4
  26. package/lib/page/utils/parse-args.js +48 -13
  27. package/lib/page/utils/parse-args.spec.js +159 -21
  28. package/lib/page/utils/render.d.ts +27 -9
  29. package/lib/page/utils/render.js +66 -12
  30. package/lib/page/utils/render.spec.js +14 -14
  31. package/lib/page/utils/server.d.ts +1 -1
  32. package/lib/page/utils/server.js +2 -2
  33. package/lib/page/utils/server.spec.js +13 -13
  34. package/package.json +1 -1
@@ -73,50 +73,50 @@ describe('parseZonesList', () => {
73
73
  });
74
74
  });
75
75
  });
76
- describe('parseOptionsList', () => {
76
+ describe('parsePropertiesList', () => {
77
77
  it('returns empty object when given empty string', () => {
78
- const result = (0, parse_args_1.parseOptionsList)('', {});
78
+ const result = (0, parse_args_1.parsePropertiesList)('', {});
79
79
  expect(result).toEqual({});
80
80
  });
81
- it('parses single option with equals separator', () => {
82
- const result = (0, parse_args_1.parseOptionsList)('theme=dark', {});
81
+ it('parses single property with equals separator', () => {
82
+ const result = (0, parse_args_1.parsePropertiesList)('theme=dark', {});
83
83
  expect(result).toEqual({
84
84
  theme: 'dark',
85
85
  });
86
86
  });
87
- it('parses single option with colon separator', () => {
88
- const result = (0, parse_args_1.parseOptionsList)('theme:dark', {});
87
+ it('parses single property with colon separator', () => {
88
+ const result = (0, parse_args_1.parsePropertiesList)('theme:dark', {});
89
89
  expect(result).toEqual({
90
90
  theme: 'dark',
91
91
  });
92
92
  });
93
- it('parses comma-separated options with equals separator', () => {
94
- const result = (0, parse_args_1.parseOptionsList)('theme=dark,containerSize=standard,sidebarPosition=right', {});
93
+ it('parses comma-separated properties with equals separator', () => {
94
+ const result = (0, parse_args_1.parsePropertiesList)('theme=dark,containerSize=standard,sidebarPosition=right', {});
95
95
  expect(result).toEqual({
96
96
  theme: 'dark',
97
97
  containerSize: 'standard',
98
98
  sidebarPosition: 'right',
99
99
  });
100
100
  });
101
- it('parses comma-separated options with colon separator', () => {
102
- const result = (0, parse_args_1.parseOptionsList)('theme:dark,containerSize:standard,sidebarPosition:right', {});
101
+ it('parses comma-separated properties with colon separator', () => {
102
+ const result = (0, parse_args_1.parsePropertiesList)('theme:dark,containerSize:standard,sidebarPosition:right', {});
103
103
  expect(result).toEqual({
104
104
  theme: 'dark',
105
105
  containerSize: 'standard',
106
106
  sidebarPosition: 'right',
107
107
  });
108
108
  });
109
- it('later options override earlier ones', () => {
110
- let result = (0, parse_args_1.parseOptionsList)('theme=light', {});
111
- result = (0, parse_args_1.parseOptionsList)('theme=dark', result);
109
+ it('later properties override earlier ones', () => {
110
+ let result = (0, parse_args_1.parsePropertiesList)('theme=light', {});
111
+ result = (0, parse_args_1.parsePropertiesList)('theme=dark', result);
112
112
  expect(result).toEqual({
113
113
  theme: 'dark',
114
114
  });
115
115
  });
116
- it('accumulates values from multiple option flags', () => {
117
- let result = (0, parse_args_1.parseOptionsList)('theme=dark', {});
118
- result = (0, parse_args_1.parseOptionsList)('containerSize=standard', result);
119
- result = (0, parse_args_1.parseOptionsList)('sidebarPosition=right', result);
116
+ it('accumulates values from multiple property flags', () => {
117
+ let result = (0, parse_args_1.parsePropertiesList)('theme=dark', {});
118
+ result = (0, parse_args_1.parsePropertiesList)('containerSize=standard', result);
119
+ result = (0, parse_args_1.parsePropertiesList)('sidebarPosition=right', result);
120
120
  expect(result).toEqual({
121
121
  theme: 'dark',
122
122
  containerSize: 'standard',
@@ -124,19 +124,19 @@ describe('parseOptionsList', () => {
124
124
  });
125
125
  });
126
126
  it('handles mixed syntax with equals and colons', () => {
127
- const result = (0, parse_args_1.parseOptionsList)('theme=dark,containerSize:standard', {});
127
+ const result = (0, parse_args_1.parsePropertiesList)('theme=dark,containerSize:standard', {});
128
128
  expect(result).toEqual({
129
129
  theme: 'dark',
130
130
  containerSize: 'standard',
131
131
  });
132
132
  });
133
133
  it('ignores malformed inputs', () => {
134
- const result = (0, parse_args_1.parseOptionsList)('malformed,theme=,=dark', {});
134
+ const result = (0, parse_args_1.parsePropertiesList)('malformed,theme=,=dark', {});
135
135
  expect(result).toEqual({});
136
136
  });
137
137
  it('handles complex example with multiple formats', () => {
138
- let result = (0, parse_args_1.parseOptionsList)('containerSize:standard', {});
139
- result = (0, parse_args_1.parseOptionsList)('sidebarPosition=right,colorTheme=dark', result);
138
+ let result = (0, parse_args_1.parsePropertiesList)('containerSize:standard', {});
139
+ result = (0, parse_args_1.parsePropertiesList)('sidebarPosition=right,colorTheme=dark', result);
140
140
  expect(result).toEqual({
141
141
  containerSize: 'standard',
142
142
  sidebarPosition: 'right',
@@ -144,3 +144,141 @@ describe('parseOptionsList', () => {
144
144
  });
145
145
  });
146
146
  });
147
+ describe('normalizeLayoutProperties', () => {
148
+ it('returns empty object when given no properties', () => {
149
+ const result = (0, parse_args_1.normalizeLayoutProperties)({}, {});
150
+ expect(result).toEqual({});
151
+ });
152
+ it('returns properties unchanged when layoutDefinition has no properties', () => {
153
+ const properties = {
154
+ theme: 'dark',
155
+ size: 'large',
156
+ };
157
+ const result = (0, parse_args_1.normalizeLayoutProperties)(properties, {});
158
+ expect(result).toEqual(properties);
159
+ });
160
+ it('converts string "true" to boolean true for boolean-type properties', () => {
161
+ const properties = {
162
+ showFooter: 'true',
163
+ };
164
+ const layoutDefinition = {
165
+ properties: {
166
+ showFooter: {
167
+ type: 'boolean',
168
+ },
169
+ },
170
+ };
171
+ const result = (0, parse_args_1.normalizeLayoutProperties)(properties, layoutDefinition);
172
+ expect(result).toEqual({
173
+ showFooter: true,
174
+ });
175
+ expect(typeof result.showFooter).toBe('boolean');
176
+ });
177
+ it('converts string "false" to boolean false for boolean-type properties', () => {
178
+ const properties = {
179
+ showFooter: 'false',
180
+ };
181
+ const layoutDefinition = {
182
+ properties: {
183
+ showFooter: {
184
+ type: 'boolean',
185
+ },
186
+ },
187
+ };
188
+ const result = (0, parse_args_1.normalizeLayoutProperties)(properties, layoutDefinition);
189
+ expect(result).toEqual({
190
+ showFooter: false,
191
+ });
192
+ expect(typeof result.showFooter).toBe('boolean');
193
+ });
194
+ it('leaves string properties unchanged for non-boolean types', () => {
195
+ const properties = {
196
+ theme: 'dark',
197
+ customTitle: 'My Title',
198
+ };
199
+ const layoutDefinition = {
200
+ properties: {
201
+ theme: {
202
+ type: 'string',
203
+ },
204
+ customTitle: {
205
+ type: 'string',
206
+ },
207
+ },
208
+ };
209
+ const result = (0, parse_args_1.normalizeLayoutProperties)(properties, layoutDefinition);
210
+ expect(result).toEqual(properties);
211
+ });
212
+ it('handles mixed boolean and string properties', () => {
213
+ const properties = {
214
+ showFooter: 'true',
215
+ showHeader: 'false',
216
+ theme: 'dark',
217
+ customTitle: 'Test',
218
+ };
219
+ const layoutDefinition = {
220
+ properties: {
221
+ showFooter: { type: 'boolean' },
222
+ showHeader: { type: 'boolean' },
223
+ theme: { type: 'string' },
224
+ customTitle: { type: 'string' },
225
+ },
226
+ };
227
+ const result = (0, parse_args_1.normalizeLayoutProperties)(properties, layoutDefinition);
228
+ expect(result).toEqual({
229
+ showFooter: true,
230
+ showHeader: false,
231
+ theme: 'dark',
232
+ customTitle: 'Test',
233
+ });
234
+ });
235
+ it('throws error for invalid boolean value', () => {
236
+ const properties = {
237
+ showFooter: 'yes',
238
+ };
239
+ const layoutDefinition = {
240
+ properties: {
241
+ showFooter: {
242
+ type: 'boolean',
243
+ },
244
+ },
245
+ };
246
+ expect(() => (0, parse_args_1.normalizeLayoutProperties)(properties, layoutDefinition)).toThrow('Invalid boolean value "yes" for property "showFooter". Must be "true" or "false".');
247
+ });
248
+ it('only normalizes properties that exist in layoutDefinition', () => {
249
+ const properties = {
250
+ showFooter: 'true',
251
+ unknownProperty: 'true',
252
+ };
253
+ const layoutDefinition = {
254
+ properties: {
255
+ showFooter: {
256
+ type: 'boolean',
257
+ },
258
+ },
259
+ };
260
+ const result = (0, parse_args_1.normalizeLayoutProperties)(properties, layoutDefinition);
261
+ expect(result).toEqual({
262
+ showFooter: true,
263
+ unknownProperty: 'true', // Left as string because not in layoutDefinition
264
+ });
265
+ });
266
+ it('preserves properties not present in layoutDefinition properties', () => {
267
+ const properties = {
268
+ showFooter: 'true',
269
+ theme: 'dark',
270
+ };
271
+ const layoutDefinition = {
272
+ properties: {
273
+ showFooter: {
274
+ type: 'boolean',
275
+ },
276
+ },
277
+ };
278
+ const result = (0, parse_args_1.normalizeLayoutProperties)(properties, layoutDefinition);
279
+ expect(result).toEqual({
280
+ showFooter: true,
281
+ theme: 'dark', // Preserved even though not in layoutDefinition
282
+ });
283
+ });
284
+ });
@@ -4,30 +4,48 @@ export interface LayoutDefinition {
4
4
  description?: string;
5
5
  entry?: string;
6
6
  template?: string;
7
- zones: Record<string, ZoneDefinition>;
8
- options?: Record<string, OptionDefinition>;
7
+ zones: ZoneDefinition[];
8
+ properties?: Record<string, PropertyDefinition>;
9
9
  }
10
10
  export interface ExtendedLayoutDefinition extends LayoutDefinition {
11
11
  template: string;
12
12
  }
13
13
  export interface ZoneDefinition {
14
+ key: string;
14
15
  displayName: string;
15
16
  description: string;
16
- minNodes?: number;
17
- maxNodes?: number;
18
17
  }
19
- export interface OptionDefinition {
20
- displayName: string;
18
+ /**
19
+ * Layout option value types.
20
+ */
21
+ export declare const LayoutOptionValueType: {
22
+ readonly stringEnum: "string-enum";
23
+ readonly boolean: "boolean";
24
+ readonly text: "text";
25
+ };
26
+ export declare type LayoutOptionValueType = typeof LayoutOptionValueType[keyof typeof LayoutOptionValueType];
27
+ export declare const LayoutOptionValueTypes: readonly ["string-enum", "boolean", "text"];
28
+ /**
29
+ * Layout property types.
30
+ */
31
+ export declare const LayoutPropertyType: {
32
+ readonly string: "string";
33
+ readonly boolean: "boolean";
34
+ };
35
+ export declare type LayoutPropertyType = typeof LayoutPropertyType[keyof typeof LayoutPropertyType];
36
+ export interface PropertyDefinition {
37
+ title: string;
21
38
  description: string;
22
- values: string[];
39
+ type: LayoutPropertyType;
40
+ enum?: string[] | boolean[];
23
41
  }
24
42
  /**
25
43
  * Renders a layout using Handlebars templating
26
44
  *
27
45
  * @param templateContent The Handlebars template string
28
46
  * @param zoneContents Content for each zone as single concatenated strings
29
- * @param layoutOptions Options for the layout
47
+ * @param layoutProperties Properties for the layout (can include boolean values for boolean-type properties)
30
48
  * @param layoutDefinition Optional layout definition object to pass to the template
31
49
  * @returns The rendered HTML
32
50
  */
33
- export declare function renderLayout(templateContent: string, zoneContents: Record<string, string>, layoutOptions: Record<string, any>, layoutDefinition?: ExtendedLayoutDefinition): Promise<string>;
51
+ export declare function renderLayout(templateContent: string, zoneContents: Record<string, string>, layoutProperties: Record<string, string | boolean>, layoutDefinition?: ExtendedLayoutDefinition): Promise<string>;
@@ -12,41 +12,95 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
12
12
  return (mod && mod.__esModule) ? mod : { "default": mod };
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
- exports.renderLayout = void 0;
15
+ exports.renderLayout = exports.LayoutPropertyType = exports.LayoutOptionValueTypes = exports.LayoutOptionValueType = void 0;
16
16
  const handlebars_1 = __importDefault(require("handlebars"));
17
+ /**
18
+ * Layout option value types.
19
+ */
20
+ exports.LayoutOptionValueType = {
21
+ stringEnum: 'string-enum',
22
+ boolean: 'boolean',
23
+ text: 'text',
24
+ };
25
+ exports.LayoutOptionValueTypes = [
26
+ exports.LayoutOptionValueType.stringEnum,
27
+ exports.LayoutOptionValueType.boolean,
28
+ exports.LayoutOptionValueType.text,
29
+ ];
30
+ /**
31
+ * Layout property types.
32
+ */
33
+ exports.LayoutPropertyType = {
34
+ string: 'string',
35
+ boolean: 'boolean',
36
+ };
37
+ /**
38
+ * Registers global Handlebars helpers
39
+ * TODO: Consider how these can be shared with page-contents-lib
40
+ */
41
+ function registerGlobalHelpers() {
42
+ handlebars_1.default.registerHelper('toLowerCase', function (text) {
43
+ return typeof text === 'string' ? text.toLowerCase() : '';
44
+ });
45
+ handlebars_1.default.registerHelper('toUpperCase', function (text) {
46
+ return typeof text === 'string' ? text.toUpperCase() : '';
47
+ });
48
+ handlebars_1.default.registerHelper('ifEq', function (first, second, options) {
49
+ if (first === second) {
50
+ return options.fn(this);
51
+ }
52
+ else {
53
+ return options.inverse(this);
54
+ }
55
+ });
56
+ handlebars_1.default.registerHelper('ifNotEq', function (first, second, options) {
57
+ if (first !== second) {
58
+ return options.fn(this);
59
+ }
60
+ else {
61
+ return options.inverse(this);
62
+ }
63
+ });
64
+ handlebars_1.default.registerHelper('stringify', function (object) {
65
+ return JSON.stringify(object);
66
+ });
67
+ }
17
68
  /**
18
69
  * Renders a layout using Handlebars templating
19
70
  *
20
71
  * @param templateContent The Handlebars template string
21
72
  * @param zoneContents Content for each zone as single concatenated strings
22
- * @param layoutOptions Options for the layout
73
+ * @param layoutProperties Properties for the layout (can include boolean values for boolean-type properties)
23
74
  * @param layoutDefinition Optional layout definition object to pass to the template
24
75
  * @returns The rendered HTML
25
76
  */
26
- function renderLayout(templateContent, zoneContents, layoutOptions, layoutDefinition) {
77
+ function renderLayout(templateContent, zoneContents, layoutProperties, layoutDefinition) {
27
78
  return __awaiter(this, void 0, void 0, function* () {
28
79
  try {
80
+ registerGlobalHelpers();
29
81
  const template = handlebars_1.default.compile(templateContent);
30
82
  const zones = {};
31
83
  for (const [zoneName, content] of Object.entries(zoneContents)) {
32
84
  // Wrap the content in SafeString to prevent HTML escaping
33
85
  zones[zoneName] = new handlebars_1.default.SafeString(content);
34
86
  }
35
- const flattenedOptions = {};
36
- for (const [key, value] of Object.entries(layoutOptions)) {
37
- const optionValue = value;
38
- if (optionValue &&
39
- typeof optionValue === 'object' &&
40
- 'selectedValue' in optionValue) {
41
- flattenedOptions[key] = optionValue.selectedValue;
87
+ const flattenedProperties = {};
88
+ for (const [key, value] of Object.entries(layoutProperties)) {
89
+ const propertyValue = value;
90
+ if (propertyValue &&
91
+ typeof propertyValue === 'object' &&
92
+ 'selectedValue' in propertyValue) {
93
+ flattenedProperties[key] = propertyValue.selectedValue;
42
94
  }
43
95
  else {
44
- flattenedOptions[key] = optionValue;
96
+ flattenedProperties[key] = propertyValue;
45
97
  }
46
98
  }
47
99
  return template({
48
100
  zones: zones,
49
- options: flattenedOptions,
101
+ // Still provide options for existing templates that use it
102
+ options: flattenedProperties,
103
+ properties: flattenedProperties,
50
104
  layout: layoutDefinition,
51
105
  });
52
106
  }
@@ -23,21 +23,21 @@ describe('renderLayout', () => {
23
23
  const zoneContents = {
24
24
  main: '<p>Content 1</p><p>Content 2</p>',
25
25
  };
26
- const layoutOptions = {};
27
- const result = yield (0, render_1.renderLayout)(templateContent, zoneContents, layoutOptions);
26
+ const layoutProperties = {};
27
+ const result = yield (0, render_1.renderLayout)(templateContent, zoneContents, layoutProperties);
28
28
  expect(result).toContain('<div class="container">');
29
29
  expect(result).toContain('<p>Content 1</p>');
30
30
  expect(result).toContain('<p>Content 2</p>');
31
31
  }));
32
- it('should apply layout options to the template', () => __awaiter(void 0, void 0, void 0, function* () {
32
+ it('should apply layout properties to the template (with deprecated options support)', () => __awaiter(void 0, void 0, void 0, function* () {
33
33
  const templateContent = '<div class="container {{options.size}}">{{zones.main}}</div>';
34
34
  const zoneContents = {
35
35
  main: '<p>Content</p>',
36
36
  };
37
- const layoutOptions = {
37
+ const layoutProperties = {
38
38
  size: 'large',
39
39
  };
40
- const result = yield (0, render_1.renderLayout)(templateContent, zoneContents, layoutOptions);
40
+ const result = yield (0, render_1.renderLayout)(templateContent, zoneContents, layoutProperties);
41
41
  expect(result).toContain('<div class="container large">');
42
42
  expect(result).toContain('<p>Content</p>');
43
43
  }));
@@ -52,8 +52,8 @@ describe('renderLayout', () => {
52
52
  main: '<p>Main Content</p>',
53
53
  sidebar: '<div>Sidebar Item 1</div><div>Sidebar Item 2</div>',
54
54
  };
55
- const layoutOptions = {};
56
- const result = yield (0, render_1.renderLayout)(templateContent, zoneContents, layoutOptions);
55
+ const layoutProperties = {};
56
+ const result = yield (0, render_1.renderLayout)(templateContent, zoneContents, layoutProperties);
57
57
  expect(result).toContain('<div class="main"><p>Main Content</p></div>');
58
58
  expect(result).toContain('<div class="sidebar"><div>Sidebar Item 1</div><div>Sidebar Item 2</div></div>');
59
59
  }));
@@ -67,10 +67,10 @@ describe('renderLayout', () => {
67
67
  const zoneContents = {
68
68
  main: '<p>Content</p>',
69
69
  };
70
- const layoutOptions = {
71
- theme: { selectedValue: 'dark' },
70
+ const layoutProperties = {
71
+ theme: 'dark',
72
72
  };
73
- const result = yield (0, render_1.renderLayout)(templateContent, zoneContents, layoutOptions);
73
+ const result = yield (0, render_1.renderLayout)(templateContent, zoneContents, layoutProperties);
74
74
  expect(result).toContain('<div class="theme-dark">');
75
75
  }));
76
76
  it('should use SafeString to prevent HTML escaping', () => __awaiter(void 0, void 0, void 0, function* () {
@@ -98,13 +98,13 @@ describe('renderLayout', () => {
98
98
  name: 'test-layout',
99
99
  displayName: 'Test Layout',
100
100
  template: templateContent,
101
- zones: {
102
- main: {
101
+ zones: [
102
+ {
103
+ key: 'main',
103
104
  displayName: 'Main Content',
104
105
  description: 'Main content area',
105
- minNodes: 1,
106
106
  },
107
- },
107
+ ],
108
108
  };
109
109
  const result = yield (0, render_1.renderLayout)(templateContent, zoneContents, {}, layoutDefinition);
110
110
  expect(result).toContain('<div class="test-layout">');
@@ -3,7 +3,7 @@ interface DevServerOptions {
3
3
  configPath: string;
4
4
  layoutDefinition: ExtendedLayoutDefinition;
5
5
  zoneContent: Record<string, string[]>;
6
- layoutOptions: Record<string, string>;
6
+ layoutProperties: Record<string, string | boolean>;
7
7
  stylesheet?: string;
8
8
  port: number;
9
9
  openBrowser: boolean;
@@ -49,7 +49,7 @@ const logger = (0, dx_logger_lib_1.getLogger)({
49
49
  });
50
50
  function startDevServer(options) {
51
51
  return __awaiter(this, void 0, void 0, function* () {
52
- const { configPath, layoutOptions, port, openBrowser } = options;
52
+ const { configPath, layoutProperties, port, openBrowser } = options;
53
53
  // Create HTTP server with stateless request handling
54
54
  const server = http.createServer((req, res) => __awaiter(this, void 0, void 0, function* () {
55
55
  const url = new URL(req.url || '/', `http://localhost:${port}`);
@@ -82,7 +82,7 @@ function startDevServer(options) {
82
82
  stylesheetContent = yield fs.readFile(options.stylesheet, 'utf-8');
83
83
  }
84
84
  // Use the renderLayout helper
85
- const html = yield (0, render_1.renderLayout)(layoutDefinition.template, zoneContents, layoutOptions, layoutDefinition);
85
+ const html = yield (0, render_1.renderLayout)(layoutDefinition.template, zoneContents, layoutProperties, layoutDefinition);
86
86
  // for hot-reload script
87
87
  const fullHtml = `
88
88
  <!DOCTYPE html>
@@ -76,25 +76,25 @@ describe('startDevServer', () => {
76
76
  displayName: 'Test Layout',
77
77
  description: 'A test layout',
78
78
  entry: 'path/to/template.html',
79
- template: '<div class="{{options.size}}">{{{zones.main}}}</div>',
80
- zones: {
81
- main: {
79
+ template: '<div class="{{properties.size}}">{{{zones.main}}}</div>',
80
+ zones: [
81
+ {
82
+ key: 'main',
82
83
  displayName: 'Main Content',
83
84
  description: 'Main content area',
84
- minNodes: 1,
85
85
  },
86
- sidebar: {
86
+ {
87
+ key: 'sidebar',
87
88
  displayName: 'Sidebar',
88
89
  description: 'Sidebar content',
89
- minNodes: 0,
90
- maxNodes: 3,
91
90
  },
92
- },
93
- options: {
91
+ ],
92
+ properties: {
94
93
  size: {
95
- displayName: 'Size',
94
+ title: 'Size',
96
95
  description: 'Container size',
97
- values: ['small', 'medium', 'large'],
96
+ enum: ['small', 'medium', 'large'],
97
+ type: 'string',
98
98
  },
99
99
  },
100
100
  };
@@ -105,7 +105,7 @@ describe('startDevServer', () => {
105
105
  main: ['/path/to/main.html'],
106
106
  sidebar: ['/path/to/sidebar1.html', '/path/to/sidebar2.html'],
107
107
  },
108
- layoutOptions: {
108
+ layoutProperties: {
109
109
  size: 'large',
110
110
  },
111
111
  stylesheet: '/path/to/styles.css',
@@ -221,7 +221,7 @@ describe('startDevServer', () => {
221
221
  expect(mockRenderLayout).toHaveBeenCalledWith(mockLayoutDefinition.template, expect.objectContaining({
222
222
  main: '<p>Main content</p>',
223
223
  sidebar: '<div>Sidebar item</div><div>Sidebar item</div>',
224
- }), mockServerOptions.layoutOptions, mockLayoutDefinition);
224
+ }), mockServerOptions.layoutProperties, mockLayoutDefinition);
225
225
  }));
226
226
  it('should set up check-changes endpoint for client polling', () => __awaiter(void 0, void 0, void 0, function* () {
227
227
  const mockRequest = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@squiz/dxp-cli-next",
3
- "version": "5.31.0-develop.4",
3
+ "version": "5.31.0-develop.6",
4
4
  "repository": {
5
5
  "url": "https://gitlab.squiz.net/dxp/dxp-cli-next"
6
6
  },