@dwp/govuk-casa 6.8.4 → 6.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/casa.js +4 -3
  3. package/dist/casa/css/casa-ie8.css +1 -1
  4. package/dist/casa/css/casa.css +1 -1
  5. package/dist/casa/js/casa.js +1 -1
  6. package/lib/ConfigIngestor.js +119 -94
  7. package/lib/GatherModifier.js +1 -1
  8. package/lib/I18n.js +12 -11
  9. package/lib/JourneyContext.js +33 -30
  10. package/lib/JourneyMap.js +24 -16
  11. package/lib/JourneyRoad.js +25 -18
  12. package/lib/Logger.js +3 -3
  13. package/lib/PageDirectory.js +3 -3
  14. package/lib/Plan.js +31 -30
  15. package/lib/Util.js +20 -20
  16. package/lib/Validation.js +1 -1
  17. package/lib/bootstrap/end-session.js +2 -2
  18. package/lib/bootstrap/load-definitions.js +9 -9
  19. package/lib/gather-modifiers/trimPostalAddressObject.js +5 -5
  20. package/lib/gather-modifiers/trimWhitespace.js +4 -4
  21. package/lib/utils/makeEditLink.js +6 -3
  22. package/lib/utils/sanitise.js +1 -1
  23. package/lib/validation/ArrayObjectField.js +5 -4
  24. package/lib/validation/ObjectField.js +4 -3
  25. package/lib/validation/SimpleField.js +4 -3
  26. package/lib/validation/ValidationError.js +5 -2
  27. package/lib/validation/processor/flattenErrorArray.js +3 -2
  28. package/lib/validation/processor/queue.js +28 -28
  29. package/lib/validation/processor.js +9 -5
  30. package/lib/validation/rules/dateObject.js +2 -2
  31. package/lib/validation/rules/email.js +1 -1
  32. package/lib/validation/rules/inArray.js +3 -3
  33. package/lib/validation/rules/nino.js +2 -2
  34. package/lib/validation/rules/optional.js +2 -2
  35. package/lib/validation/rules/postalAddressObject.js +2 -2
  36. package/lib/validation/rules/regex.js +1 -1
  37. package/lib/validation/rules/required.js +3 -3
  38. package/lib/validation/rules/strlen.js +1 -1
  39. package/lib/view-filters/formatDateObject.js +6 -3
  40. package/lib/view-filters/includes.js +4 -4
  41. package/lib/view-filters/index.js +1 -1
  42. package/lib/view-filters/mergeObjectsDeep.js +3 -2
  43. package/lib/view-filters/renderAsAttributes.js +1 -1
  44. package/middleware/headers/config-defaults.js +2 -0
  45. package/middleware/i18n/i18n.js +15 -15
  46. package/middleware/nunjucks/environment.js +8 -9
  47. package/middleware/page/csrf.js +1 -1
  48. package/middleware/page/gather.js +1 -1
  49. package/middleware/page/index.js +5 -5
  50. package/middleware/page/journey-continue.js +15 -2
  51. package/middleware/page/journey-rails.js +1 -1
  52. package/middleware/page/prepare-request.js +2 -2
  53. package/middleware/page/skip.js +1 -1
  54. package/middleware/page/utils.js +37 -36
  55. package/middleware/page/validate.js +1 -1
  56. package/middleware/session/index.js +1 -1
  57. package/middleware/static/index.js +12 -7
  58. package/middleware/static/prepare-assets.js +4 -4
  59. package/middleware/static/serve-assets.js +4 -7
  60. package/package.json +51 -53
  61. package/src/js/casa.js +10 -6
  62. package/views/casa/layouts/main.njk +9 -0
  63. package/src/robots.txt +0 -2
@@ -8,9 +8,10 @@
8
8
  * }
9
9
  *
10
10
  * @param {object} obj Object of fields that will be tested
