hof 22.12.0-unit-of-measure-beta.1 → 22.13.0-frontend-v4-beta.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.
Files changed (48) hide show
  1. package/CHANGELOG.md +13 -1
  2. package/README.md +0 -78
  3. package/build/tasks/images/index.js +20 -5
  4. package/build/tasks/watch/index.js +10 -2
  5. package/components/date/templates/date.html +1 -1
  6. package/components/index.js +0 -1
  7. package/config/builder-defaults.js +6 -2
  8. package/controller/controller.js +3 -5
  9. package/controller/validation/index.js +1 -1
  10. package/controller/validation/validators.js +1 -0
  11. package/frontend/govuk-template/build/config.js +1 -0
  12. package/frontend/govuk-template/build/govuk_template.html +58 -42
  13. package/frontend/govuk-template/govuk_template_generated.html +118 -0
  14. package/frontend/template-mixins/mixins/template-mixins.js +10 -59
  15. package/frontend/template-mixins/partials/forms/checkbox.html +5 -1
  16. package/frontend/template-mixins/partials/forms/input-text-date.html +2 -1
  17. package/frontend/template-mixins/partials/forms/input-text-group.html +1 -1
  18. package/frontend/template-mixins/partials/forms/textarea-group.html +1 -1
  19. package/frontend/template-partials/views/layout.html +1 -1
  20. package/frontend/template-partials/views/partials/cookie-banner.html +50 -32
  21. package/frontend/template-partials/views/partials/navigation.html +2 -2
  22. package/frontend/themes/gov-uk/client-js/cookieSettings.js +35 -23
  23. package/frontend/themes/gov-uk/styles/govuk.scss +0 -1
  24. package/frontend/toolkit/assets/javascript/form-focus.js +0 -4
  25. package/frontend/toolkit/assets/rebrand/images/govuk-logo.svg +25 -0
  26. package/index.js +4 -2
  27. package/package.json +2 -2
  28. package/sandbox/apps/sandbox/fields.js +1 -18
  29. package/sandbox/apps/sandbox/index.js +0 -4
  30. package/sandbox/apps/sandbox/sections/summary-data-sections.js +1 -7
  31. package/sandbox/apps/sandbox/translations/en/default.json +0 -33
  32. package/sandbox/apps/sandbox/translations/src/en/fields.json +0 -10
  33. package/sandbox/apps/sandbox/translations/src/en/pages.json +0 -3
  34. package/sandbox/apps/sandbox/translations/src/en/validation.json +0 -12
  35. package/sandbox/package.json +1 -1
  36. package/sandbox/public/css/app.css +2996 -1330
  37. package/sandbox/public/images/govuk-logo.svg +25 -0
  38. package/sandbox/public/js/bundle.js +4751 -2217
  39. package/sandbox/yarn.lock +4 -4
  40. package/components/amount-with-unit-select/amount-with-unit-select.js +0 -107
  41. package/components/amount-with-unit-select/fields.js +0 -15
  42. package/components/amount-with-unit-select/hooks.js +0 -168
  43. package/components/amount-with-unit-select/templates/amount-with-unit-select.html +0 -20
  44. package/components/amount-with-unit-select/utils.js +0 -191
  45. package/components/amount-with-unit-select/validation.js +0 -175
  46. package/frontend/template-mixins/partials/forms/grouped-inputs-select.html +0 -13
  47. package/frontend/template-mixins/partials/forms/grouped-inputs-text.html +0 -37
  48. package/frontend/themes/gov-uk/styles/_grouped-input.scss +0 -5
package/CHANGELOG.md CHANGED
@@ -1,3 +1,16 @@
1
+ ## 2025-12-09, Version 23.0.0 (Stable), @Rhodine-orleans-lindsay
2
+ ### Changed
3
+ - Updated cookie banner view to follow GOV.UK design system. Updated cookieSettings.js to allow for different confirmation text based on whether cookies were accepted or rejected
4
+ - Added inputmode='numeric' to date component
5
+ - Added span for checkbox error messages
6
+ - Updated imported javascript
7
+ - Added data-module attribute for govuk-skip-link for screen readers
8
+ - Removed aria-polite=live for character-count and removed pattern attribute for date input
9
+ - Replaced deprecated govuk-header__link--service-name with govuk-header__service-name
10
+ - Added a modifier for phone text input styles that accept sequences of digits
11
+ - Added govuk-template--rebranded class to govuk template html to enable govuk rebrand styles:
12
+ - Updated header and footer to follow GOV.UK design system as part of rebrand
13
+
1
14
  ## 2025-11-20, Version 22.12.0 (Stable), @dk4g @jamiecarterHO
2
15
 
3
16
  ### Infrastructure
@@ -31,7 +44,6 @@ For testing purposes, you can use the following command to generate a random val
31
44
  - For custom session timeout handling that is not linked to the redis session ttl, The following variables must be set: `CUSTOM_SESSION_EXPIRY` to the relevant expiry time e.g.600 and `USE_CUSTOM_SESSION_TIMEOUT` to true.
32
45
  - If a behaviour is required on the '/session-timeout` step, the '/session-timeout' step must be set in the project's index.js, along with any relevant behaviours.
33
46
 
34
-
35
47
  ## 2025-10-10, Version 22.10.4 (Stable), @dk4g
36
48
  ### Security
37
49
  - Upgraded axios version to address a security vulnerability
package/README.md CHANGED
@@ -1012,83 +1012,6 @@ Using the translation key `fields.field-name.label` will return different values
1012
1012
 
1013
1013
  # HOF Components
1014
1014
 
