@defra/forms-engine-plugin 4.0.5 → 4.0.7

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 (83) hide show
  1. package/.public/stylesheets/application.min.css +2 -2
  2. package/.public/stylesheets/application.min.css.map +1 -1
  3. package/.server/client/stylesheets/_location-input.scss +60 -0
  4. package/.server/client/stylesheets/application.scss +1 -6
  5. package/.server/client/stylesheets/shared.scss +8 -0
  6. package/.server/server/forms/register-as-a-unicorn-breeder.yaml +28 -0
  7. package/.server/server/plugins/engine/components/ComponentBase.d.ts +1 -1
  8. package/.server/server/plugins/engine/components/ComponentBase.js.map +1 -1
  9. package/.server/server/plugins/engine/components/EastingNorthingField.d.ts +121 -0
  10. package/.server/server/plugins/engine/components/EastingNorthingField.js +166 -0
  11. package/.server/server/plugins/engine/components/EastingNorthingField.js.map +1 -0
  12. package/.server/server/plugins/engine/components/LatLongField.d.ts +121 -0
  13. package/.server/server/plugins/engine/components/LatLongField.js +164 -0
  14. package/.server/server/plugins/engine/components/LatLongField.js.map +1 -0
  15. package/.server/server/plugins/engine/components/LocationFieldBase.d.ts +134 -0
  16. package/.server/server/plugins/engine/components/LocationFieldBase.js +85 -0
  17. package/.server/server/plugins/engine/components/LocationFieldBase.js.map +1 -0
  18. package/.server/server/plugins/engine/components/LocationFieldHelpers.d.ts +108 -0
  19. package/.server/server/plugins/engine/components/LocationFieldHelpers.js +96 -0
  20. package/.server/server/plugins/engine/components/LocationFieldHelpers.js.map +1 -0
  21. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.d.ts +19 -0
  22. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js +40 -0
  23. package/.server/server/plugins/engine/components/NationalGridFieldNumberField.js.map +1 -0
  24. package/.server/server/plugins/engine/components/OsGridRefField.d.ts +19 -0
  25. package/.server/server/plugins/engine/components/OsGridRefField.js +56 -0
  26. package/.server/server/plugins/engine/components/OsGridRefField.js.map +1 -0
  27. package/.server/server/plugins/engine/components/helpers/components.d.ts +3 -4
  28. package/.server/server/plugins/engine/components/helpers/components.js +21 -29
  29. package/.server/server/plugins/engine/components/helpers/components.js.map +1 -1
  30. package/.server/server/plugins/engine/components/index.d.ts +4 -0
  31. package/.server/server/plugins/engine/components/index.js +4 -0
  32. package/.server/server/plugins/engine/components/index.js.map +1 -1
  33. package/.server/server/plugins/engine/components/markdownParser.d.ts +2 -0
  34. package/.server/server/plugins/engine/components/markdownParser.js +28 -0
  35. package/.server/server/plugins/engine/components/markdownParser.js.map +1 -0
  36. package/.server/server/plugins/engine/components/types.d.ts +10 -0
  37. package/.server/server/plugins/engine/components/types.js.map +1 -1
  38. package/.server/server/plugins/engine/pageControllers/helpers/pages.js +7 -0
  39. package/.server/server/plugins/engine/pageControllers/helpers/pages.js.map +1 -1
  40. package/.server/server/plugins/engine/types/index.d.ts +1 -1
  41. package/.server/server/plugins/engine/types/index.js.map +1 -1
  42. package/.server/server/plugins/engine/types.d.ts +2 -2
  43. package/.server/server/plugins/engine/types.js.map +1 -1
  44. package/.server/server/plugins/engine/views/components/_location-field-base.html +53 -0
  45. package/.server/server/plugins/engine/views/components/eastingnorthingfield.html +5 -0
  46. package/.server/server/plugins/engine/views/components/latlongfield.html +5 -0
  47. package/.server/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +13 -0
  48. package/.server/server/plugins/engine/views/components/osgridreffield.html +13 -0
  49. package/.server/server/plugins/nunjucks/filters/field.d.ts +1 -1
  50. package/package.json +3 -3
  51. package/src/client/stylesheets/_location-input.scss +60 -0
  52. package/src/client/stylesheets/application.scss +1 -6
  53. package/src/client/stylesheets/shared.scss +8 -0
  54. package/src/server/forms/register-as-a-unicorn-breeder.yaml +28 -0
  55. package/src/server/plugins/engine/components/ComponentBase.ts +1 -1
  56. package/src/server/plugins/engine/components/EastingNorthingField.test.ts +665 -0
  57. package/src/server/plugins/engine/components/EastingNorthingField.ts +224 -0
  58. package/src/server/plugins/engine/components/LatLongField.test.ts +700 -0
  59. package/src/server/plugins/engine/components/LatLongField.ts +213 -0
  60. package/src/server/plugins/engine/components/LocationFieldBase.test.ts +253 -0
  61. package/src/server/plugins/engine/components/LocationFieldBase.ts +152 -0
  62. package/src/server/plugins/engine/components/LocationFieldHelpers.test.ts +338 -0
  63. package/src/server/plugins/engine/components/LocationFieldHelpers.ts +123 -0
  64. package/src/server/plugins/engine/components/NationalGridFieldNumberField.test.ts +438 -0
  65. package/src/server/plugins/engine/components/NationalGridFieldNumberField.ts +52 -0
  66. package/src/server/plugins/engine/components/OsGridRefField.test.ts +469 -0
  67. package/src/server/plugins/engine/components/OsGridRefField.ts +71 -0
  68. package/src/server/plugins/engine/components/helpers/components.test.ts +270 -0
  69. package/src/server/plugins/engine/components/helpers/components.ts +39 -47
  70. package/src/server/plugins/engine/components/helpers/helpers.test.ts +71 -1
  71. package/src/server/plugins/engine/components/index.ts +4 -0
  72. package/src/server/plugins/engine/components/markdownParser.ts +40 -0
  73. package/src/server/plugins/engine/components/types.ts +14 -0
  74. package/src/server/plugins/engine/outputFormatters/adapter/v1.location.test.ts +356 -0
  75. package/src/server/plugins/engine/pageControllers/helpers/helpers.test.ts +4 -0
  76. package/src/server/plugins/engine/pageControllers/helpers/pages.ts +8 -0
  77. package/src/server/plugins/engine/types/index.ts +2 -0
  78. package/src/server/plugins/engine/types.ts +4 -0
  79. package/src/server/plugins/engine/views/components/_location-field-base.html +53 -0
  80. package/src/server/plugins/engine/views/components/eastingnorthingfield.html +5 -0
  81. package/src/server/plugins/engine/views/components/latlongfield.html +5 -0
  82. package/src/server/plugins/engine/views/components/nationalgridfieldnumberfield.html +13 -0
  83. package/src/server/plugins/engine/views/components/osgridreffield.html +13 -0
