hof 20.0.0-beta.1 → 20.0.0-beta.12
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.
- package/.github/workflows/automate-publish.yml +1 -1
- package/.github/workflows/automate-tag.yml +1 -1
- package/.nyc_output/e2fdc3eb-4fd2-47e0-a392-fe5f665776a4.json +1 -0
- package/.nyc_output/processinfo/e2fdc3eb-4fd2-47e0-a392-fe5f665776a4.json +1 -0
- package/.nyc_output/processinfo/index.json +1 -1
- package/build/lib/mkdir.js +2 -2
- package/components/date/index.js +37 -24
- package/components/date/templates/date.html +3 -3
- package/components/emailer/index.js +49 -41
- package/components/emailer/transports/debug.js +1 -2
- package/components/summary/index.js +18 -0
- package/config/hof-defaults.js +5 -3
- package/config/rate-limits.js +20 -0
- package/config/sanitisation-rules.js +29 -0
- package/controller/base-controller.js +26 -8
- package/controller/controller.js +11 -15
- package/frontend/govuk-template/build/config.js +1 -1
- package/frontend/template-mixins/mixins/template-mixins.js +8 -8
- package/frontend/template-mixins/partials/forms/checkbox-group.html +3 -3
- package/frontend/template-mixins/partials/forms/input-text-group.html +3 -3
- package/frontend/template-mixins/partials/forms/option-group.html +3 -3
- package/frontend/template-mixins/partials/forms/select.html +2 -2
- package/frontend/template-mixins/partials/forms/textarea-group.html +2 -2
- package/frontend/template-mixins/partials/mixins/panel.html +3 -4
- package/frontend/template-partials/translations/src/en/errors.json +12 -0
- package/frontend/template-partials/views/partials/form.html +2 -1
- package/frontend/template-partials/views/rate-limit-error.html +10 -0
- package/frontend/themes/gov-uk/client-js/govuk-cookies.js +43 -44
- package/frontend/themes/gov-uk/client-js/index.js +2 -2
- package/frontend/themes/gov-uk/client-js/skip-to-main.js +18 -17
- package/frontend/themes/gov-uk/styles/_cookie-banner.scss +51 -1
- package/frontend/themes/gov-uk/styles/govuk.scss +5 -0
- package/frontend/toolkit/assets/javascript/form-focus.js +10 -1
- package/frontend/toolkit/assets/javascript/validation.js +6 -1
- package/index.js +9 -4
- package/lib/router.js +2 -1
- package/lib/settings.js +18 -2
- package/middleware/errors.js +32 -0
- package/middleware/index.js +2 -1
- package/middleware/rate-limiter.js +98 -0
- package/package.json +5 -6
- package/sandbox/.env +1 -1
- package/sandbox/apps/sandbox/fields.js +14 -9
- package/sandbox/apps/sandbox/index.js +1 -5
- package/sandbox/apps/sandbox/translations/en/default.json +4 -13
- package/sandbox/apps/sandbox/translations/src/en/fields.json +3 -2
- package/sandbox/apps/sandbox/translations/src/en/pages.json +2 -12
- package/sandbox/assets/scss/app.scss +0 -55
- package/sandbox/package.json +1 -0
- package/sandbox/public/css/app.css +4898 -4908
- package/sandbox/public/js/bundle.js +79 -65
- package/sandbox/server.js +7 -1
- package/sandbox/yarn.lock +20 -1
- package/transpiler/lib/write-files.js +1 -2
- package/utilities/helpers/index.js +16 -1
- package/wizard/index.js +1 -0
- package/.nyc_output/65af88d9-aebe-4d1b-a21d-6fbf7f2bbda4.json +0 -1
- package/.nyc_output/processinfo/65af88d9-aebe-4d1b-a21d-6fbf7f2bbda4.json +0 -1
@@ -213,7 +213,7 @@ module.exports = function (options) {
|
|
213
213
|
date: extension.date,
|
214
214
|
autocomplete: autocomplete,
|
215
215
|
child: field.child,
|
216
|
-
|
216
|
+
isPageHeading: field.isPageHeading,
|
217
217
|
attributes: field.attributes,
|
218
218
|
renderChild: renderChild.bind(this)
|
219
219
|
});
|
@@ -240,8 +240,7 @@ module.exports = function (options) {
|
|
240
240
|
legend: t(legendValue),
|
241
241
|
legendClassName: legendClassName,
|
242
242
|
role: opts.type === 'radio' ? 'radiogroup' : 'group',
|
243
|
-
|
244
|
-
noHeading: field.noHeading,
|
243
|
+
isPageHeading: field.isPageHeading,
|
245
244
|
detail: detail ? detail : '',
|
246
245
|
hint: conditionalTranslate(getTranslationKey(field, key, 'hint')),
|
247
246
|
options: _.map(field.options, function (obj) {
|
@@ -276,6 +275,7 @@ module.exports = function (options) {
|
|
276
275
|
value: value,
|
277
276
|
type: opts.type,
|
278
277
|
selected: selected,
|
278
|
+
radioOption: opts.type === 'radio',
|
279
279
|
toggle: toggle,
|
280
280
|
child: child,
|
281
281
|
optionHint: conditionalTranslate(optionHint) || ''
|
@@ -431,8 +431,8 @@ module.exports = function (options) {
|
|
431
431
|
year: autocomplete + '-year'
|
432
432
|
};
|
433
433
|
}
|
434
|
-
const
|
435
|
-
const formGroupClassName = (field.formGroup && field.formGroup.className) ? field.formGroup.className : ''
|
434
|
+
const isThisRequired = field.validate ? field.validate.indexOf('required') > -1 : false;
|
435
|
+
const formGroupClassName = (field.formGroup && field.formGroup.className) ? field.formGroup.className : '';
|
436
436
|
const classNameDay = (field.controlsClass && field.controlsClass.day) ? field.controlsClass.day : 'govuk-date-input__input govuk-input--width-2';
|
437
437
|
const classNameMonth = (field.controlsClass && field.controlsClass.month) ? field.controlsClass.month : 'govuk-date-input__input govuk-input--width-2';
|
438
438
|
const classNameYear = (field.controlsClass && field.controlsClass.year) ? field.controlsClass.year : 'govuk-date-input__input govuk-input--width-4';
|
@@ -440,12 +440,12 @@ module.exports = function (options) {
|
|
440
440
|
const parts = [];
|
441
441
|
|
442
442
|
if (isExact) {
|
443
|
-
const dayPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-day', { pattern: '[0-9]*', min: 1, max: 31, maxlength: 2, hintId: key + '-hint', date: true, autocomplete: autocomplete.day, formGroupClassName, className: classNameDay,
|
443
|
+
const dayPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-day', { pattern: '[0-9]*', min: 1, max: 31, maxlength: 2, hintId: key + '-hint', date: true, autocomplete: autocomplete.day, formGroupClassName, className: classNameDay, isThisRequired }));
|
444
444
|
parts.push(dayPart);
|
445
445
|
}
|
446
446
|
|
447
|
-
const monthPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-month', { pattern: '[0-9]*', min: 1, max: 12, maxlength: 2, hintId: key + '-hint', date: true, autocomplete: autocomplete.month, formGroupClassName, className: classNameMonth,
|
448
|
-
const yearPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-year', { pattern: '[0-9]*', maxlength: 4, hintId: key + '-hint', date: true, autocomplete: autocomplete.year, formGroupClassName, className: classNameYear,
|
447
|
+
const monthPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-month', { pattern: '[0-9]*', min: 1, max: 12, maxlength: 2, hintId: key + '-hint', date: true, autocomplete: autocomplete.month, formGroupClassName, className: classNameMonth, isThisRequired }));
|
448
|
+
const yearPart = compiled['partials/forms/input-text-date'].render(inputText.call(this, key + '-year', { pattern: '[0-9]*', maxlength: 4, hintId: key + '-hint', date: true, autocomplete: autocomplete.year, formGroupClassName, className: classNameYear, isThisRequired }));
|
449
449
|
|
450
450
|
return parts.concat(monthPart, yearPart).join('\n');
|
451
451
|
};
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<div id="{{key}}-group" class="govuk-form-group{{#className}} {{className}} {{/className}}{{#formGroupClassName}} {{formGroupClassName}}{{/formGroupClassName}}{{#error}} govuk-form-group--error{{/error}}">
|
2
2
|
<fieldset class="govuk-fieldset" {{#hint}} aria-describedby="{{key}}-hint"{{/hint}}>
|
3
|
-
<legend class="govuk-fieldset__legend govuk-fieldset__legend--l{{#legendClassName}} {{legendClassName}}{{/legendClassName}}">
|
4
|
-
{{
|
3
|
+
<legend class="govuk-fieldset__legend {{#isPageHeading}}govuk-fieldset__legend--l{{/isPageHeading}}{{#legendClassName}} {{legendClassName}}{{/legendClassName}}">
|
4
|
+
{{#isPageHeading}}<h1 class="govuk-fieldset__heading">{{/isPageHeading}}
|
5
5
|
{{legend}}
|
6
|
-
{{
|
6
|
+
{{#isPageHeading}}</h1>{{/isPageHeading}}
|
7
7
|
</legend>
|
8
8
|
{{#hint}}<div id="{{key}}-hint" class="govuk-hint">{{hint}}</div>{{/hint}}
|
9
9
|
{{#error}}
|
@@ -1,8 +1,8 @@
|
|
1
1
|
<div id="{{id}}-group" class="{{#compound}} form-group-compound{{/compound}}{{#formGroupClassName}}{{formGroupClassName}}{{/formGroupClassName}}{{#error}} govuk-form-group--error{{/error}}">
|
2
|
-
{{
|
2
|
+
{{#isPageHeading}}<h1 class="govuk-label-wrapper">{{/isPageHeading}}<label for="{{id}}" class="{{labelClassName}}">
|
3
3
|
{{{label}}}
|
4
4
|
</label>
|
5
|
-
{{
|
5
|
+
{{#isPageHeading}}</h1>{{/isPageHeading}}
|
6
6
|
{{#hint}}<span {{$hintId}}id="{{hintId}}" {{/hintId}}class="govuk-hint">{{hint}}</span>{{/hint}}
|
7
7
|
{{#error}}
|
8
8
|
<p class="govuk-error-message">
|
@@ -19,7 +19,7 @@
|
|
19
19
|
type="{{type}}"
|
20
20
|
name="{{id}}"
|
21
21
|
id="{{id}}"
|
22
|
-
class="govuk-input{{#className}}
|
22
|
+
class="{{^className}}govuk-input{{/className}}{{#className}}{{className}}{{/className}}{{#error}} invalid-input{{/error}}"
|
23
23
|
aria-required="{{required}}"
|
24
24
|
{{#value}} value="{{value}}"{{/value}}
|
25
25
|
{{#min}} min="{{min}}"{{/min}}
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<div id="{{key}}-group" class="govuk-form-group{{#className}} {{className}} {{/className}}{{#formGroupClassName}} {{formGroupClassName}}{{/formGroupClassName}}{{#error}} govuk-form-group--error{{/error}}">
|
2
2
|
<fieldset class="govuk-fieldset" {{#hint}} aria-describedby="{{key}}-hint"{{/hint}}>
|
3
|
-
<legend class="govuk-fieldset__legend govuk-fieldset__legend--l{{#legendClassName}} {{legendClassName}}{{/legendClassName}}">
|
4
|
-
{{
|
3
|
+
<legend class="govuk-fieldset__legend {{#isPageHeading}}govuk-fieldset__legend--l{{/isPageHeading}}{{#legendClassName}} {{legendClassName}}{{/legendClassName}}">
|
4
|
+
{{#isPageHeading}}<h1 class="govuk-fieldset__heading">{{/isPageHeading}}
|
5
5
|
{{legend}}
|
6
|
-
{{
|
6
|
+
{{#isPageHeading}}</h1>{{/isPageHeading}}
|
7
7
|
</legend>
|
8
8
|
{{#hint}}<div id="{{key}}-hint" class="govuk-hint">{{hint}}</div>{{/hint}}
|
9
9
|
{{#error}}<p id="{{key}}-error" class="govuk-error-message"><span class="govuk-visually-hidden">Error:</span> {{error.message}}</p>{{/error}}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<div id="{{id}}-group" class="{{#compound}} form-group-compound{{/compound}}{{#formGroupClassName}} {{formGroupClassName}}{{/formGroupClassName}}{{#error}} govuk-form-group--error{{/error}}">
|
2
|
-
{{
|
2
|
+
{{#isPageHeading}}<h1 class="govuk-label-wrapper">{{/isPageHeading}}<label for="{{id}}" class="{{labelClassName}}{{#isPageHeading}}govuk-label--l{{/isPageHeading}}">
|
3
3
|
{{{label}}}
|
4
4
|
{{#hint}}<span {{$hintId}}id="{{hintId}}" {{/hintId}}class="govuk-hint">{{hint}}</span>{{/hint}}
|
5
5
|
{{#error}}
|
@@ -8,7 +8,7 @@
|
|
8
8
|
</p>
|
9
9
|
{{/error}}
|
10
10
|
</label>
|
11
|
-
{{
|
11
|
+
{{#isPageHeading}}</h1>{{/isPageHeading}}
|
12
12
|
<select id="{{id}}" class="govuk-select{{#className}} {{className}}{{/className}}{{#error}} invalid-input{{/error}}" name="{{id}}" aria-required="{{required}}">
|
13
13
|
{{#options}}
|
14
14
|
<option value="{{value}}" {{#selected}}selected{{/selected}}>{{label}}</option>
|
@@ -2,7 +2,7 @@
|
|
2
2
|
<div class="govuk-character-count" data-module="govuk-character-count" data-maxlength="{{maxlength}}">
|
3
3
|
{{/maxlength}}
|
4
4
|
<div id="{{id}}-group" class="{{#compound}}form-group-compound {{/compound}}{{#formGroupClassName}}{{formGroupClassName}}{{/formGroupClassName}}{{#error}} govuk-form-group--error{{/error}}">
|
5
|
-
{{
|
5
|
+
{{#isPageHeading}}<h1 class="govuk-label-wrapper">{{/isPageHeading}}<label for="{{id}}" class="{{labelClassName}}">
|
6
6
|
{{{label}}}
|
7
7
|
{{#error}}
|
8
8
|
<p id="{{id}}-error" class="govuk-error-message">
|
@@ -10,7 +10,7 @@
|
|
10
10
|
</p>
|
11
11
|
{{/error}}
|
12
12
|
</label>
|
13
|
-
{{
|
13
|
+
{{#isPageHeading}}</h1>{{/isPageHeading}}
|
14
14
|
{{#hint}}<div {{$hintId}}id="{{hintId}}" {{/hintId}}class="govuk-hint">{{hint}}</div>{{/hint}}
|
15
15
|
{{#renderChild}}{{/renderChild}}
|
16
16
|
<textarea
|
@@ -1,5 +1,4 @@
|
|
1
|
-
<div id="{{toggle}}-panel" class="
|
2
|
-
|
3
|
-
|
4
|
-
</div>
|
1
|
+
<div id="{{toggle}}-panel" class="{{#radioOption}}govuk-radios__conditional govuk-radios__conditional--hidden{{/radioOption}}
|
2
|
+
{{^radioOption}}govuk-checkboxes__conditional govuk-checkboxes__conditional--hidden{{/radioOption}}">
|
3
|
+
{{#renderMixin}}{{/renderMixin}}
|
5
4
|
</div>
|
@@ -14,5 +14,17 @@
|
|
14
14
|
"cookies-required": {
|
15
15
|
"title": "Cookies are required to use this service",
|
16
16
|
"message": "Cookies are required in order to use this service.<br /><br /> Please <a href=\"http://www.aboutcookies.org/how-to-control-cookies/\" rel=\"external\">enable cookies</a> and try again. Find out <a href=\"/cookies\">how to we use cookies</a>."
|
17
|
+
},
|
18
|
+
"ddos-rate-limit": {
|
19
|
+
"title": "Too many requests submitted",
|
20
|
+
"message": "You have submitted too many requests in quick succession.",
|
21
|
+
"pre-time-to-wait": "Please try again in ",
|
22
|
+
"post-time-to-wait": " minutes."
|
23
|
+
},
|
24
|
+
"submission-rate-limit": {
|
25
|
+
"title": "Too many submissions",
|
26
|
+
"message": "You have submitted too many applications in a short space of time.",
|
27
|
+
"pre-time-to-wait": "Please try again in ",
|
28
|
+
"post-time-to-wait": " minutes."
|
17
29
|
}
|
18
30
|
}
|
@@ -1,7 +1,8 @@
|
|
1
1
|
<form action="" method="POST" {{$encoding}}{{/encoding}} autocomplete="off" novalidate="true" spellcheck="false">
|
2
2
|
{{$intro}}
|
3
|
-
{{#intro}}<
|
3
|
+
{{#intro}}<p>{{intro}}</p>{{/intro}}
|
4
4
|
{{/intro}}
|
5
|
+
|
5
6
|
{{$form}}{{/form}}
|
6
7
|
{{#csrf-token}}
|
7
8
|
<input type="hidden" name="x-csrf-token" value="{{csrf-token}}" />
|
@@ -0,0 +1,10 @@
|
|
1
|
+
{{<layout}}
|
2
|
+
{{$header}}
|
3
|
+
{{content.title}}
|
4
|
+
{{/header}}
|
5
|
+
{{$content}}
|
6
|
+
<p>{{content.message}}</p>
|
7
|
+
<p>{{content.preTimeToWait}}{{content.timeToWait}}{{content.postTimeToWait}}</p>
|
8
|
+
<a href="/" class="button" role="button">{{#t}}buttons.try-again{{/t}}</a>
|
9
|
+
{{/content}}
|
10
|
+
{{/layout}}
|
@@ -1,6 +1,7 @@
|
|
1
|
+
/* eslint-disable no-undef, no-param-reassign, no-unused-vars */
|
1
2
|
(function () {
|
2
|
-
|
3
|
-
|
3
|
+
'use strict';
|
4
|
+
const root = this;
|
4
5
|
if(typeof root.GOVUK === 'undefined') { root.GOVUK = {}; }
|
5
6
|
|
6
7
|
/*
|
@@ -19,37 +20,35 @@
|
|
19
20
|
GOVUK.cookie('hobnob', null);
|
20
21
|
*/
|
21
22
|
GOVUK.cookie = function (name, value, options) {
|
22
|
-
if(typeof value !== 'undefined'){
|
23
|
+
if(typeof value !== 'undefined') {
|
23
24
|
if(value === false || value === null) {
|
24
25
|
return GOVUK.setCookie(name, '', { days: -1 });
|
25
|
-
} else {
|
26
|
-
return GOVUK.setCookie(name, value, options);
|
27
26
|
}
|
28
|
-
|
29
|
-
return GOVUK.getCookie(name);
|
27
|
+
return GOVUK.setCookie(name, value, options);
|
30
28
|
}
|
29
|
+
return GOVUK.getCookie(name);
|
31
30
|
};
|
32
31
|
GOVUK.setCookie = function (name, value, options) {
|
33
32
|
if(typeof options === 'undefined') {
|
34
33
|
options = {};
|
35
34
|
}
|
36
|
-
|
35
|
+
let cookieString = name + '=' + value + '; path=/';
|
37
36
|
if (options.days) {
|
38
|
-
|
37
|
+
const date = new Date();
|
39
38
|
date.setTime(date.getTime() + (options.days * 24 * 60 * 60 * 1000));
|
40
|
-
cookieString = cookieString +
|
39
|
+
cookieString = cookieString + '; expires=' + date.toGMTString();
|
41
40
|
}
|
42
|
-
if (document.location.protocol
|
43
|
-
cookieString = cookieString +
|
41
|
+
if (document.location.protocol === 'https:') {
|
42
|
+
cookieString = cookieString + '; Secure';
|
44
43
|
}
|
45
44
|
document.cookie = cookieString;
|
46
45
|
};
|
47
46
|
GOVUK.getCookie = function (name) {
|
48
|
-
|
49
|
-
|
50
|
-
for(
|
51
|
-
|
52
|
-
while (cookie.charAt(0)
|
47
|
+
const nameEQ = name + '=';
|
48
|
+
const cookies = document.cookie.split(';');
|
49
|
+
for(let i = 0, len = cookies.length; i < len; i++) {
|
50
|
+
let cookie = cookies[i];
|
51
|
+
while (cookie.charAt(0) === ' ') {
|
53
52
|
cookie = cookie.substring(1, cookie.length);
|
54
53
|
}
|
55
54
|
if (cookie.indexOf(nameEQ) === 0) {
|
@@ -60,33 +59,33 @@
|
|
60
59
|
};
|
61
60
|
}).call(this);
|
62
61
|
(function () {
|
63
|
-
'use strict'
|
64
|
-
|
65
|
-
if (typeof root.GOVUK === 'undefined') { root.GOVUK = {} }
|
62
|
+
'use strict';
|
63
|
+
const root = this;
|
64
|
+
if (typeof root.GOVUK === 'undefined') { root.GOVUK = {}; }
|
66
65
|
|
67
66
|
GOVUK.addCookieMessage = function () {
|
68
|
-
|
67
|
+
const message = document.getElementById('global-cookie-message');
|
69
68
|
|
70
|
-
|
69
|
+
const hasCookieMessage = (message && GOVUK.cookie('seen_cookie_message') === null);
|
71
70
|
|
72
71
|
if (hasCookieMessage) {
|
73
|
-
message.style.display = 'block'
|
74
|
-
GOVUK.cookie('seen_cookie_message', 'yes', { days: 28 })
|
72
|
+
message.style.display = 'block';
|
73
|
+
GOVUK.cookie('seen_cookie_message', 'yes', { days: 28 });
|
75
74
|
|
76
75
|
document.addEventListener('DOMContentLoaded', function (event) {
|
77
76
|
if (GOVUK.analytics && typeof GOVUK.analytics.trackEvent === 'function') {
|
78
77
|
GOVUK.analytics.trackEvent('cookieBanner', 'Cookie banner shown', {
|
79
78
|
value: 1,
|
80
79
|
nonInteraction: true
|
81
|
-
})
|
80
|
+
});
|
82
81
|
}
|
83
|
-
})
|
84
|
-
}
|
85
|
-
}
|
82
|
+
});
|
83
|
+
}
|
84
|
+
};
|
86
85
|
}).call(this)
|
87
86
|
;
|
88
|
-
(function() {
|
89
|
-
|
87
|
+
(function () {
|
88
|
+
'use strict';
|
90
89
|
|
91
90
|
// add cookie message
|
92
91
|
if (window.GOVUK && GOVUK.addCookieMessage) {
|
@@ -94,28 +93,28 @@
|
|
94
93
|
}
|
95
94
|
|
96
95
|
// header navigation toggle
|
97
|
-
if (document.querySelectorAll && document.addEventListener){
|
98
|
-
|
99
|
-
|
100
|
-
for(i=0,_i=els.length; i<_i; i++){
|
101
|
-
els[i].addEventListener('click', function(e){
|
96
|
+
if (document.querySelectorAll && document.addEventListener) {
|
97
|
+
const els = document.querySelectorAll('.js-header-toggle');
|
98
|
+
let i; let _i;
|
99
|
+
for(i = 0, _i = els.length; i < _i; i++) {
|
100
|
+
els[i].addEventListener('click', function (e) {
|
102
101
|
e.preventDefault();
|
103
|
-
|
104
|
-
|
105
|
-
|
102
|
+
const target = document.getElementById(this.getAttribute('href').substr(1));
|
103
|
+
const targetClass = target.getAttribute('class') || '';
|
104
|
+
const sourceClass = this.getAttribute('class') || '';
|
106
105
|
|
107
|
-
if(targetClass.indexOf('js-visible') !== -1){
|
106
|
+
if(targetClass.indexOf('js-visible') !== -1) {
|
108
107
|
target.setAttribute('class', targetClass.replace(/(^|\s)js-visible(\s|$)/, ''));
|
109
108
|
} else {
|
110
|
-
target.setAttribute('class', targetClass +
|
109
|
+
target.setAttribute('class', targetClass + ' js-visible');
|
111
110
|
}
|
112
|
-
if(sourceClass.indexOf('js-visible') !== -1){
|
111
|
+
if(sourceClass.indexOf('js-visible') !== -1) {
|
113
112
|
this.setAttribute('class', sourceClass.replace(/(^|\s)js-visible(\s|$)/, ''));
|
114
113
|
} else {
|
115
|
-
this.setAttribute('class', sourceClass +
|
114
|
+
this.setAttribute('class', sourceClass + ' js-visible');
|
116
115
|
}
|
117
|
-
this.setAttribute('aria-expanded', this.getAttribute('aria-expanded') !==
|
118
|
-
target.setAttribute('aria-hidden', target.getAttribute('aria-hidden') ===
|
116
|
+
this.setAttribute('aria-expanded', this.getAttribute('aria-expanded') !== 'true');
|
117
|
+
target.setAttribute('aria-hidden', target.getAttribute('aria-hidden') === 'false');
|
119
118
|
});
|
120
119
|
}
|
121
120
|
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
/* eslint-disable no-var */
|
1
|
+
/* eslint-disable no-var, vars-on-top, no-unused-vars */
|
2
2
|
'use strict';
|
3
3
|
|
4
4
|
var toolkit = require('../../../toolkit');
|
@@ -8,7 +8,7 @@ var formFocus = toolkit.formFocus;
|
|
8
8
|
var characterCount = toolkit.characterCount;
|
9
9
|
var validation = toolkit.validation;
|
10
10
|
|
11
|
-
var GOVUK = require('govuk-frontend')
|
11
|
+
var GOVUK = require('govuk-frontend');
|
12
12
|
GOVUK.initAll();
|
13
13
|
window.GOVUK = GOVUK;
|
14
14
|
var skipToMain = require('./skip-to-main');
|
@@ -1,18 +1,19 @@
|
|
1
1
|
const skipToMain = function () {
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
}
|
16
|
-
}
|
17
|
-
}
|
18
|
-
|
2
|
+
const skipToMainLink = document.getElementById('skip-to-main');
|
3
|
+
const firstControlId = skipToMainLink.hash.split('#')[1] ? skipToMainLink.hash.split('#')[1] : 'main-content';
|
4
|
+
if(firstControlId === 'main-content') {
|
5
|
+
skipToMainLink.setAttribute('href', '#main-content');
|
6
|
+
}
|
7
|
+
if(firstControlId) {
|
8
|
+
// eslint-disable-next-line no-unused-vars
|
9
|
+
skipToMainLink.onclick = function (e) {
|
10
|
+
// here timeout added just to make this functionality asynchronous
|
11
|
+
// to focus on form as well as non form contents
|
12
|
+
setTimeout(() => {
|
13
|
+
const firstControl = document.getElementById(firstControlId);
|
14
|
+
firstControl.focus();
|
15
|
+
}, 10);
|
16
|
+
};
|
17
|
+
}
|
18
|
+
};
|
19
|
+
skipToMain();
|
@@ -10,7 +10,6 @@
|
|
10
10
|
}
|
11
11
|
|
12
12
|
#cookie-banner {
|
13
|
-
max-width: 960px;
|
14
13
|
margin: 0 15px;
|
15
14
|
p {
|
16
15
|
margin: 0;
|
@@ -62,3 +61,54 @@
|
|
62
61
|
height: fit-content;
|
63
62
|
}
|
64
63
|
}
|
64
|
+
|
65
|
+
// the following are additional hof specific govuk cookie banner styling
|
66
|
+
.govuk-banner--success {
|
67
|
+
border-color: #00703c;
|
68
|
+
color: #00703c;
|
69
|
+
}
|
70
|
+
|
71
|
+
.govuk-banner {
|
72
|
+
border: 5px solid #1d70b8;
|
73
|
+
font-size: 0;
|
74
|
+
margin-bottom: 30px;
|
75
|
+
padding: 10px;
|
76
|
+
}
|
77
|
+
|
78
|
+
.govuk-banner__icon{
|
79
|
+
display: inline-block;
|
80
|
+
}
|
81
|
+
|
82
|
+
.govuk-banner__message {
|
83
|
+
font-family: "GDS Transport", Arial, sans-serif;
|
84
|
+
-webkit-font-smoothing: antialiased;
|
85
|
+
font-weight: 400;
|
86
|
+
font-size: 1rem;
|
87
|
+
line-height: 1.25;
|
88
|
+
color: #0b0c0c;
|
89
|
+
display: block;
|
90
|
+
overflow: hidden;
|
91
|
+
display: inline-block;
|
92
|
+
margin-left: 10px;
|
93
|
+
}
|
94
|
+
|
95
|
+
.govuk-banner__assistive {
|
96
|
+
position: absolute !important;
|
97
|
+
width: 1px !important;
|
98
|
+
height: 1px !important;
|
99
|
+
margin: 0 !important;
|
100
|
+
padding: 0 !important;
|
101
|
+
overflow: hidden !important;
|
102
|
+
clip: rect(0 0 0 0) !important;
|
103
|
+
clip-path: inset(50%) !important;
|
104
|
+
border: 0 !important;
|
105
|
+
white-space: nowrap !important;
|
106
|
+
}
|
107
|
+
|
108
|
+
.cookie-table-holder > table > tbody > tr > td:first-child{
|
109
|
+
font-weight:bold;
|
110
|
+
}
|
111
|
+
|
112
|
+
.js-enabled #global-cookie-message {
|
113
|
+
display: none;
|
114
|
+
}
|
@@ -12,6 +12,11 @@ $path: "/public/images/" !default;
|
|
12
12
|
// https://github.com/alphagov/govuk_elements/blob/master/packages/govuk-elements-sass/public/sass/_elements.scss
|
13
13
|
@import "govuk-elements-sass/public/sass/elements";
|
14
14
|
|
15
|
+
// Govuk frontend
|
16
|
+
// https://github.com/alphagov/govuk-frontend-docs
|
17
|
+
// @import "node_modules/govuk-frontend/govuk/all";
|
18
|
+
@import "../../../../node_modules/govuk-frontend/govuk/all";
|
19
|
+
|
15
20
|
// Custom
|
16
21
|
@import "base";
|
17
22
|
@import "layout";
|
@@ -71,11 +71,20 @@ function formFocus() {
|
|
71
71
|
var labels;
|
72
72
|
var summaries;
|
73
73
|
|
74
|
-
|
74
|
+
var editMode = getElementFromSummaryLink && getEditPath === 'edit';
|
75
|
+
|
76
|
+
if (getElementFromSummaryLink && document.getElementById(getElementFromSummaryLink) && editMode) {
|
75
77
|
document.getElementById(getElementFromSummaryLink).focus();
|
78
|
+
}
|
79
|
+
|
80
|
+
if (getElementFromSummaryLink && document.getElementById(getElementFromSummaryLink + '-group') && editMode) {
|
76
81
|
document.getElementById(getElementFromSummaryLink + '-group').scrollIntoView();
|
77
82
|
}
|
78
83
|
|
84
|
+
if (document.getElementById(getElementFromSummaryLink + '-day') && forms.length === 1 && editMode) {
|
85
|
+
document.getElementById(getElementFromSummaryLink + '-day').focus();
|
86
|
+
}
|
87
|
+
|
79
88
|
if (forms.length > 0) {
|
80
89
|
labels = document.getElementsByTagName('label');
|
81
90
|
if (labels) {
|
@@ -24,7 +24,12 @@ function clicked(e) {
|
|
24
24
|
}
|
25
25
|
|
26
26
|
if (inputs) {
|
27
|
-
inputs[0].
|
27
|
+
if (inputs[0].getAttribute('type') === 'hidden') {
|
28
|
+
var getVisibleElements = group.querySelectorAll('input[type=text]');
|
29
|
+
getVisibleElements[0].focus();
|
30
|
+
} else {
|
31
|
+
inputs[0].focus();
|
32
|
+
}
|
28
33
|
}
|
29
34
|
}
|
30
35
|
}
|
package/index.js
CHANGED
@@ -120,8 +120,9 @@ const getContentSecurityPolicy = (config, res) => {
|
|
120
120
|
* @param options.getTerms {boolean} Optional boolean - whether to mount the /terms endpoint
|
121
121
|
* @param options.getCookies {boolean} Optional boolean - whether to mount the /cookies endpoint
|
122
122
|
* @param options.noCache {boolean} Optional boolean - whether to disable caching
|
123
|
-
* @param options.getAccessibilityStatement {boolean} Optional boolean - whether to mount the
|
124
|
-
*
|
123
|
+
* @param options.getAccessibilityStatement {boolean} Optional boolean - whether to mount the
|
124
|
+
* /accessibility-statement endpoint
|
125
|
+
*
|
125
126
|
* @returns {object} A new HOF application using the configuration supplied in options
|
126
127
|
*/
|
127
128
|
function bootstrap(options) {
|
@@ -205,9 +206,13 @@ function bootstrap(options) {
|
|
205
206
|
}));
|
206
207
|
app.use(mixins());
|
207
208
|
app.use(markdown(config.markdown));
|
208
|
-
|
209
|
+
// rate limits have to be loaded before all routes so it is applied to them
|
210
|
+
if (config.rateLimits.requests.active) {
|
211
|
+
app.use(hofMiddleware.rateLimiter(config, 'requests'));
|
212
|
+
}
|
213
|
+
|
209
214
|
// Set up routing so <YOUR-SITE-URL>/assets are served from /node_modules/govuk-frontend/govuk/assets
|
210
|
-
app.use('/assets', express.static(path.join(__dirname, '/node_modules/govuk-frontend/govuk/assets')))
|
215
|
+
app.use('/assets', express.static(path.join(__dirname, '/node_modules/govuk-frontend/govuk/assets')));
|
211
216
|
|
212
217
|
if (config.getAccessibility === true) {
|
213
218
|
deprecate(
|
package/lib/router.js
CHANGED
@@ -19,7 +19,8 @@ function getWizardConfig(config) {
|
|
19
19
|
const wizardConfig = {
|
20
20
|
name: config.route.name || (config.route.baseUrl || '').replace('/', ''),
|
21
21
|
protocol: config.protocol,
|
22
|
-
env: config.env
|
22
|
+
env: config.env,
|
23
|
+
sanitiseInputs: config.sanitiseInputs
|
23
24
|
};
|
24
25
|
|
25
26
|
if (config.appConfig) {
|
package/lib/settings.js
CHANGED
@@ -7,7 +7,22 @@ const hoganExpressStrict = require('hogan-express-strict');
|
|
7
7
|
const expressPartialTemplates = require('express-partial-templates');
|
8
8
|
const bodyParser = require('body-parser');
|
9
9
|
|
10
|
-
|
10
|
+
const dirExists = dir => {
|
11
|
+
try {
|
12
|
+
if (fs.existsSync(dir)) {
|
13
|
+
return true;
|
14
|
+
}
|
15
|
+
return false;
|
16
|
+
} catch(err) {
|
17
|
+
throw new Error(`${err}: Cannot check if the directory path exists`);
|
18
|
+
}
|
19
|
+
};
|
20
|
+
|
21
|
+
const filterEmptyViews = views => {
|
22
|
+
return views.filter(view => dirExists(view));
|
23
|
+
};
|
24
|
+
|
25
|
+
module.exports = async (app, config) => {
|
11
26
|
const viewEngine = config.viewEngine || 'html';
|
12
27
|
|
13
28
|
app.use((req, res, next) => {
|
@@ -17,7 +32,8 @@ module.exports = (app, config) => {
|
|
17
32
|
|
18
33
|
app.use(config.theme());
|
19
34
|
|
20
|
-
const
|
35
|
+
const filteredViews = filterEmptyViews(config.theme.views);
|
36
|
+
const viewPaths = [].concat(filteredViews);
|
21
37
|
app.set('view engine', viewEngine);
|
22
38
|
app.enable('view cache');
|
23
39
|
|
package/middleware/errors.js
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
/* eslint-disable no-unused-vars */
|
2
2
|
'use strict';
|
3
3
|
|
4
|
+
const rateLimitsConfig = require('../config/rate-limits');
|
5
|
+
|
4
6
|
const errorTitle = code => `${code}_ERROR`;
|
5
7
|
const errorMsg = code => `There is a ${code}_ERROR`;
|
6
8
|
// eslint-disable-next-line complexity
|
@@ -21,6 +23,36 @@ const getContent = (err, translate) => {
|
|
21
23
|
content.message = (translate && translate('errors.cookies-required.message'));
|
22
24
|
}
|
23
25
|
|
26
|
+
if (err.code === 'DDOS_RATE_LIMIT') {
|
27
|
+
err.status = 429;
|
28
|
+
err.template = 'rate-limit-error';
|
29
|
+
err.title = (translate && translate('errors.ddos-rate-limit.title'));
|
30
|
+
err.message = (translate && translate('errors.ddos-rate-limit.message'));
|
31
|
+
err.preTimeToWait = (translate && translate('errors.ddos-rate-limit.pre-time-to-wait'));
|
32
|
+
err.timeToWait = rateLimitsConfig.rateLimits.requests.windowSizeInMinutes;
|
33
|
+
err.postTimeToWait = (translate && translate('errors.ddos-rate-limit.post-time-to-wait'));
|
34
|
+
content.title = (translate && translate('errors.ddos-rate-limit.title'));
|
35
|
+
content.message = (translate && translate('errors.ddos-rate-limit.message'));
|
36
|
+
content.preTimeToWait = (translate && translate('errors.ddos-rate-limit.pre-time-to-wait'));
|
37
|
+
content.timeToWait = rateLimitsConfig.rateLimits.requests.windowSizeInMinutes;
|
38
|
+
content.postTimeToWait = (translate && translate('errors.ddos-rate-limit.post-time-to-wait'));
|
39
|
+
}
|
40
|
+
|
41
|
+
if (err.code === 'SUBMISSION_RATE_LIMIT') {
|
42
|
+
err.status = 429;
|
43
|
+
err.template = 'rate-limit-error';
|
44
|
+
err.title = (translate && translate('errors.submission-rate-limit.title'));
|
45
|
+
err.message = (translate && translate('errors.submission-rate-limit.message'));
|
46
|
+
err.preTimeToWait = (translate && translate('errors.submission-rate-limit.pre-time-to-wait'));
|
47
|
+
err.timeToWait = rateLimitsConfig.rateLimits.submissions.windowSizeInMinutes;
|
48
|
+
err.postTimeToWait = (translate && translate('errors.submission-rate-limit.post-time-to-wait'));
|
49
|
+
content.title = (translate && translate('errors.submission-rate-limit.title'));
|
50
|
+
content.message = (translate && translate('errors.submission-rate-limit.message'));
|
51
|
+
content.preTimeToWait = (translate && translate('errors.submission-rate-limit.pre-time-to-wait'));
|
52
|
+
content.timeToWait = rateLimitsConfig.rateLimits.submissions.windowSizeInMinutes;
|
53
|
+
content.postTimeToWait = (translate && translate('errors.submission-rate-limit.post-time-to-wait'));
|
54
|
+
}
|
55
|
+
|
24
56
|
err.code = err.code || 'UNKNOWN';
|
25
57
|
err.status = err.status || 500;
|
26
58
|
|
package/middleware/index.js
CHANGED