1015
- ## AmountWithUnitSelect Component
1016
-
1017
- A component for handling the rendering, processing, and validation of a text input (amount) field and a select-dropdown input field (unit) used in HOF applications.
1018
-
1019
- ### Usage
1020
-
1021
- In your fields config:
1022
-
1023
- ```js
1024
- const amountWithUnitSelectComponent = require("hof").components.amountWithUnitSelect;
1025
-
1026
- module.exports = {
1027
- "amountWithUnitSelect-field": amountWithUnitSelectComponent("amountWithUnitSelect", {
1028
- mixin: 'input-amount-with-unit-select',
1029
- amountLabel: "Amount:", // If not specified, defaults to 'Amount'
1030
- unitLabel: "Unit:", // If not specified, defaults to 'Unit'
1031
- options: [
1032
- { "null": "Select..." }, // If a null option is not specified, a default null option with the label 'Select...' is included in the options
1033
- { "label": "untranslated option label 1", "value": "1" },
1034
- { "label": "untranslated option label 2", "value": "2" }
1035
- ],
1036
- hint: "E.g: 5 Kilogram",
1037
- legend: 'Enter An Amount',
1038
- isPageHeading: 'true',
1039
- amountOptional: 'false', // If not specified, defaults to false if the required validator is not applied, otherwise true
1040
- unitOptional: 'true', // If not specified, defaults to false if the required validator is not applied, otherwise true
1041
- validate: ['alphanum']
1042
- }),
1043
- };
1044
- ```
1045
-
1046
- The above example will create a new AmountWithUnitSelect component with the key `'amountWithUnitSelect-field'`.
1047
- It will set the AmountWithUnitSelect component's text input label to `'Amount:'` (instead of the default `'Amount'`) and the select input label to `'Unit:'` (instead of the default `'Unit'`).
1048
- The component's Select input will have the dropdown options `'Select...'` (mapping to the value `'null'`), `'untranslated option label 1'` (mapping to the value `'1'`), and `'untranslated option label 2'` (mapping to the value `'2'`).
1049
- The component's hint text will be set to `'E.G: 5 Kilogram'`, the field title/legend will be set to `'Enter An Amount'`, and the page heading will be the field's title.
1050
- In terms of validation, the text input (amount) will have the `'required'` validator applied, but the select input (unit) will not (a value will not be required to be selected), and the text field will have the `'alphanum'` validator applied.
1051
-
1052
- ### Configuration
1053
-
1054
- The following optional configuration options are supported:
1055
-
1056
- - `validate {String|Array}` – Validators to use on the text input field. The `'alphanum'` and `'required'` validators are likely to be used.
1057
- - `template` – An absolute path to an alternate template.
1058
- - `amountLabel {String}` – A custom label for the text input field (amount). Defaults to `'Amount'` if omitted. This can also be specified and defined in the field translations.
1059
- - `unitLabel {String}` – A custom label for the select input field (unit). Defaults to `'Unit'` if omitted. This can also be specified and defined in the field translations.
1060
- - `options {Array}` – A list of labels and corresponding values (options) for the select input field to present. Each option has the format `{ "label": "", "value": ""}`. The default/null option is defined with the format `{ "null": "Select" }` (where the text `'Select'` is the label and can be modified). If the null option is not defined, a default null option will be included in the options with the label `'Select...'`. This can also be specified and defined in the field translations.
1061
- - `hint {String}` – Hint text displayed for both fields. This can also be specified and defined in the field translations.
1062
- - `legend {String}` – Legend text displayed for both fields. This can also be specified and defined in the field translations.
1063
- - `isPageHeading {Boolean}` – Sets the legend as the page heading on single-page questions.
1064
- - `amountOptional {Boolean}` – The text input (amount) defaults to `''` (empty string) if omitted. Defaults to `false`. If the `'required'` validator is defined in the `validate` configuration option, then this configuration is ignored (both fields are made mandatory).
1065
- - `unitOptional {Boolean}` – The select input (unit) defaults to `null` if omitted. Defaults to `false`. If the `'required'` validator is defined in the `validate` configuration option, then this configuration is ignored (both fields are made mandatory).
1066
-
1067
- ### Validation Error Messages
1068
-
1069
- In Validation.json (within the translations):
1070
-
1071
- ```js
1072
- "amountWithUnitSelect": {
1073
- "default": "Enter the amount in the correct format; for example, 10 Litres",
1074
- "alphanum": "The amount must not contain any special characters",
1075
- "required": "Enter an amount and a unit value"
1076
- },
1077
- "amountWithUnitSelect-unit": {
1078
- "default": "A valid value must be selected as the amount unit",
1079
- "required": "A unit must be selected for the amount"
1080
- },
1081
- "amountWithUnitSelect-amount": {
1082
- "alphanum": "The amount must not be an alphanum"
1083
- }
1084
- ```
1085
-
1086
- Validation error messages can be defined for a specific child component that errored by adding a JSON object with a key that has the component's name (I.E. `'amountWithUnitSelect'`) followed by a hyphen and the child component's name (I.E. '-amount' or '-unit'). So to define an error message, for the `'required'` validation error, for specifically the unit component, an `'amountWithUnitSelect-unit'` object can be created (like in the example above) with a validator's name and the error message to show for it respectively, set as a key:value pair in the object (E.G. `"required": "A unit must be selected for the amount" within "amountWithUnitSelect-unit"` - like in the example).
1087
- Validation error messages defined specifically for child components, for a given type of validation error, (such as `'required'` for `'amountWithUnitSelect-unit'`) will take precedence over error messages defined for the same validation error in the parent. So in this case, the `"required": "Enter an amount and a unit value"` validation message defined in the `"amountWithUnitSelect"` JSON object in the above example will not show when the `"amountWithUnitSelect-unit"` `'required'` validation error message is defined. If there was no `'required'` error message defined for, say, the `"amountWithUnitSelect-amount"` object (like in the example above), the `"amountWithUnitSelect"` object's `'required'` error message would show if the `'required'` validation error is triggered on the 'amount' child component (I.E. When an amount value is not provided).
1088
- The `'default'` catch all validation error message can also be defined in a similar manner for the child components to override the parent component's defined `'default'` error message.
1089
-
1090
- So the example above will create a scenario where `'required'` validation errors triggered on the 'unit' field will display the error message `"A unit must be selected for the amount"` (specified in the `"amountWithUnitSelect-unit"` JSON object). Any `'required'` validation errors triggered on the 'amount' field will display the error message `"Enter an amount and a unit value"` (specified in the `"amountWithUnitSelect"` JSON object - as there is no `'required'` error message defined specifically for the 'amount' field (withing `"amountWithUnitSelect-amount"`)).
1091
-
1092
1015
  ## Date Component