@@ -0,0 +1,356 @@
1
+ import {
2
+ ComponentType,
3
+ type EastingNorthingFieldComponent,
4
+ type FormDefinition,
5
+ type LatLongFieldComponent,
6
+ type NationalGridFieldNumberFieldComponent,
7
+ type OsGridRefFieldComponent,
8
+ type PageQuestion
9
+ } from '@defra/forms-model'
10
+
11
+ import {
12
+ EastingNorthingField,
13
+ LatLongField,
14
+ NationalGridFieldNumberField,
15
+ OsGridRefField
16
+ } from '~/src/server/plugins/engine/components/index.js'
17
+ import { FormModel } from '~/src/server/plugins/engine/models/index.js'
18
+ import { type DetailItemField } from '~/src/server/plugins/engine/models/types.js'
19
+ import { format } from '~/src/server/plugins/engine/outputFormatters/adapter/v1.js'
20
+ import { buildFormContextRequest } from '~/src/server/plugins/engine/pageControllers/__stubs__/request.js'
21
+ import {
22
+ FormAdapterSubmissionSchemaVersion,
23
+ type FormAdapterSubmissionMessagePayload
24
+ } from '~/src/server/plugins/engine/types/index.js'
25
+ import { FormStatus } from '~/src/server/routes/types.js'
26
+
27
+ describe('Adapter V1 formatter - Location fields', () => {
28
+ const definition: FormDefinition = {
29
+ name: 'Location Test Form',
30
+ startPage: '/location',
31
+ pages: [
32
+ {
33
+ path: '/location',
34
+ title: 'Location Page',
35
+ next: [],
36
+ components: [
37
+ {
38
+ type: ComponentType.EastingNorthingField,
39
+ name: 'locationEN',
40
+ title: 'Easting and Northing',
41
+ options: {}
42
+ },
43
+ {
44
+ type: ComponentType.LatLongField,
45
+ name: 'locationLL',
46
+ title: 'Latitude and Longitude',
47
+ options: {}
48
+ },
49
+ {
50
+ type: ComponentType.OsGridRefField,
51
+ name: 'gridRef',
52
+ title: 'OS Grid Reference',
53
+ options: {}
54
+ },
55
+ {
56
+ type: ComponentType.NationalGridFieldNumberField,
57
+ name: 'ngField',
58
+ title: 'National Grid Field Number',
59
+ options: {}
60
+ }
61
+ ]
62
+ } satisfies PageQuestion
63
+ ],
64
+ lists: [],
65
+ sections: [],
66
+ conditions: []
67
+ }
68
+
69
+ const model = new FormModel(definition, { basePath: 'test' })
70
+ const locationPage = definition.pages[0] as PageQuestion
71
+
72
+ const submitResponse = {
73
+ message: 'Submit completed',
74
+ result: {
75
+ files: {
76
+ main: '00000000-0000-0000-0000-000000000000',
77
+ repeaters: {}
78
+ }
79
+ }
80
+ }
81
+
82
+ const pageUrl = new URL('http://example.com/test/location')
83
+
84
+ const request = buildFormContextRequest({
85
+ method: 'get',
86
+ url: pageUrl,
87
+ path: pageUrl.pathname,
88
+ params: {
89
+ path: 'location',
90
+ slug: 'test'
91
+ },
92
+ query: {},
93
+ app: { model }
94
+ })
95
+
96
+ it('includes EastingNorthingField values in the payload', () => {
97
+ const state = {
98
+ $$__referenceNumber: 'ABC-123',
99
+ locationEN__easting: 123456,
100
+ locationEN__northing: 654321,
101
+ locationLL__latitude: 51.5,
102
+ locationLL__longitude: -0.1,
103
+ gridRef: 'TQ123456',
104
+ ngField: 'NG12345678'
105
+ }
106
+
107
+ const context = model.getFormContext(request, state)
108
+
109
+ const eastingNorthingField = new EastingNorthingField(
110
+ locationPage.components[0] as EastingNorthingFieldComponent,
111
+ { model }
112
+ )
113
+
114
+ const items: DetailItemField[] = [
115
+ {
116
+ name: 'locationEN',
117
+ label: 'Easting and Northing',
118
+ href: '/location',
119
+ title: 'Easting and Northing',
120
+ field: eastingNorthingField,
121
+ state,
122
+ value: '654321, 123456'
123
+ } as unknown as DetailItemField
124
+ ]
125
+
126
+ const result = format(context, items, model, submitResponse, {
127
+ state: FormStatus.Live,
128
+ isPreview: false
129
+ })
130
+
131
+ const payload = JSON.parse(result) as FormAdapterSubmissionMessagePayload
132
+
133
+ expect(payload.meta.schemaVersion).toBe(
134
+ FormAdapterSubmissionSchemaVersion.V1
135
+ )
136
+ expect(payload.data.main.locationEN).toEqual({
137
+ easting: 123456,
138
+ northing: 654321
139
+ })
140
+ })
141
+
142
+ it('includes LatLongField values in the payload', () => {
143
+ const state = {
144
+ $$__referenceNumber: 'ABC-123',
145
+ locationLL__latitude: 51.51945,
146
+ locationLL__longitude: -0.127758
147
+ }
148
+
149
+ const context = model.getFormContext(request, state)
150
+
151
+ const latLongField = new LatLongField(
152
+ locationPage.components[1] as LatLongFieldComponent,
153
+ { model }
154
+ )
155
+
156
+ const items: DetailItemField[] = [
157
+ {
158
+ name: 'locationLL',
159
+ label: 'Latitude and Longitude',
160
+ href: '/location',
161
+ title: 'Latitude and Longitude',
162
+ field: latLongField,
163
+ state,
164
+ value: '51.519450, -0.127758'
165
+ } as unknown as DetailItemField
166
+ ]
167
+
168
+ const result = format(context, items, model, submitResponse, {
169
+ state: FormStatus.Live,
170
+ isPreview: false
171
+ })
172
+
173
+ const payload = JSON.parse(result) as FormAdapterSubmissionMessagePayload
174
+
175
+ expect(payload.data.main.locationLL).toEqual({
176
+ latitude: 51.51945,
177
+ longitude: -0.127758
178
+ })
179
+ })
180
+
181
+ it('includes simple location field values in the payload', () => {
182
+ const state = {
183
+ $$__referenceNumber: 'ABC-123',
184
+ gridRef: 'TQ123456',
185
+ ngField: 'NG12345678'
186
+ }
187
+
188
+ const context = model.getFormContext(request, state)
189
+
190
+ const osGridRefField = new OsGridRefField(
191
+ locationPage.components[2] as OsGridRefFieldComponent,
192
+ { model }
193
+ )
194
+
195
+ const nationalGridField = new NationalGridFieldNumberField(
196
+ locationPage.components[3] as NationalGridFieldNumberFieldComponent,
197
+ { model }
198
+ )
199
+
200
+ const items: DetailItemField[] = [
201
+ {
202
+ name: 'gridRef',
203
+ label: 'OS Grid Reference',
204
+ href: '/location',
205
+ title: 'OS Grid Reference',
206
+ field: osGridRefField,
207
+ state,
208
+ value: 'TQ123456'
209
+ } as unknown as DetailItemField,
210
+ {
211
+ name: 'ngField',
212
+ label: 'National Grid Field Number',
213
+ href: '/location',
214
+ title: 'National Grid Field Number',
215
+ field: nationalGridField,
216
+ state,
217
+ value: 'NG12345678'
218
+ } as unknown as DetailItemField
219
+ ]
220
+
221
+ const result = format(context, items, model, submitResponse, {
222
+ state: FormStatus.Live,
223
+ isPreview: false
224
+ })
225
+
226
+ const payload = JSON.parse(result) as FormAdapterSubmissionMessagePayload
227
+
228
+ expect(payload.data.main.gridRef).toBe('TQ123456')
229
+ expect(payload.data.main.ngField).toBe('NG12345678')
230
+ })
231
+
232
+ it('handles null values for optional location fields', () => {
233
+ const state = {
234
+ $$__referenceNumber: 'ABC-123'
235
+ }
236
+
237
+ const context = model.getFormContext(request, state)
238
+
239
+ const eastingNorthingField = new EastingNorthingField(
240
+ locationPage.components[0] as EastingNorthingFieldComponent,
241
+ { model }
242
+ )
243
+
244
+ const items: DetailItemField[] = [
245
+ {
246
+ name: 'locationEN',
247
+ label: 'Easting and Northing',
248
+ href: '/location',
249
+ title: 'Easting and Northing',
250
+ field: eastingNorthingField,
251
+ state,
252
+ value: ''
253
+ } as unknown as DetailItemField
254
+ ]
255
+
256
+ const result = format(context, items, model, submitResponse, {
257
+ state: FormStatus.Live,
258
+ isPreview: false
259
+ })
260
+
261
+ const payload = JSON.parse(result) as FormAdapterSubmissionMessagePayload
262
+
263
+ expect(payload.data.main.locationEN).toBeNull()
264
+ })
265
+
266
+ it('includes all location fields in a mixed form', () => {
267
+ const state = {
268
+ $$__referenceNumber: 'ABC-123',
269
+ locationEN__easting: 123456,
270
+ locationEN__northing: 654321,
271
+ locationLL__latitude: 51.51945,
272
+ locationLL__longitude: -0.127758,
273
+ gridRef: 'TQ123456',
274
+ ngField: 'NG12345678'
275
+ }
276
+
277
+ const context = model.getFormContext(request, state)
278
+
279
+ const eastingNorthingField = new EastingNorthingField(
280
+ locationPage.components[0] as EastingNorthingFieldComponent,
281
+ { model }
282
+ )
283
+ const latLongField = new LatLongField(
284
+ locationPage.components[1] as LatLongFieldComponent,
285
+ { model }
286
+ )
287
+ const osGridRefField = new OsGridRefField(
288
+ locationPage.components[2] as OsGridRefFieldComponent,
289
+ { model }
290
+ )
291
+ const nationalGridField = new NationalGridFieldNumberField(
292
+ locationPage.components[3] as NationalGridFieldNumberFieldComponent,
293
+ { model }
294
+ )
295
+
296
+ const items: DetailItemField[] = [
297
+ {
298
+ name: 'locationEN',
299
+ label: 'Easting and Northing',
300
+ href: '/location',
301
+ title: 'Easting and Northing',
302
+ field: eastingNorthingField,
303
+ state,
304
+ value: '654321, 123456'
305
+ } as unknown as DetailItemField,
306
+ {
307
+ name: 'locationLL',
308
+ label: 'Latitude and Longitude',
309
+ href: '/location',
310
+ title: 'Latitude and Longitude',
311
+ field: latLongField,
312
+ state,
313
+ value: '51.519450, -0.127758'
314
+ } as unknown as DetailItemField,
315
+ {
316
+ name: 'gridRef',
317
+ label: 'OS Grid Reference',
318
+ href: '/location',
319
+ title: 'OS Grid Reference',
320
+ field: osGridRefField,
321
+ state,
322
+ value: 'TQ123456'
323
+ } as unknown as DetailItemField,
324
+ {
325
+ name: 'ngField',
326
+ label: 'National Grid Field Number',
327
+ href: '/location',
328
+ title: 'National Grid Field Number',
329
+ field: nationalGridField,
330
+ state,
331
+ value: 'NG12345678'
332
+ } as unknown as DetailItemField
333
+ ]
334
+
335
+ const result = format(context, items, model, submitResponse, {
336
+ state: FormStatus.Live,
337
+ isPreview: false
338
+ })
339
+
340
+ const payload = JSON.parse(result) as FormAdapterSubmissionMessagePayload
341
+
342
+ // Check all location fields are included correctly
343
+ expect(payload.data.main).toEqual({
344
+ locationEN: {
345
+ easting: 123456,
346
+ northing: 654321
347
+ },
348
+ locationLL: {
349
+ latitude: 51.51945,
350
+ longitude: -0.127758
351
+ },
352
+ gridRef: 'TQ123456',
353
+ ngField: 'NG12345678'
354
+ })
355
+ })
356
+ })
@@ -67,6 +67,10 @@ describe('Page controller helpers', () => {
67
67
  controller = SummaryPageController
68
68
  break
69
69
 
70
+ case ControllerType.SummaryWithConfirmationEmail:
71
+ controller = SummaryPageController
72
+ break
73
+
70
74
  case ControllerType.Status:
71
75
  controller = StatusPageController
72
76
  break
@@ -11,6 +11,10 @@ import * as PageControllers from '~/src/server/plugins/engine/pageControllers/in
11
11
  export function isPageController(
12
12
  controllerName?: string | ControllerType
13
13
  ): controllerName is keyof typeof PageControllers {
14
+ // Handle SummaryWithConfirmationEmail as it uses SummaryPageController
15
+ if (controllerName === ControllerType.SummaryWithConfirmationEmail) {
16
+ return true
17
+ }
14
18
  return isControllerName(controllerName) && controllerName in PageControllers
15
19
  }
16
20
 
@@ -52,6 +56,10 @@ export function createPage(model: FormModel, pageDef: Page) {
52
56
  controller = new PageControllers.SummaryPageController(model, pageDef)
53
57
  break
54
58
 
59
+ case ControllerType.SummaryWithConfirmationEmail:
60
+ controller = new PageControllers.SummaryPageController(model, pageDef)
61
+ break
62
+
55
63
  case ControllerType.Status:
56
64
  controller = new PageControllers.StatusPageController(model, pageDef)
57
65
  break
@@ -61,7 +61,9 @@ export type {
61
61
  Content,
62
62
  DateInputItem,
63
63
  DatePartsState,
64
+ EastingNorthingState,
64
65
  Label,
66
+ LatLongState,
65
67
  ListItem,
66
68
  ListItemLabel,
67
69
  MonthYearState,
@@ -23,6 +23,8 @@ import {
23
23
  type ComponentText,
24
24
  type ComponentViewModel,
25
25
  type DatePartsState,
26
+ type EastingNorthingState,
27
+ type LatLongState,
26
28
  type MonthYearState
27
29
  } from '~/src/server/plugins/engine/components/types.js'
28
30
  import { type FormModel } from '~/src/server/plugins/engine/models/index.js'
@@ -464,6 +466,8 @@ export type RichFormValue =
464
466
  | DatePartsState
465
467
  | MonthYearState
466
468
  | UkAddressState
469
+ | EastingNorthingState
470
+ | LatLongState
467
471
 
468
472
  export interface FormAdapterSubmissionMessageData {
469
473
  main: Record<string, RichFormValue | null>
@@ -0,0 +1,53 @@
1
+ {% from "govuk/components/input/macro.njk" import govukInput %}
2
+ {% from "govuk/components/fieldset/macro.njk" import govukFieldset %}
3
+ {% from "govuk/components/details/macro.njk" import govukDetails %}
4
+ {% from "govuk/components/hint/macro.njk" import govukHint %}
5
+
6
+ {% macro LocationFieldBase(component, inputType, inputMode) %}
7
+ {% set fieldsetHtml %}
8
+ {% if component.model.hint %}
9
+ {{ govukHint({
10
+ id: component.model.name + "-hint",
11
+ text: component.model.hint.text
12
+ }) }}
13
+ {% endif %}
14
+
15
+ <div class="app-location-input">
16
+ {% for item in component.model.items %}
17
+ <div class="app-location-input__item">
18
+ {{ govukInput({
19
+ id: item.id,
20
+ name: item.name,
21
+ label: {
22
+ text: item.label,
23
+ classes: "govuk-label--s"
24
+ },
25
+ classes: item.classes,
26
+ value: item.value,
27
+ type: inputType,
28
+ inputmode: inputMode,
29
+ prefix: item.prefix,
30
+ suffix: item.suffix
31
+ }) }}
32
+ </div>
33
+ {% endfor %}
34
+ </div>
35
+
36
+ {% if component.model.instructionText %}
37
+ {{ govukDetails({
38
+ summaryText: "How to find location details",
39
+ html: component.model.instructionText | safe
40
+ }) }}
41
+ {% endif %}
42
+ {% endset %}
43
+
44
+ {{ govukFieldset({
45
+ legend: {
46
+ text: component.model.fieldset.legend.text,
47
+ classes: component.model.fieldset.legend.classes,
48
+ isPageHeading: false
49
+ },
50
+ html: fieldsetHtml
51
+ }) }}
52
+ {% endmacro %}
53
+
@@ -0,0 +1,5 @@
1
+ {% from "./_location-field-base.html" import LocationFieldBase %}
2
+
3
+ {% macro EastingNorthingField(component) %}
4
+ {{ LocationFieldBase(component, "number", "numeric") }}
5
+ {% endmacro %}
@@ -0,0 +1,5 @@
1
+ {% from "./_location-field-base.html" import LocationFieldBase %}
2
+
3
+ {% macro LatLongField(component) %}
4
+ {{ LocationFieldBase(component, "text", "decimal") }}
5
+ {% endmacro %}
@@ -0,0 +1,13 @@
1
+ {% from "components/textfield.html" import TextField %}
2
+ {% from "govuk/components/details/macro.njk" import govukDetails %}
3
+
4
+ {% macro NationalGridFieldNumberField(component) %}
5
+ {{ TextField(component) }}
6
+
7
+ {% if component.model.instructionText %}
8
+ {{ govukDetails({
9
+ summaryText: "How to find location details",
10
+ html: component.model.instructionText | safe
11
+ }) }}
12
+ {% endif %}
13
+ {% endmacro %}
@@ -0,0 +1,13 @@
1
+ {% from "components/textfield.html" import TextField %}
2
+ {% from "govuk/components/details/macro.njk" import govukDetails %}
3
+
4
+ {% macro OsGridRefField(component) %}
5
+ {{ TextField(component) }}
6
+
7
+ {% if component.model.instructionText %}
8
+ {{ govukDetails({
9
+ summaryText: "How to find location details",
10
+ html: component.model.instructionText | safe
11
+ }) }}
12
+ {% endif %}
13
+ {% endmacro %}