11
- * @param {array|null} validators Validation rules that must be satisfied
12
- * @param {function|null} condition Condition to meet before validators are run
13
- * @return {object} Validation object suitable for processing
11
+ * @param {Array|null} validators Validation rules that must be satisfied
12
+ * @param {Function|null} condition Condition to meet before validators are run
13
+ * @returns {object} Validation object suitable for processing
14
+ * @throws {TypeError} When arguments are invalid
14
15
  */
15
16
  module.exports = (obj = {}, validators = [], condition) => {
16
17
  if (Object.prototype.toString.call(obj) !== '[object Object]') {
@@ -1,9 +1,10 @@
1
1
  /**
2
2
  * A simple field.
3
3
  *
4
- * @param {array} validators Validation rules (bindable functions) to satisfy
5
- * @param {Function|null} condition Condition to meet before validators are run
6
- * @return {object} Validation object suitable for processing
4
+ * @param {Array} validators Validation rules (bindable functions) to satisfy.
5
+ * @param {Function|null} condition Condition to meet before validators are run.
6
+ * @returns {object} Validation object suitable for processing.
7
+ * @throws {TypeError} When validator or condition is an invalid type
7
8
  */
8
9
  module.exports = (validators = [], condition) => {
9
10
  validators.forEach((v) => {
@@ -14,13 +14,13 @@ class ValidationError {
14
14
  * String => 'common:errors.my-error-message'
15
15
  * Object => (see constructor argument for structure of this object)
16
16
  * Function => Function returns object suitable for constructor (see example below)
17
- * Error => A JavaScript error. It's `message` will be used as the error
17
+ * Error => A JavaScript error. It's `message` will be used as the error.
18
18
  *
19
19
  * `dataContext` is an object containing the same data passed to all validator
20
20
  * functions, and contains:
21
21
  * waypointId => The current waypoint being requested
22
22
  * fieldName => Name of the field being validated
23
- * journeyContext => The full JourneyContext of the current request
23
+ * journeyContext => The full JourneyContext of the current request.
24
24
  *
25
25
  * Example function signature that can be used for `errorMsg`:
26
26
  * ({ waypointId, fieldName, journeyContext }) => ({
@@ -31,7 +31,10 @@ class ValidationError {
31
31
  * });
32
32
  *
33
33
  * @param {object} args See args above
34
+ * @param {any} args.errorMsg Error message to seed the ValidationError
35
+ * @param {object} args.dataContext Validation context
34
36
  * @returns {object} Primitive error matching structure above
37
+ * @throws {TypeError} If errorMsg is not in a valid type
35
38
  */
36
39
  static make({ errorMsg, dataContext = {} }) {
37
40
  // Convert strings to the most basic object primitive
@@ -4,8 +4,9 @@ const ValidationError = require('../ValidationError.js');
4
4
  * Converts a (potentially) deeply nested array of ValidationErrors into a flat
5
5
  * array.
6
6
  *
7
- * @param {array} errorsArray Array of errors
8
- * @return {array} The flatted array
7
+ * @param {Array<ValidationError>} errorsArray Array of errors.
8
+ * @returns {Array} The flatted array.
9
+ * @throws {TypeError} When error is not a ValidationError
9
10
  */
10
11
  module.exports = (errorsArray = []) => {
11
12
  let errors = errorsArray;
@@ -10,13 +10,13 @@ const T_ARRAY_OBJECT = 'array_object';
10
10
  /**
11
11
  * Add a validator object to the processing queue.
12
12
  *
13
- * @param {array} queue Queue to which validators will be added
14
- * @param {string} waypointId Waypoint under validation
15
- * @param {PageMeta} pageMeta Meta object representing the page being validated
16
- * @param {object} journeyContext Full JourneyContext
17
- * @param {string} field Field to validate (in square-brace notation)
18
- * @param {object} validatorObj Validation attributes to apply
19
- * @return {void}
13
+ * @param {Array} queue Queue to which validators will be added.
14
+ * @param {string} waypointId Waypoint under validation.
15
+ * @param {PageMeta} pageMeta Meta object representing the page being validated.
16
+ * @param {object} journeyContext Full JourneyContext.
17
+ * @param {string} field Field to validate (in square-brace notation).
18
+ * @param {object} validatorObj Validation attributes to apply.
19
+ * @returns {void}
20
20
  */
21
21
  /* eslint-disable-next-line consistent-return,require-jsdoc */
22
22
  function queueValidator(queue, waypointId, pageMeta, journeyContext, field, validatorObj) {
@@ -51,13 +51,13 @@ function queueValidator(queue, waypointId, pageMeta, journeyContext, field, vali
51
51
  /**
52
52
  * Add a Validation.SimpleField object to the processing queue.
53
53
  *
54
- * @param {array} queue Queue to which validators will be added
55
- * @param {string} waypointId Waypoint under validation
56
- * @param {PageMeta} pageMeta Meta object representing the page being validated
57
- * @param {object} journeyContext Full JourneyContext
58
- * @param {string} field Field to validate (in square-brace notation)
59
- * @param {object} validatorObj Validation attributes to apply
60
- * @return {void}
54
+ * @param {Array} queue Queue to which validators will be added.
55
+ * @param {string} waypointId Waypoint under validation.
56
+ * @param {PageMeta} pageMeta Meta object representing the page being validated.
57
+ * @param {object} journeyContext Full JourneyContext.
58
+ * @param {string} field Field to validate (in square-brace notation).
59
+ * @param {object} validatorObj Validation attributes to apply.
60
+ * @returns {void}
61
61
  */
62
62
  function queueSimpleValidator(queue, waypointId, pageMeta, journeyContext, field, validatorObj) {
63
63
  // Ensure pageMeta.id is defined when extracting data for the waypoint
@@ -136,13 +136,13 @@ function queueSimpleValidator(queue, waypointId, pageMeta, journeyContext, field
136
136
  /**
137
137
  * Add a Validation.ObjectField object to the queue.
138
138
  *
139
- * @param {array} queue Queue to which validators will be added
140
- * @param {string} waypointId Waypoint under validation
141
- * @param {PageMeta} pageMeta Meta object representing the page being validated
142
- * @param {object} journeyContext Full JourneyContext
143
- * @param {string} field Field to validate (in square-brace notation)
144
- * @param {object} validatorObj Validation attributes to apply
145
- * @return {void}
139
+ * @param {Array} queue Queue to which validators will be added.
140
+ * @param {string} waypointId Waypoint under validation.
141
+ * @param {PageMeta} pageMeta Meta object representing the page being validated.
142
+ * @param {object} journeyContext Full JourneyContext.
143
+ * @param {string} field Field to validate (in square-brace notation).
144
+ * @param {object} validatorObj Validation attributes to apply.
145
+ * @returns {void}
146
146
  */
147
147
  function queueObjectValidator(queue, waypointId, pageMeta, journeyContext, field, validatorObj) {
148
148
  // Add this validator's rules to the queue (if any)
@@ -165,13 +165,13 @@ function queueObjectValidator(queue, waypointId, pageMeta, journeyContext, field
165
165
  /**
166
166
  * Add a Validation.ArrayObjectField object to the queue.
167
167
  *
168
- * @param {array} queue Queue to which validators will be added
169
- * @param {string} waypointId Waypoint under validation
170
- * @param {PageMeta} pageMeta Meta object representing the page being validated
171
- * @param {object} journeyContext Full JourneyContext
172
- * @param {string} field Field to validate (in square-brace notation)
173
- * @param {object} validatorObj Validation attributes to apply
174
- * @return {void}
168
+ * @param {Array} queue Queue to which validators will be added.
169
+ * @param {string} waypointId Waypoint under validation.
170
+ * @param {PageMeta} pageMeta Meta object representing the page being validated.
171
+ * @param {object} journeyContext Full JourneyContext.
172
+ * @param {string} field Field to validate (in square-brace notation).
173
+ * @param {object} validatorObj Validation attributes to apply.
174
+ * @returns {void}
175
175
  */
176
176
  function queueArrayObjectValidator(
177
177
  queue, waypointId, pageMeta, journeyContext, field, validatorObj,
@@ -17,7 +17,11 @@ const { queueValidator } = require('./processor/queue.js');
17
17
  * bool reduceErrors = Reduces each field to a single error (default false)
18
18
  *
19
19
  * @param {object} params Parameters object as above
20
- * @return {Promise} Promise
20
+ * @param {string} params.waypointId Waypoint ID
21
+ * @param {object} params.pageMeta Page meta
22
+ * @param {Function} params.journeyContext Journey context
23
+ * @param {boolean} params.reduceErrors True is errors should be reduced to a single error
24
+ * @returns {Promise} Promise
21
25
  */
22
26
  // module.exports = (fieldValidators = {}, userData = {}, options = {}) => {
23
27
  module.exports = ({
@@ -36,8 +40,8 @@ module.exports = ({
36
40
  * have multiple validation rules that may each be violated and thus result
37
41
  * in their own error messages, which can quickly stack up on larger pages.
38
42
  *
39
- * @param {object} errors All errors
40
- * @return {object} Reduced error list, indexed by field name
43
+ * @param {object} errors All errors.
44
+ * @returns {object} Reduced error list, indexed by field name.
41
45
  */
42
46
  function reduceGroupedErrors(errors) {
43
47
  const reduced = Object.create(null);
@@ -52,8 +56,8 @@ module.exports = ({
52
56
  * object indexed by the field names. This makes it easier to reference errors
53
57
  * in the front-end template.
54
58
  *
55
- * @param {array} errorsList Array of errors
56
- * @return {Promise} Promise
59
+ * @param {Array} errorsList Array of errors.
60
+ * @returns {Promise} Promise.
57
61
  */
58
62
  function gatherErrors(errorsList) {
59
63
  let grouped = Object.create(null);
@@ -7,7 +7,7 @@ const ValidationError = require('../ValidationError.js');
7
7
  * dd: <string>,
8
8
  * mm: <string>,
9
9
  * yyyy: <string>
10
- * }
10
+ * }.
11
11
  *
12
12
  * Note that the time part of any injected "moment" objects will be zero'ed, as
13
13
  * we are only interested in the date component (minimum day resolution).
@@ -25,7 +25,7 @@ const ValidationError = require('../ValidationError.js');
25
25
  *
26
26
  * @param {object} value Date object (see description)
27
27
  * @param {object} dataContext Context
28
- * @return {Promise} Promise
28
+ * @returns {Promise} Promise
29
29
  */
30
30
  function dateObject(value, dataContext = {}) {
31
31
  const config = {
@@ -7,7 +7,7 @@
7
7
  * string|object errorMsg = Error message to use on validation failure
8
8
  *
9
9
  * @param {string} value Email address
10
- * @return {Promise} Promise
10
+ * @returns {Promise} Promise
11
11
  */
12
12
 
13
13
  const { isEmail } = require('validator');
@@ -2,13 +2,13 @@
2
2
  * Test if a value is present in an array.
3
3
  *
4
4
  * Bound attributes:
5
- * Array source = Array of values to test against
5
+ * Array source = Array of values to test against.
6
6
  *
7
7
  * If the value itself is an array, all values within that array must be present
8
8
  * in the `source` array in order to pass validation.
9
9
  *
10
- * @param {mixed} value Value to find
11
- * @return {Promise} Promise
10
+ * @param {any} value Value to find.
11
+ * @returns {Promise} Promise.
12
12
  */
13
13
  const ValidationError = require('../ValidationError.js');
14
14
 
@@ -3,14 +3,14 @@
3
3
  *
4
4
  * Bound attributes:
5
5
  * string|object errorMsg = Error message to use on validation failure
6
- * boolean allowWhitespace = will permit input values that contain spaces
6
+ * boolean allowWhitespace = will permit input values that contain spaces.
7
7
  *
8
8
  * Ref:
9
9
  * https://en.wikipedia.org/wiki/National_Insurance_number#Format
10
10
  * https://design-system.service.gov.uk/patterns/national-insurance-numbers/
11
11
  *
12
12
  * @param {string} value NI number
13
- * @return {Promise} Promise
13
+ * @returns {Promise} Promise
14
14
  */
15
15
  const ValidationError = require('../ValidationError.js');
16
16
 
@@ -4,8 +4,8 @@ const Util = require('../../Util.js');
4
4
  * This is different to all other rules in that it _must_ return a value
5
5
  * synchronously. You must not `bind()` this function to create a new one.
6
6
  *
7
- * @param {mixed} value Value
8
- * @return {bool} Return true if the value is not present
7
+ * @param {any} value Value.
8
+ * @returns {boolean} Return true if the value is not present.
9
9
  */
10
10
  function optional(value) {
11
11
  return Util.isEmpty(value);
@@ -12,11 +12,11 @@
12
12
  * string|object errorMsgAddress3 = Error message for address3 part
13
13
  * string|object errorMsgAddress4 = Error message for address4 part
14
14
  * string|object errorMsgPostcode = Error message for postcode part
15
- * int strlenmax = Max. string length for each of the inputs appress[1-4]
15
+ * int strlenmax = Max. String length for each of the inputs appress[1-4]
16
16
  * array requiredFields = Field parts required (others become optional)
17
17
  *
18
18
  * @param {object} value Address object to test
19
- * @return {Promise} Promise
19
+ * @returns {Promise} Promise
20
20
  */
21
21
  const ValidationError = require('../ValidationError.js');
22
22
 
@@ -7,7 +7,7 @@
7
7
  * boolean invert = return reject on positive regex match
8
8
  *
9
9
  * @param {string} value String to check
10
- * @return {Promise} Promise
10
+ * @returns {Promise} Promise
11
11
  */
12
12
  const ValidationError = require('../ValidationError.js');
13
13
 
@@ -1,5 +1,5 @@
1
1
  /**
2
- * required
2
+ * Required.
3
3
  */
4
4
  const Util = require('../../Util.js');
5
5
  const ValidationError = require('../ValidationError.js');
@@ -10,9 +10,9 @@ const ValidationError = require('../ValidationError.js');
10
10
  * Value is required. The following values will fail this rule:
11
11
  * (all values that satisify `Util.isEmpty()`) plus '\s'
12
12
  *
13
- * @param {mixed} value Value to test
13
+ * @param {any} value Value to test
14
14
  * @param {object} dataContext Context
15
- * @return {Promise} Promise
15
+ * @returns {Promise} Promise
16
16
  */
17
17
  function required(value, dataContext = {}) {
18
18
  let result;
@@ -8,7 +8,7 @@
8
8
  * int min = Minimum string length required
9
9
  *
10
10
  * @param {string} inputValue Value to test
11
- * @return {Promise} Promise
11
+ * @returns {Promise} Promise
12
12
  */
13
13
  const ValidationError = require('../ValidationError.js');
14
14
 
@@ -10,10 +10,13 @@ const moment = require('moment');
10
10
  * `date` may be any of the following types:
11
11
  * object - {dd:'', mm:'', yyyy:''}
12
12
  *
13
- * @param {mixed} date Date (see supported formats above)
14
- * @return {string} Formatted date
13
+ * @param {object} date Date (see supported formats above)
14
+ * @param {object} config Holds locale
15
+ * @returns {string} Formatted date
15
16
  */
16
- module.exports = function formatDateObject(date, { locale = 'en' } = {}) {
17
+ module.exports = function formatDateObject(date, config = {}) {
18
+ const { locale = 'en' } = config;
19
+
17
20
  if (
18
21
  Object.prototype.toString.call(date) === '[object Object]'
19
22
  && 'yyyy' in date
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Test if an array includes the given element
2
+ * Test if an array includes the given element.
3
3
  *
4
- * @param {array} source Array to search
5
- * @param {mixed} search Element to search for
6
- * @return {boolean} Result
4
+ * @param {Array} source Array to search.
5
+ * @param {any} search Element to search for.
6
+ * @returns {boolean} Result.
7
7
  */
8
8
  module.exports = function includes(source = [], search = '') {
9
9
  return source.includes(search);
@@ -13,7 +13,7 @@ const makeEditLink = require('../utils/makeEditLink.js');
13
13
  /**
14
14
  * Load filters into the given Nunjucks environment
15
15
  *
16
- * @param {NunjucksEnvironment} env Nunjucks environment
16
+ * @param {any} env Nunjucks environment
17
17
  * @param {string} mountUrl Application mount URL
18
18
  * @returns {void}
19
19
  */
@@ -3,8 +3,9 @@ const merge = require('lodash.merge');
3
3
  /**
4
4
  * Merge the given objects. The first object given will _not_ be mutated.
5
5
  *
6
- * @param {object} objects... Objects to be merged
7
- * @return {object} Merged object
6
+ * @param {...any} objects Objects to be merged.
7
+ * @returns {object} Merged object.
8
+ * @throws {TypeError} When attempting to merge a non-object
8
9
  */
9
10
  module.exports = function mergeObjectsDeep(...objects) {
10
11
  // Validate
@@ -13,7 +13,7 @@ const nunjucks = require('nunjucks');
13
13
  * Output: class="basic" data-ga="3"
14
14
  *
15
15
  * @param {object} attrsObject Attributes object (in name:value pairs)
16
- * @return {string} Formatted
16
+ * @returns {string} Formatted
17
17
  */
18
18
  module.exports = function renderAsAttributes(attrsObject) {
19
19
  const attrsList = [];
@@ -42,11 +42,13 @@ module.exports = (app, cspConfig = {}) => {
42
42
  cspDirectives = Object.keys(cspDirectives).map((directive) => `${directive} ${cspDirectives[directive].join(' ')}`);
43
43
 
44
44
  // Prepare default headers
45
+ // added X-Robots-Tag based on https://www.gov.uk/service-manual/technology/get-a-domain-name
45
46
  const defaultHeaders = {
46
47
  'X-Content-Type-Options': 'nosniff',
47
48
  'X-XSS-Protection': '1; mode=block',
48
49
  'X-Frame-Options': 'DENY',
49
50
  'Content-Security-Policy': cspDirectives.join('; '),
51
+ 'X-Robots-Tag': 'noindex, nofollow',
50
52
  };
51
53
 
52
54
  return {
@@ -1,19 +1,19 @@
1
1
  /**
2
- * Configure multi-lingual support.
3
- *
4
- * This middleware will determine the language to use for each request, by
5
- * inspecting the query and existing session.
6
- *
7
- * Enhances `req` with:
8
- * string language = The language code to use (ISO 639-1)
9
- * function i18nTranslator = A class instance to translate for the current req
10
- *
11
- * Enhances `req.session` with:
12
- * string language = The language code to use (ISO 639-1)
13
- *
14
- * Enhances `req.casa.journeyContext.nav` with
15
- * string language = The language code to use (ISO 639-1)
16
- */
2
+ * Configure multi-lingual support.
3
+ *
4
+ * This middleware will determine the language to use for each request, by
5
+ * inspecting the query and existing session.
6
+ *
7
+ * Enhances `req` with:
8
+ * string language = The language code to use (ISO 639-1).
9
+ * Function i18nTranslator = A class instance to translate for the current req.
10
+ *
11
+ * Enhances `req.session` with:
12
+ * string language = The language code to use (ISO 639-1).
13
+ *
14
+ * Enhances `req.casa.journeyContext.nav` with
15
+ * string language = The language code to use (ISO 639-1).
16
+ */
17
17
 
18
18
  module.exports = (logger, supportedLocales = [], translatorFactory) => (req, res, next) => {
19
19
  const currentSessionLanguage = (req.session || Object.create(null)).language;
@@ -8,23 +8,22 @@
8
8
  *
9
9
  * Enhances `res` with:
10
10
  * function render = Function to render and return a template response
11
- * Environment nunjucksEnvironment = Nunjucks environment for this request
11
+ * Environment nunjucksEnvironment = Nunjucks environment for this request.
12
12
  */
13
13
 
14
14
  const nunjucks = require('nunjucks');
15
15
  const path = require('path');
16
16
 
17
17
  /**
18
- * `govukFrontendDir` must be the path to the layout template file
19
- * (template.njk), which would typically be passed in from
20
- * the result of:
18
+ * `govukFrontendDir` must be the path to the layout template file template.njk
19
+ * which would typically be passed in from the result of:
21
20
  * require.resolve('govuk-frontend')
22
21
  *
23
- * @param {object} logger Logger
24
- * @param {Express} app Express app
25
- * @param {array} viewDirs List of view directories to register with Nunjucks
26
- * @param {string} govukFrontendDir Path to `govuk-frontend` module
27
- * @return {nunjucks.Environment} Configured environment
22
+ * @param {object} logger Logger.
23
+ * @param {Function} app Express app.
24
+ * @param {Array} viewDirs List of view directories to register with Nunjucks.
25
+ * @param {string} govukFrontendDir Path to `govuk-frontend` module.
26
+ * @returns {nunjucks.Environment} Configured environment.
28
27
  */
29
28
  module.exports = (logger, app, viewDirs = [], govukFrontendDir = '') => {
30
29
  // Resolve all application template search paths, and add CASA-specific dirs.
@@ -2,7 +2,7 @@
2
2
  * Generate CSRF protection to use on all mutating (POST) requests. The
3
3
  * `csrfSupplyToken` function will make the current token available to views
4
4
  * via the `casa.csrfToken` variable, which you can use as so:
5
- * <input type="hidden" name="_csrf" value="{{ casa.csrfToken }}">
5
+ * <input type="hidden" name="_csrf" value="{{ casa.csrfToken }}">.
6
6
  */
7
7
 
8
8
  const csrf = require('csurf');
@@ -21,7 +21,7 @@ module.exports = (pageMeta = {}) => [mwBodyParser, (req, res, next) => {
21
21
  /**
22
22
  * Store data in request, clearing validation flags prior to validation.
23
23
  *
24
- * @param {object} data Data to store
24
+ * @param {object} data Data to store.
25
25
  * @returns {void}
26
26
  */
27
27
  function storeSessionData(data) {
@@ -15,16 +15,16 @@
15
15
  * hooks: {
16
16
  * pregather: function(req, res, next) {},
17
17
  * postvalidate: function(req, res, next) {},
18
- * prerender: function(req, res, next) {}
19
- * }
20
- * }
18
+ * prerender: function(req, res, next) {}.
19
+ * }.
20
+ * }.
21
21
  *
22
22
  * The `next()` function takes an optional error object containing an array of
23
23
  * errors for each field, e.g:
24
24
  * next({
25
25
  * <fieldName>: [{inline: '...', summary: '...'}, ...],
26
26
  * ...
27
- * })
27
+ * }).
28
28
  *
29
29
  * "Override":
30
30
  * -----------
@@ -35,7 +35,7 @@
35
35
  * get: function(req, res, next) {},
36
36
  * post: function(req, res, next) {}
37
37
  * }
38
- * };
38
+ * };.
39
39
  */
40
40
 
41
41
  const mwBodyParser = require('../../lib/commonBodyParser.js');
@@ -47,7 +47,9 @@ module.exports = (pageMeta = {}, mountUrl = '/', useStickyEdit = false) => (req,
47
47
  // `a, b, c, d` vs `a, c, d` <- should stop at `d` (`b` was removed) <- [.-..]
48
48
  // `a, b, c` vs `a, c, d` <- should stop at `d` (`b` was removed, `d` was added) <- [.-..+]
49
49
  let compareIndex = 0;
50
- const compareIndexMax = preGatherTraversalSnapshot.length - 1;
50
+ const compareIndexMax = useStickyEdit
51
+ ? currentTraversalSnapshot.length - 1
52
+ : preGatherTraversalSnapshot.length - 1;
51
53
  for (let i = 0, l = currentTraversalSnapshot.length; i < l; i++) {
52
54
  // Build waypoint URL for the current waypoint
53
55
  const waypointUrl = `${mountUrl}/${currentTraversalSnapshot[i].label.sourceOrigin || nextOrigin}/${currentTraversalSnapshot[i].source}`.replace(/\/+/g, '/');
@@ -64,7 +66,18 @@ module.exports = (pageMeta = {}, mountUrl = '/', useStickyEdit = false) => (req,
64
66
  while (compareIndex <= compareIndexMax) {
65
67
  nextWaypoint = waypointUrl;
66
68
  nextOrigin = currentTraversalSnapshot[i].label.targetOrigin || nextOrigin;
67
- if (currentTraversalSnapshot[i].source === preGatherTraversalSnapshot[compareIndex++]) {
69
+ compareIndex++;
70
+
71
+ // If we've exhausted the pre-gathering waypoints, then sticky mode
72
+ // should try to send us as far along the remaining journey as possible
73
+ if (useStickyEdit && preGatherTraversalSnapshot[compareIndex - 1] === undefined) {
74
+ nextWaypoint = `${mountUrl}/${nextOrigin}/${currentTraversalSnapshot[compareIndex - 1].source}`;
75
+ /* eslint-disable-next-line max-len */
76
+ nextOrigin = currentTraversalSnapshot[compareIndex - 1].label.targetOrigin || nextOrigin;
77
+ break;
78
+ }
79
+
80
+ if (currentTraversalSnapshot[i].source === preGatherTraversalSnapshot[compareIndex - 1]) {
68
81
  // The current snapshot may include more waypoints than than the
69
82
  // previous. In this case, if we've exhausted the list of previous
70
83
  // waypoints, with the last one being a match, we must leave the user on
@@ -5,7 +5,7 @@
5
5
  *
6
6
  * Enhances `res.locals.casa` with:
7
7
  * string journeyPreviousUrl = Absolute URL to the previous page in the journey
8
- * (if applicable)
8
+ * (if applicable).
9
9
  */
10
10
 
11
11
  const createLogger = require('../../lib/Logger.js');
@@ -1,9 +1,9 @@
1
1
  /**
2
2
  * Enhances `req.casa` with:
3
3
  * string journeyWaypointId = Converts requested URL into a string suitable for
4
- * use as a journey waypoint ID (i.e. remove trailing slashes)
4
+ * use as a journey waypoint ID (i.e. Remove trailing slashes)
5
5
  * object journeyOrigin = The origin from which traversals should start
6
- * Plan plan = The grand Plan
6
+ * Plan plan = The grand Plan.
7
7
  */
8
8
 
9
9
  const createLogger = require('../../lib/Logger.js');
@@ -12,7 +12,7 @@
12
12
  * visited beforehand, so this middleware must come after journey-rails.
13
13
  *
14
14
  * Format:
15
- * /current-waypoint?skipto=next-waypoint
15
+ * /current-waypoint?skipto=next-waypoint.
16
16
  */
17
17
 
18
18
  const { URL, URLSearchParams } = require('url');