1093
1016
 
1094
1017
  A component for handling the rendering and processing of 3-input date fields used in HOF Applications.
@@ -1720,7 +1643,6 @@ currency
1720
1643
  select
1721
1644
  input-text
1722
1645
  input-date
1723
- input-amount-with-unit-select
1724
1646
  input-text-compound
1725
1647
  input-text-code
1726
1648
  input-number
@@ -10,12 +10,27 @@ module.exports = config => {
10
10
  if (!config.images) {
11
11
  return Promise.resolve();
12
12
  }
13
+ const imagesOutput = config.images.out;
13
14
 
14
- return new Promise((resolve, reject) => {
15
- fs.stat(config.images.src, err => err ? reject(err) : resolve());
16
- })
17
- .then(() => mkdir(config.images.out))
18
- .then(() => spawn('cp', ['-r', config.images.src, config.images.out]))
15
+ // Due to govuk rebrand logo, images are copied from multiple sources & mapping can cause 'File exists' error.
16
+ // Remove if exists as a file
17
+ if (fs.existsSync(imagesOutput) && !fs.lstatSync(imagesOutput).isDirectory()) {
18
+ fs.unlinkSync(imagesOutput);
19
+ }
20
+ // Ensure directory exists
21
+ if (!fs.existsSync(imagesOutput)) {
22
+ fs.mkdirSync(imagesOutput, { recursive: true });
23
+ }
24
+ const srcs = Array.isArray(config.images.src) ? config.images.src : [config.images.src];
25
+
26
+ return Promise.all(srcs.map(src => {
27
+ if (!fs.existsSync(src)) {
28
+ console.log(`${chalk.yellow('warning')}: Skipping missing images folder: ${src}`);
29
+ return Promise.resolve();
30
+ }
31
+ return mkdir(imagesOutput)
32
+ .then(() => spawn('cp', ['-r', `${src}/.`, imagesOutput]));
33
+ }))
19
34
  .catch(e => {
20
35
  if (e.code !== 'ENOENT') {
21
36
  throw e;
@@ -32,7 +32,14 @@ module.exports = config => {
32
32
  }, {});
33
33
 
34
34
  function triggersTask(file) {
35
- return Object.keys(matchers).filter(key => match(file, matchers[key]));
35
+ return Object.keys(matchers).filter(key => {
36
+ const pattern = matchers[key];
37
+ // Only call minimatch if pattern is a non-empty string or array of strings
38
+ if (Array.isArray(pattern)) {
39
+ return pattern.some(p => typeof p === 'string' && p.length > 0 && match(file, p));
40
+ }
41
+ return typeof pattern === 'string' && pattern.length > 0 && match(file, pattern);
42
+ });
36
43
  }
37
44
 
38
45
  function restart() {
@@ -94,7 +101,7 @@ module.exports = config => {
94
101
  process.stdin.setEncoding('utf8');
95
102
  process.stdin.on('data', data => {
96
103
  const dataType = (data + '').trim().toLowerCase();
97
- if (dataType === config.watch.restart) {
104
+ if (dataType === config.watch.restart) {
98
105
  restart();
99
106
  }
100
107
  });
@@ -118,6 +125,7 @@ module.exports = config => {
118
125
  const rootDir = require('path').resolve(__dirname, '../../../');
119
126
  ignored.push(`${rootDir}/frontend/govuk-template/govuk_template_generated.html`);
120
127
  watchLocation = [rootDir, '.'];
128
+ process.env.SESSION_SECRET = require('crypto').randomBytes(16).toString('hex');
121
129
  }
122
130
 
123
131
  const watcher = chokidar.watch(watchLocation, { ignored });
@@ -6,7 +6,7 @@
6
6
  {{#isPageHeading}}</h1>{{/isPageHeading}}
7
7
  </legend>
8
8
  {{#hint}}
9
- <span id="{{key}}-hint" class="govuk-hint">{{{hint}}}</span>
9
+ <div id="{{key}}-hint" class="govuk-hint">{{{hint}}}</div>
10
10
  {{/hint}}
11
11
  {{#error}}
12
12
  <p id="{{key}}-error" class="govuk-error-message">
@@ -5,7 +5,6 @@ module.exports = {
5
5
  clearSession: require('./clear-session'),
6
6
  combineAndLoopFields: require('./combine-and-loop-fields'),
7
7
  date: require('./date'),
8
- amountWithUnitSelect: require('./amount-with-unit-select/amount-with-unit-select'),
9
8
  emailer: require('./emailer'),
10
9
  homeOfficeCountries: require('./homeoffice-countries'),
11
10
  notify: require('./notify'),
@@ -1,4 +1,8 @@
1
1
  'use strict';
2
+ const toolkitImages =
3
+ process.env.HOF_SANDBOX === 'true'
4
+ ? '../frontend/toolkit/assets/rebrand/images'
5
+ : 'node_modules/hof/frontend/toolkit/assets/rebrand/images';
2
6
 
3
7
  module.exports = {
4
8
  browserify: {
@@ -24,8 +28,8 @@ module.exports = {
24
28
  shared: 'apps/common/translations/src'
25
29
  },
26
30
  images: {
27
- src: 'assets/images',
28
- out: 'public',
31
+ src: ['assets/rebrand/images', 'assets/images', toolkitImages],
32
+ out: 'public/images',
29
33
  match: 'assets/images/**/*',
30
34
  restart: false
31
35
  },
@@ -200,12 +200,10 @@ module.exports = class Controller extends BaseController {
200
200
  req.form.errors[key].errorLinkId = key + '-' + field.options[0];
201
201
  }
202
202
  // eslint-disable-next-line brace-style
203
- } else if (field && field.mixin === 'input-date') {
204
- // get first field for date input control
203
+ }
204
+ // get first field for date input control
205
+ else if (field && field.mixin === 'input-date') {
205
206
  req.form.errors[key].errorLinkId = key + '-day';
206
- } else if (field && field.mixin === 'input-amount-with-unit-select') {
207
- // get first field for amount-unit input control
208
- req.form.errors[key].errorLinkId = key + '-amount';
209
207
  } else {
210
208
  req.form.errors[key].errorLinkId = key;
211
209
  }
@@ -47,7 +47,7 @@ function validate(fields) {
47
47
  fields[key].validate = [fields[key].validate];
48
48
  }
49
49
 
50
- if (fields[key].options && !fields[key].groupedFieldsWithOptions) {
50
+ if (fields[key].options) {
51
51
  fields[key].validate = fields[key].validate || [];
52
52
  fields[key].validate.push({
53
53
  type: 'equal',
@@ -177,4 +177,5 @@ module.exports = Validators = {
177
177
  // eslint-disable-next-line max-len
178
178
  return value === '' || Validators.regex(value, /^(([GIR] ?0[A]{2})|((([A-Z][0-9]{1,2})|(([A-Z][A-HJ-Y][0-9]{1,2})|(([A-Z][0-9][A-Z])|([A-Z][A-HJ-Y][0-9]?[A-Z])))) ?[0-9][A-Z]{2}))$/i);
179
179
  }
180
+
180
181
  };
@@ -3,6 +3,7 @@
3
3
  module.exports = {
4
4
  htmlLang: '{{htmlLang}}',
5
5
  assetPath: '{{govukAssetPath}}',
6
+ assetRebrandPath: '{{govukAssetPath}}rebrand/',
6
7
  afterHeader: '{{$afterHeader}}{{/afterHeader}}',
7
8
  bodyClasses: '{{$bodyClasses}}{{/bodyClasses}}',
8
9
  bodyStart: '{{$bodyStart}}{{/bodyStart}}',
@@ -1,31 +1,24 @@
1
1
 
2
2
  <!DOCTYPE html>
3
3
  <!--[if lt IE 9]><html class="lte-ie8" lang="{{ htmlLang }}"><![endif]-->
4
- <!--[if gt IE 8]><!--><html lang="{{ htmlLang }}" class="govuk-template"><!--<![endif]-->
4
+ <!--[if gt IE 8]><!--><html lang="{{ htmlLang }}" class="govuk-template--rebranded"><!--<![endif]-->
5
5
  <head>
6
6
  <meta charset="utf-8" />
7
7
  <title>{{ pageTitle }}</title>
8
8
  {{{ head }}}
9
9
 
10
- <link rel="shortcut icon" sizes="16x16 32x32 48x48" href="{{assetPath}}images/favicon.ico" type="image/x-icon">
11
- <link rel="mask-icon" href="{{assetPath}}images/govuk-mask-icon.svg" color="#0b0c0c">
12
- <link rel="apple-touch-icon" sizes="180x180" href="{{assetPath}}images/govuk-apple-touch-icon-180x180.png">
13
- <link rel="apple-touch-icon" sizes="167x167" href="{{assetPath}}images/govuk-apple-touch-icon-167x167.png">
14
- <link rel="apple-touch-icon" sizes="152x152" href="{{assetPath}}images/govuk-apple-touch-icon-152x152.png">
15
- <link rel="apple-touch-icon" href="{{assetPath}}images/govuk-apple-touch-icon.png">
16
-
17
-
18
- <meta name="theme-color" content="#0b0c0c" />
19
-
20
- <meta name="viewport" content="width=device-width, initial-scale=1">
21
-
22
-
23
- <meta property="og:image" content="{{assetPath}}images/opengraph-image.png">
10
+ <meta name="theme-color" content="#1d70b8">
11
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
12
+ <link rel="icon" sizes="48x48" href="{{assetRebrandPath}}images/favicon.ico">
13
+ <link rel="icon" sizes="any" href="{{assetRebrandPath}}images/favicon.svg" type="image/svg+xml">
14
+ <link rel="mask-icon" href="{{assetRebrandPath}}images/govuk-icon-mask.svg" color="#1d70b8">
15
+ <link rel="apple-touch-icon" href="{{assetRebrandPath}}images/govuk-icon-180.png">
16
+ <link rel="manifest" href="{{assetRebrandPath}}manifest.json">
17
+ <meta property="og:image" content="{{assetRebrandPath}}images/govuk-opengraph-image.png">
24
18
  </head>
25
19
 
26
20
  <body class="{{ bodyClasses }} govuk-template__body js-enabled" >
27
- <script>document.body.className = ((document.body.className) ? document.body.className + ' js-enabled' : 'js-enabled');</script>
28
-
21
+ <script>document.body.className += ' js-enabled' + ('noModule' in HTMLScriptElement.prototype ? ' govuk-frontend-supported' : '');</script>
29
22
 
30
23
 
31
24
  <div id="global-cookie-message" class="gem-c-cookie-banner govuk-clearfix" data-module="cookie-banner" role="region" aria-label="cookie banner" data-nosnippet="">
@@ -39,19 +32,13 @@
39
32
 
40
33
  <div class="govuk-header__logo">
41
34
  <a href="{{{ homepageUrl }}}" title="{{ logoLinkTitle }}" id="logo" class="govuk-header__link govuk-header__link--homepage" target="_blank" data-module="track-click" data-track-category="homeLinkClicked" data-track-action="homeHeader">
42
- <span class="govuk-header__logotype">
43
- <!--[if gt IE 8]><!-->
44
- <svg aria-hidden="true" focusable="false" class="govuk-header__logotype-crown" xmlns="http://www.w3.org/2000/svg\" viewBox="0 0 32 30" height="30" width="32">
45
- <path fill="currentColor" fill-rule="evenodd" d="M22.6 10.4c-1 .4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s-.1 2-1 2.4m-5.9 6.7c-.9.4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s-.1 2-1 2.4m10.8-3.7c-1 .4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s0 2-1 2.4m3.3 4.8c-1 .4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s-.1 2-1 2.4M17 4.7l2.3 1.2V2.5l-2.3.7-.2-.2.9-3h-3.4l.9 3-.2.2c-.1.1-2.3-.7-2.3-.7v3.4L15 4.7c.1.1.1.2.2.2l-1.3 4c-.1.2-.1.4-.1.6 0 1.1.8 2 1.9 2.2h.7c1-.2 1.9-1.1 1.9-2.1 0-.2 0-.4-.1-.6l-1.3-4c-.1-.2 0-.2.1-.3m-7.6 5.7c.9.4 2-.1 2.4-1 .4-.9-.1-2-1-2.4-.9-.4-2 .1-2.4 1s0 2 1 2.4m-5 3c.9.4 2-.1 2.4-1 .4-.9-.1-2-1-2.4-.9-.4-2 .1-2.4 1s.1 2 1 2.4m-3.2 4.8c.9.4 2-.1 2.4-1 .4-.9-.1-2-1-2.4-.9-.4-2 .1-2.4 1s0 2 1 2.4m14.8 11c4.4 0 8.6.3 12.3.8 1.1-4.5 2.4-7 3.7-8.8l-2.5-.9c.2 1.3.3 1.9 0 2.7-.4-.4-.8-1.1-1.1-2.3l-1.2 4c.7-.5 1.3-.8 2-.9-1.1 2.5-2.6 3.1-3.5 3-1.1-.2-1.7-1.2-1.5-2.1.3-1.2 1.5-1.5 2.1-.1 1.1-2.3-.8-3-2-2.3 1.9-1.9 2.1-3.5.6-5.6-2.1 1.6-2.1 3.2-1.2 5.5-1.2-1.4-3.2-.6-2.5 1.6.9-1.4 2.1-.5 1.9.8-.2 1.1-1.7 2.1-3.5 1.9-2.7-.2-2.9-2.1-2.9-3.6.7-.1 1.9.5 2.9 1.9l.4-4.3c-1.1 1.1-2.1 1.4-3.2 1.4.4-1.2 2.1-3 2.1-3h-5.4s1.7 1.9 2.1 3c-1.1 0-2.1-.2-3.2-1.4l.4 4.3c1-1.4 2.2-2 2.9-1.9-.1 1.5-.2 3.4-2.9 3.6-1.9.2-3.4-.8-3.5-1.9-.2-1.3 1-2.2 1.9-.8.7-2.3-1.2-3-2.5-1.6.9-2.2.9-3.9-1.2-5.5-1.5 2-1.3 3.7.6 5.6-1.2-.7-3.1 0-2 2.3.6-1.4 1.8-1.1 2.1.1.2.9-.3 1.9-1.5 2.1-.9.2-2.4-.5-3.5-3 .6 0 1.2.3 2 .9l-1.2-4c-.3 1.1-.7 1.9-1.1 2.3-.3-.8-.2-1.4 0-2.7l-2.9.9C1.3 23 2.6 25.5 3.7 30c3.7-.5 7.9-.8 12.3-.8"></path>
46
- </svg>
47
- <!--<![endif]-->
48
- <!--[if IE 8]>
49
- <img src="{{ assetPath }}images/govuk-logotype-tudor-crown.png" class="govuk-header__logotype-crown-fallback-image" width="32" height="30" alt="">
50
- <![endif]-->
51
- </span>
52
- <span class="govuk-header__logotype-text">
53
- {{{ globalHeaderText }}}
54
- </span>
35
+ <!--[if gt IE 8]><!-->
36
+ <div id="govuk-header__logo"></div>
37
+ <img src="/public/images/govuk-logo.svg" id="govuk-header__logo" alt="Logo" loading="lazy" />
38
+ <!--<![endif]-->
39
+ <!--[if IE 8]>
40
+ <img src="{{ assetRebrandPath }}images/govuk-logotype-tudor-crown.png" class="govuk-header__logotype-crown-fallback-image" width="32" height="30" alt="">
41
+ <![endif]-->
55
42
  </a>
56
43
  </div>
57
44
  {{{ insideHeader }}}
@@ -66,25 +53,54 @@
66
53
 
67
54
  {{{ content }}}
68
55
 
69
- <footer class="govuk-footer" id="footer" role="contentinfo">
70
-
56
+ <footer class="govuk-footer">
71
57
  <div class="govuk-width-container">
72
- {{{ footerTop }}}
73
-
58
+ <svg
59
+ focusable="false"
60
+ role="presentation"
61
+ xmlns="http://www.w3.org/2000/svg"
62
+ viewBox="0 0 64 60"
63
+ height="30"
64
+ width="32"
65
+ fill="currentcolor" class="govuk-footer__crown">
66
+ <g>
67
+ <circle cx="20" cy="17.6" r="3.7" />
68
+ <circle cx="10.2" cy="23.5" r="3.7" />
69
+ <circle cx="3.7" cy="33.2" r="3.7" />
70
+ <circle cx="31.7" cy="30.6" r="3.7" />
71
+ <circle cx="43.3" cy="17.6" r="3.7" />
72
+ <circle cx="53.2" cy="23.5" r="3.7" />
73
+ <circle cx="59.7" cy="33.2" r="3.7" />
74
+ <circle cx="31.7" cy="30.6" r="3.7" />
75
+ <path d="M33.1,9.8c.2-.1.3-.3.5-.5l4.6,2.4v-6.8l-4.6,1.5c-.1-.2-.3-.3-.5-.5l1.9-5.9h-6.7l1.9,5.9c-.2.1-.3.3-.5.5l-4.6-1.5v6.8l4.6-2.4c.1.2.3.3.5.5l-2.6,8c-.9,2.8,1.2,5.7,4.1,5.7h0c3,0,5.1-2.9,4.1-5.7l-2.6-8ZM37,37.9s-3.4,3.8-4.1,6.1c2.2,0,4.2-.5,6.4-2.8l-.7,8.5c-2-2.8-4.4-4.1-5.7-3.8.1,3.1.5,6.7,5.8,7.2,3.7.3,6.7-1.5,7-3.8.4-2.6-2-4.3-3.7-1.6-1.4-4.5,2.4-6.1,4.9-3.2-1.9-4.5-1.8-7.7,2.4-10.9,3,4,2.6,7.3-1.2,11.1,2.4-1.3,6.2,0,4,4.6-1.2-2.8-3.7-2.2-4.2.2-.3,1.7.7,3.7,3,4.2,1.9.3,4.7-.9,7-5.9-1.3,0-2.4.7-3.9,1.7l2.4-8c.6,2.3,1.4,3.7,2.2,4.5.6-1.6.5-2.8,0-5.3l5,1.8c-2.6,3.6-5.2,8.7-7.3,17.5-7.4-1.1-15.7-1.7-24.5-1.7h0c-8.8,0-17.1.6-24.5,1.7-2.1-8.9-4.7-13.9-7.3-17.5l5-1.8c-.5,2.5-.6,3.7,0,5.3.8-.8,1.6-2.3,2.2-4.5l2.4,8c-1.5-1-2.6-1.7-3.9-1.7,2.3,5,5.2,6.2,7,5.9,2.3-.4,3.3-2.4,3-4.2-.5-2.4-3-3.1-4.2-.2-2.2-4.6,1.6-6,4-4.6-3.7-3.7-4.2-7.1-1.2-11.1,4.2,3.2,4.3,6.4,2.4,10.9,2.5-2.8,6.3-1.3,4.9,3.2-1.8-2.7-4.1-1-3.7,1.6.3,2.3,3.3,4.1,7,3.8,5.4-.5,5.7-4.2,5.8-7.2-1.3-.2-3.7,1-5.7,3.8l-.7-8.5c2.2,2.3,4.2,2.7,6.4,2.8-.7-2.3-4.1-6.1-4.1-6.1h10.6,0Z" />
76
+ </g>
77
+ </svg>
74
78
  <div class="govuk-footer__meta">
75
79
  <div class="govuk-footer__meta-item govuk-footer__meta-item--grow">
76
- <h2 class="govuk-visually-hidden">Support links</h2>
80
+ <h2 class="govuk-visually-hidden">Support links</h2>
77
81
  {{{ footerSupportLinks }}}
78
-
79
- <svg aria-hidden="true" focusable="false" class="govuk-footer__licence-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 483.2 195.7" height="17" width="41">
80
- <path fill="currentColor" d="M421.5 142.8V.1l-50.7 32.3v161.1h112.4v-50.7zm-122.3-9.6A47.12 47.12 0 0 1 221 97.8c0-26 21.1-47.1 47.1-47.1 16.7 0 31.4 8.7 39.7 21.8l42.7-27.2A97.63 97.63 0 0 0 268.1 0c-36.5 0-68.3 20.1-85.1 49.7A98 98 0 0 0 97.8 0C43.9 0 0 43.9 0 97.8s43.9 97.8 97.8 97.8c36.5 0 68.3-20.1 85.1-49.7a97.76 97.76 0 0 0 149.6 25.4l19.4 22.2h3v-87.8h-80l24.3 27.5zM97.8 145c-26 0-47.1-21.1-47.1-47.1s21.1-47.1 47.1-47.1 47.2 21 47.2 47S123.8 145 97.8 145"></path>
82
+ <svg
83
+ aria-hidden="true"
84
+ focusable="false"
85
+ class="govuk-footer__licence-logo"
86
+ xmlns="http://www.w3.org/2000/svg"
87
+ viewBox="0 0 483.2 195.7"
88
+ height="17"
89
+ width="41">
90
+ <path
91
+ fill="currentColor"
92
+ d="M421.5 142.8V.1l-50.7 32.3v161.1h112.4v-50.7zm-122.3-9.6A47.12 47.12 0 0 1 221 97.8c0-26 21.1-47.1 47.1-47.1 16.7 0 31.4 8.7 39.7 21.8l42.7-27.2A97.63 97.63 0 0 0 268.1 0c-36.5 0-68.3 20.1-85.1 49.7A98 98 0 0 0 97.8 0C43.9 0 0 43.9 0 97.8s43.9 97.8 97.8 97.8c36.5 0 68.3-20.1 85.1-49.7a97.76 97.76 0 0 0 149.6 25.4l19.4 22.2h3v-87.8h-80l24.3 27.5zM97.8 145c-26 0-47.1-21.1-47.1-47.1s21.1-47.1 47.1-47.1 47.2 21 47.2 47S123.8 145 97.8 145" />
81
93
  </svg>
82
-
83
- <span class="govuk-footer__licence-description">{{{ licenceMessage }}}</span>
94
+ <span class="govuk-footer__licence-description">
95
+ {{{ licenceMessage }}}
96
+ </span>
84
97
  </div>
85
-
86
98
  <div class="govuk-footer__meta-item">
87
- <a class="govuk-footer__link govuk-footer__copyright-logo" id="copyright-logo" target="_blank" href="https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/">{{{ crownCopyrightMessage }}}</a>
99
+ <a
100
+ class="govuk-footer__link govuk-footer__copyright-logo"
101
+ href="https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/">
102
+ {{{ crownCopyrightMessage }}}
103
+ </a>
88
104
  </div>
89
105
  </div>
90
106
  </div>
@@ -0,0 +1,118 @@
1
+
2
+ <!DOCTYPE html>
3
+ <!--[if lt IE 9]><html class="lte-ie8" lang="{{htmlLang}}"><![endif]-->
4
+ <!--[if gt IE 8]><!--><html lang="{{htmlLang}}" class="govuk-template--rebranded"><!--<![endif]-->
5
+ <head>
6
+ <meta charset="utf-8" />
7
+ <title>{{$pageTitle}}{{/pageTitle}}</title>
8
+ {{$head}}{{/head}}
9
+
10
+ <meta name="theme-color" content="#1d70b8">
11
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
12
+ <link rel="icon" sizes="48x48" href="{{govukAssetPath}}rebrand/images/favicon.ico">
13
+ <link rel="icon" sizes="any" href="{{govukAssetPath}}rebrand/images/favicon.svg" type="image/svg+xml">
14
+ <link rel="mask-icon" href="{{govukAssetPath}}rebrand/images/govuk-icon-mask.svg" color="#1d70b8">
15
+ <link rel="apple-touch-icon" href="{{govukAssetPath}}rebrand/images/govuk-icon-180.png">
16
+ <link rel="manifest" href="{{govukAssetPath}}rebrand/manifest.json">
17
+ <meta property="og:image" content="{{govukAssetPath}}rebrand/images/govuk-opengraph-image.png">
18
+ </head>
19
+
20
+ <body class="{{$bodyClasses}}{{/bodyClasses}} govuk-template__body js-enabled" >
21
+ <script {{#nonce}}nonce="{{nonce}}"{{/nonce}}>document.body.className += ' js-enabled' + ('noModule' in HTMLScriptElement.prototype ? ' govuk-frontend-supported' : '');</script>
22
+
23
+
24
+ <div id="global-cookie-message" class="gem-c-cookie-banner govuk-clearfix" data-module="cookie-banner" role="region" aria-label="cookie banner" data-nosnippet="">
25
+ {{$cookieMessage}}{{/cookieMessage}}
26
+ </div>
27
+
28
+ {{$bodyStart}}{{/bodyStart}}
29
+
30
+ <header role="banner" id="govuk-header" class="{{$headerClass}}{{/headerClass}}">
31
+ <div class="govuk-header__container govuk-width-container">
32
+
33
+ <div class="govuk-header__logo">
34
+ <a href="{{$homepageUrl}}https://www.gov.uk{{/homepageUrl}}" title="{{$logoLinkTitle}}Go to the GOV.UK homepage{{/logoLinkTitle}}" id="logo" class="govuk-header__link govuk-header__link--homepage" target="_blank" data-module="track-click" data-track-category="homeLinkClicked" data-track-action="homeHeader">
35
+ <!--[if gt IE 8]><!-->
36
+ <div id="govuk-header__logo"></div>
37
+ <img src="/public/images/govuk-logo.svg" id="govuk-header__logo" alt="Logo" loading="lazy" />
38
+ <!--<![endif]-->
39
+ <!--[if IE 8]>
40
+ <img src="{{govukAssetPath}}rebrand/images/govuk-logotype-tudor-crown.png" class="govuk-header__logotype-crown-fallback-image" width="32" height="30" alt="">
41
+ <![endif]-->
42
+ </a>
43
+ </div>
44
+ {{$insideHeader}}{{/insideHeader}}
45
+
46
+ {{$propositionHeader}}{{/propositionHeader}}
47
+ </div>
48
+ </header>
49
+
50
+
51
+ {{$afterHeader}}{{/afterHeader}}
52
+
53
+
54
+ {{$main}}{{/main}}
55
+
56
+ <footer class="govuk-footer">
57
+ <div class="govuk-width-container">
58
+ <svg
59
+ focusable="false"
60
+ role="presentation"
61
+ xmlns="http://www.w3.org/2000/svg"
62
+ viewBox="0 0 64 60"
63
+ height="30"
64
+ width="32"
65
+ fill="currentcolor" class="govuk-footer__crown">
66
+ <g>
67
+ <circle cx="20" cy="17.6" r="3.7" />
68
+ <circle cx="10.2" cy="23.5" r="3.7" />
69
+ <circle cx="3.7" cy="33.2" r="3.7" />
70
+ <circle cx="31.7" cy="30.6" r="3.7" />
71
+ <circle cx="43.3" cy="17.6" r="3.7" />
72
+ <circle cx="53.2" cy="23.5" r="3.7" />
73
+ <circle cx="59.7" cy="33.2" r="3.7" />
74
+ <circle cx="31.7" cy="30.6" r="3.7" />
75
+ <path d="M33.1,9.8c.2-.1.3-.3.5-.5l4.6,2.4v-6.8l-4.6,1.5c-.1-.2-.3-.3-.5-.5l1.9-5.9h-6.7l1.9,5.9c-.2.1-.3.3-.5.5l-4.6-1.5v6.8l4.6-2.4c.1.2.3.3.5.5l-2.6,8c-.9,2.8,1.2,5.7,4.1,5.7h0c3,0,5.1-2.9,4.1-5.7l-2.6-8ZM37,37.9s-3.4,3.8-4.1,6.1c2.2,0,4.2-.5,6.4-2.8l-.7,8.5c-2-2.8-4.4-4.1-5.7-3.8.1,3.1.5,6.7,5.8,7.2,3.7.3,6.7-1.5,7-3.8.4-2.6-2-4.3-3.7-1.6-1.4-4.5,2.4-6.1,4.9-3.2-1.9-4.5-1.8-7.7,2.4-10.9,3,4,2.6,7.3-1.2,11.1,2.4-1.3,6.2,0,4,4.6-1.2-2.8-3.7-2.2-4.2.2-.3,1.7.7,3.7,3,4.2,1.9.3,4.7-.9,7-5.9-1.3,0-2.4.7-3.9,1.7l2.4-8c.6,2.3,1.4,3.7,2.2,4.5.6-1.6.5-2.8,0-5.3l5,1.8c-2.6,3.6-5.2,8.7-7.3,17.5-7.4-1.1-15.7-1.7-24.5-1.7h0c-8.8,0-17.1.6-24.5,1.7-2.1-8.9-4.7-13.9-7.3-17.5l5-1.8c-.5,2.5-.6,3.7,0,5.3.8-.8,1.6-2.3,2.2-4.5l2.4,8c-1.5-1-2.6-1.7-3.9-1.7,2.3,5,5.2,6.2,7,5.9,2.3-.4,3.3-2.4,3-4.2-.5-2.4-3-3.1-4.2-.2-2.2-4.6,1.6-6,4-4.6-3.7-3.7-4.2-7.1-1.2-11.1,4.2,3.2,4.3,6.4,2.4,10.9,2.5-2.8,6.3-1.3,4.9,3.2-1.8-2.7-4.1-1-3.7,1.6.3,2.3,3.3,4.1,7,3.8,5.4-.5,5.7-4.2,5.8-7.2-1.3-.2-3.7,1-5.7,3.8l-.7-8.5c2.2,2.3,4.2,2.7,6.4,2.8-.7-2.3-4.1-6.1-4.1-6.1h10.6,0Z" />
76
+ </g>
77
+ </svg>
78
+ <div class="govuk-footer__meta">
79
+ <div class="govuk-footer__meta-item govuk-footer__meta-item--grow">
80
+ <h2 class="govuk-visually-hidden">Support links</h2>
81
+ {{$footerSupportLinks}}{{/footerSupportLinks}}
82
+ <svg
83
+ aria-hidden="true"
84
+ focusable="false"
85
+ class="govuk-footer__licence-logo"
86
+ xmlns="http://www.w3.org/2000/svg"
87
+ viewBox="0 0 483.2 195.7"
88
+ height="17"
89
+ width="41">
90
+ <path
91
+ fill="currentColor"
92
+ d="M421.5 142.8V.1l-50.7 32.3v161.1h112.4v-50.7zm-122.3-9.6A47.12 47.12 0 0 1 221 97.8c0-26 21.1-47.1 47.1-47.1 16.7 0 31.4 8.7 39.7 21.8l42.7-27.2A97.63 97.63 0 0 0 268.1 0c-36.5 0-68.3 20.1-85.1 49.7A98 98 0 0 0 97.8 0C43.9 0 0 43.9 0 97.8s43.9 97.8 97.8 97.8c36.5 0 68.3-20.1 85.1-49.7a97.76 97.76 0 0 0 149.6 25.4l19.4 22.2h3v-87.8h-80l24.3 27.5zM97.8 145c-26 0-47.1-21.1-47.1-47.1s21.1-47.1 47.1-47.1 47.2 21 47.2 47S123.8 145 97.8 145" />
93
+ </svg>
94
+ <span class="govuk-footer__licence-description">
95
+ {{$licenceMessage}}All content is available under the <a href="https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/" id="open-government-licence" class="govuk-footer__link" target="_blank" rel="license">Open Government Licence v3.0</a>, except where otherwise stated{{/licenceMessage}}
96
+ </span>
97
+ </div>
98
+ <div class="govuk-footer__meta-item">
99
+ <a
100
+ class="govuk-footer__link govuk-footer__copyright-logo"
101
+ href="https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/">
102
+ {{$crownCopyrightMessage}}© Crown copyright{{/crownCopyrightMessage}}
103
+ </a>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ </footer>
108
+
109
+ <div id="global-app-error" class="app-error hidden"></div>
110
+
111
+
112
+ {{$bodyEnd}}{{/bodyEnd}}
113
+
114
+
115
+ <script {{#nonce}}nonce="{{nonce}}"{{/nonce}}>if (typeof window.GOVUK === 'undefined') document.body.className = document.body.className.replace('js-enabled', '');</script>
116
+
117
+ </body>
118
+ </html>