hof 22.9.0-beta.v1 → 22.9.0-beta.v3

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 (316) hide show
  1. package/config/hof-defaults.js +1 -0
  2. package/frontend/template-partials/views/cookies.html +6 -6
  3. package/frontend/template-partials/views/partials/cookie-banner.html +11 -6
  4. package/lib/settings.js +1 -0
  5. package/package.json +1 -1
  6. package/package/.eslintignore +0 -1
  7. package/package/CHANGELOG.md +0 -232
  8. package/package/LICENSE +0 -21
  9. package/package/README.md +0 -1887
  10. package/package/bin/hof-build +0 -10
  11. package/package/bin/hof-transpiler +0 -12
  12. package/package/build/helpers/importer.js +0 -29
  13. package/package/build/helpers/local.js +0 -35
  14. package/package/build/helpers/resolver/import.js +0 -32
  15. package/package/build/helpers/resolver/nearest-package-root.js +0 -33
  16. package/package/build/helpers/resolver/package.js +0 -29
  17. package/package/build/helpers/resolver.js +0 -16
  18. package/package/build/index.js +0 -49
  19. package/package/build/lib/env.js +0 -36
  20. package/package/build/lib/mkdir.js +0 -9
  21. package/package/build/lib/run.js +0 -17
  22. package/package/build/lib/spawn.js +0 -18
  23. package/package/build/tasks/browserify/compress.js +0 -15
  24. package/package/build/tasks/browserify/index.js +0 -48
  25. package/package/build/tasks/build/index.js +0 -6
  26. package/package/build/tasks/images/index.js +0 -27
  27. package/package/build/tasks/index.js +0 -8
  28. package/package/build/tasks/sass/index.js +0 -67
  29. package/package/build/tasks/translate/index.js +0 -20
  30. package/package/build/tasks/watch/index.js +0 -161
  31. package/package/components/address-lookup/default-model.js +0 -76
  32. package/package/components/address-lookup/defaults.js +0 -25
  33. package/package/components/address-lookup/index.js +0 -251
  34. package/package/components/address-lookup/templates/address-lookup.html +0 -14
  35. package/package/components/address-lookup/templates/address.html +0 -22
  36. package/package/components/address-lookup/templates/postcode.html +0 -9
  37. package/package/components/clear-session/Readme.md +0 -46
  38. package/package/components/clear-session/index.js +0 -26
  39. package/package/components/combine-and-loop-fields/Readme.md +0 -42
  40. package/package/components/combine-and-loop-fields/index.js +0 -156
  41. package/package/components/date/fields.js +0 -16
  42. package/package/components/date/index.js +0 -172
  43. package/package/components/date/templates/date.html +0 -20
  44. package/package/components/emailer/assets/images/govuk_logotype_email.png +0 -0
  45. package/package/components/emailer/assets/images/ho_crest_27px.png +0 -0
  46. package/package/components/emailer/assets/images/spacer.gif +0 -0
  47. package/package/components/emailer/email-service.js +0 -51
  48. package/package/components/emailer/emailer.js +0 -53
  49. package/package/components/emailer/index.js +0 -74
  50. package/package/components/emailer/transports/debug.js +0 -74
  51. package/package/components/emailer/transports/index.js +0 -8
  52. package/package/components/emailer/transports/ses.js +0 -36
  53. package/package/components/emailer/transports/smtp.js +0 -26
  54. package/package/components/emailer/transports/stub.js +0 -5
  55. package/package/components/emailer/views/layout.html +0 -63
  56. package/package/components/homeoffice-countries/index.js +0 -22
  57. package/package/components/index.js +0 -13
  58. package/package/components/notify/index.js +0 -62
  59. package/package/components/notify/notify.js +0 -51
  60. package/package/components/session-timeout-warning/index.js +0 -67
  61. package/package/components/summary/index.js +0 -237
  62. package/package/config/builder-defaults.js +0 -45
  63. package/package/config/component-defaults.js +0 -13
  64. package/package/config/hof-defaults.js +0 -65
  65. package/package/config/rate-limits.js +0 -20
  66. package/package/config/sanitisation-rules.js +0 -32
  67. package/package/controller/base-controller.js +0 -296
  68. package/package/controller/behaviour-hooks.js +0 -51
  69. package/package/controller/behaviour-session.js +0 -64
  70. package/package/controller/controller.js +0 -258
  71. package/package/controller/deprecate-error.js +0 -10
  72. package/package/controller/formatting/formatters.js +0 -70
  73. package/package/controller/formatting/index.js +0 -32
  74. package/package/controller/index.js +0 -17
  75. package/package/controller/validation/email.js +0 -30
  76. package/package/controller/validation/index.js +0 -101
  77. package/package/controller/validation/validators.js +0 -181
  78. package/package/controller/validation-error.js +0 -14
  79. package/package/frontend/govuk-template/build/config.js +0 -24
  80. package/package/frontend/govuk-template/build/govuk_template.html +0 -102
  81. package/package/frontend/govuk-template/build/index.js +0 -23
  82. package/package/frontend/govuk-template/govuk_template_generated.html +0 -102
  83. package/package/frontend/govuk-template/index.js +0 -29
  84. package/package/frontend/index.js +0 -9
  85. package/package/frontend/template-mixins/mixins/helpers.js +0 -103
  86. package/package/frontend/template-mixins/mixins/index.js +0 -37
  87. package/package/frontend/template-mixins/mixins/render.js +0 -12
  88. package/package/frontend/template-mixins/mixins/template-mixins.js +0 -520
  89. package/package/frontend/template-mixins/partials/forms/checkbox-group.html +0 -47
  90. package/package/frontend/template-mixins/partials/forms/checkbox.html +0 -16
  91. package/package/frontend/template-mixins/partials/forms/input-submit.html +0 -1
  92. package/package/frontend/template-mixins/partials/forms/input-text-date.html +0 -37
  93. package/package/frontend/template-mixins/partials/forms/input-text-group.html +0 -45
  94. package/package/frontend/template-mixins/partials/forms/option-group.html +0 -43
  95. package/package/frontend/template-mixins/partials/forms/select.html +0 -17
  96. package/package/frontend/template-mixins/partials/forms/textarea-group.html +0 -37
  97. package/package/frontend/template-mixins/partials/mixins/panel.html +0 -4
  98. package/package/frontend/template-partials/index.js +0 -9
  99. package/package/frontend/template-partials/translations/index.js +0 -26
  100. package/package/frontend/template-partials/translations/src/cy/base.json +0 -4
  101. package/package/frontend/template-partials/translations/src/cy/buttons.json +0 -6
  102. package/package/frontend/template-partials/translations/src/cy/cookies.json +0 -104
  103. package/package/frontend/template-partials/translations/src/cy/errorlist.json +0 -6
  104. package/package/frontend/template-partials/translations/src/cy/errors.json +0 -18
  105. package/package/frontend/template-partials/translations/src/cy/terms.json +0 -28
  106. package/package/frontend/template-partials/translations/src/en/accessibility.json +0 -43
  107. package/package/frontend/template-partials/translations/src/en/base.json +0 -5
  108. package/package/frontend/template-partials/translations/src/en/buttons.json +0 -10
  109. package/package/frontend/template-partials/translations/src/en/cookies.json +0 -116
  110. package/package/frontend/template-partials/translations/src/en/errorlist.json +0 -7
  111. package/package/frontend/template-partials/translations/src/en/errors.json +0 -35
  112. package/package/frontend/template-partials/translations/src/en/exit.json +0 -5
  113. package/package/frontend/template-partials/translations/src/en/fields.json +0 -5
  114. package/package/frontend/template-partials/translations/src/en/journey.json +0 -6
  115. package/package/frontend/template-partials/translations/src/en/save-and-exit.json +0 -4
  116. package/package/frontend/template-partials/translations/src/en/terms.json +0 -28
  117. package/package/frontend/template-partials/views/404.html +0 -9
  118. package/package/frontend/template-partials/views/accessibility.html +0 -55
  119. package/package/frontend/template-partials/views/confirm.html +0 -8
  120. package/package/frontend/template-partials/views/confirmation.html +0 -19
  121. package/package/frontend/template-partials/views/content/en/what-happens-next.md +0 -0
  122. package/package/frontend/template-partials/views/cookie-error.html +0 -1
  123. package/package/frontend/template-partials/views/cookies.html +0 -84
  124. package/package/frontend/template-partials/views/email/data-row.html +0 -4
  125. package/package/frontend/template-partials/views/email/formatted.html +0 -12
  126. package/package/frontend/template-partials/views/email/layout.html +0 -63
  127. package/package/frontend/template-partials/views/email/raw.html +0 -11
  128. package/package/frontend/template-partials/views/email/section-row.html +0 -3
  129. package/package/frontend/template-partials/views/error.html +0 -20
  130. package/package/frontend/template-partials/views/exit.html +0 -9
  131. package/package/frontend/template-partials/views/feedback-submitted.html +0 -11
  132. package/package/frontend/template-partials/views/layout.html +0 -55
  133. package/package/frontend/template-partials/views/partials/analytics-table.html +0 -25
  134. package/package/frontend/template-partials/views/partials/back.html +0 -5
  135. package/package/frontend/template-partials/views/partials/bullet-list.html +0 -7
  136. package/package/frontend/template-partials/views/partials/confirmation-alert.html +0 -6
  137. package/package/frontend/template-partials/views/partials/continue.html +0 -5
  138. package/package/frontend/template-partials/views/partials/cookie-banner.html +0 -29
  139. package/package/frontend/template-partials/views/partials/cookie-notification.html +0 -4
  140. package/package/frontend/template-partials/views/partials/cookie-settings-button.html +0 -1
  141. package/package/frontend/template-partials/views/partials/cookie-settings-radio.html +0 -8
  142. package/package/frontend/template-partials/views/partials/details-summary.html +0 -8
  143. package/package/frontend/template-partials/views/partials/external-link.html +0 -1
  144. package/package/frontend/template-partials/views/partials/form.html +0 -10
  145. package/package/frontend/template-partials/views/partials/gatag.html +0 -60
  146. package/package/frontend/template-partials/views/partials/head.html +0 -31
  147. package/package/frontend/template-partials/views/partials/heading.html +0 -11
  148. package/package/frontend/template-partials/views/partials/items-table.html +0 -32
  149. package/package/frontend/template-partials/views/partials/maincontent-left.html +0 -10
  150. package/package/frontend/template-partials/views/partials/navigation.html +0 -8
  151. package/package/frontend/template-partials/views/partials/page.html +0 -23
  152. package/package/frontend/template-partials/views/partials/panel-indent.html +0 -3
  153. package/package/frontend/template-partials/views/partials/session-cookies-table.html +0 -28
  154. package/package/frontend/template-partials/views/partials/session-timeout-warning.html +0 -38
  155. package/package/frontend/template-partials/views/partials/summary-table-row.html +0 -14
  156. package/package/frontend/template-partials/views/partials/summary-table.html +0 -8
  157. package/package/frontend/template-partials/views/partials/table.html +0 -18
  158. package/package/frontend/template-partials/views/partials/validation-list.html +0 -3
  159. package/package/frontend/template-partials/views/partials/validation-summary.html +0 -25
  160. package/package/frontend/template-partials/views/partials/warn.html +0 -7
  161. package/package/frontend/template-partials/views/rate-limit-error.html +0 -10
  162. package/package/frontend/template-partials/views/save-and-exit.html +0 -17
  163. package/package/frontend/template-partials/views/service-unavailable.html +0 -13
  164. package/package/frontend/template-partials/views/session-timeout.html +0 -7
  165. package/package/frontend/template-partials/views/step.html +0 -14
  166. package/package/frontend/template-partials/views/terms.html +0 -26
  167. package/package/frontend/themes/gov-uk/client-js/cookieSettings.js +0 -145
  168. package/package/frontend/themes/gov-uk/client-js/govuk-cookies.js +0 -121
  169. package/package/frontend/themes/gov-uk/client-js/index.js +0 -27
  170. package/package/frontend/themes/gov-uk/client-js/session-timeout-dialog.js +0 -348
  171. package/package/frontend/themes/gov-uk/client-js/skip-to-main.js +0 -19
  172. package/package/frontend/themes/gov-uk/index.js +0 -9
  173. package/package/frontend/themes/gov-uk/styles/_base.scss +0 -17
  174. package/package/frontend/themes/gov-uk/styles/_check_your_answers.scss +0 -155
  175. package/package/frontend/themes/gov-uk/styles/_cookie-banner.scss +0 -111
  176. package/package/frontend/themes/gov-uk/styles/_cookie-settings.scss +0 -33
  177. package/package/frontend/themes/gov-uk/styles/_govuk_frontend_toolkit.scss +0 -23
  178. package/package/frontend/themes/gov-uk/styles/_helpers.scss +0 -5
  179. package/package/frontend/themes/gov-uk/styles/_layout.scss +0 -125
  180. package/package/frontend/themes/gov-uk/styles/_panel-indent.scss +0 -27
  181. package/package/frontend/themes/gov-uk/styles/_pdf.scss +0 -42
  182. package/package/frontend/themes/gov-uk/styles/_session-timeout-dialog.scss +0 -121
  183. package/package/frontend/themes/gov-uk/styles/_typography.scss +0 -27
  184. package/package/frontend/themes/gov-uk/styles/_variables.scss +0 -11
  185. package/package/frontend/themes/gov-uk/styles/govuk.scss +0 -43
  186. package/package/frontend/themes/gov-uk/styles/mixins.scss +0 -16
  187. package/package/frontend/themes/gov-uk/styles/modules/_alerts.scss +0 -73
  188. package/package/frontend/themes/gov-uk/styles/modules/_buttons.scss +0 -5
  189. package/package/frontend/themes/gov-uk/styles/modules/_character-count.scss +0 -8
  190. package/package/frontend/themes/gov-uk/styles/modules/_confirm-page.scss +0 -20
  191. package/package/frontend/themes/gov-uk/styles/modules/_lists.scss +0 -5
  192. package/package/frontend/themes/gov-uk/styles/modules/_progressive-reveal.scss +0 -17
  193. package/package/frontend/themes/gov-uk/styles/modules/_validation.scss +0 -51
  194. package/package/frontend/themes/index.js +0 -5
  195. package/package/frontend/toolkit/assets/images/passports/new-window-link-blue.png +0 -0
  196. package/package/frontend/toolkit/assets/images/passports/new-window-link.png +0 -0
  197. package/package/frontend/toolkit/assets/images/spinner.gif +0 -0
  198. package/package/frontend/toolkit/assets/javascript/character-count.js +0 -99
  199. package/package/frontend/toolkit/assets/javascript/form-focus.js +0 -101
  200. package/package/frontend/toolkit/assets/javascript/helpers.js +0 -177
  201. package/package/frontend/toolkit/assets/javascript/progressive-reveal.js +0 -72
  202. package/package/frontend/toolkit/assets/javascript/validation.js +0 -71
  203. package/package/frontend/toolkit/assets/javascript/vendor/details.polyfill.js +0 -189
  204. package/package/frontend/toolkit/assets/javascript/vendor/indexof.polyfill.js +0 -39
  205. package/package/frontend/toolkit/assets/javascript/vendor/safari-cachebuster.js +0 -6
  206. package/package/frontend/toolkit/assets/stylesheets/_base.scss +0 -17
  207. package/package/frontend/toolkit/assets/stylesheets/_helpers.scss +0 -5
  208. package/package/frontend/toolkit/assets/stylesheets/_layout.scss +0 -118
  209. package/package/frontend/toolkit/assets/stylesheets/_typography.scss +0 -27
  210. package/package/frontend/toolkit/assets/stylesheets/_variables.scss +0 -11
  211. package/package/frontend/toolkit/assets/stylesheets/app.scss +0 -30
  212. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_buttons.scss +0 -47
  213. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_details.scss +0 -38
  214. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_elements-typography.scss +0 -175
  215. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_forms.scss +0 -167
  216. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_helpers.scss +0 -39
  217. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_layout.scss +0 -67
  218. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_lists.scss +0 -40
  219. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_panels.scss +0 -29
  220. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_reset.scss +0 -33
  221. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/_tables.scss +0 -33
  222. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/forms/_form-block-labels.scss +0 -63
  223. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/forms/_form-date.scss +0 -39
  224. package/package/frontend/toolkit/assets/stylesheets/govuk-elements/forms/_form-validation.scss +0 -63
  225. package/package/frontend/toolkit/assets/stylesheets/mixins.scss +0 -16
  226. package/package/frontend/toolkit/assets/stylesheets/modules/_alerts.scss +0 -73
  227. package/package/frontend/toolkit/assets/stylesheets/modules/_buttons.scss +0 -5
  228. package/package/frontend/toolkit/assets/stylesheets/modules/_confirm-page.scss +0 -20
  229. package/package/frontend/toolkit/assets/stylesheets/modules/_lists.scss +0 -5
  230. package/package/frontend/toolkit/assets/stylesheets/modules/_progressive-reveal.scss +0 -17
  231. package/package/frontend/toolkit/assets/stylesheets/modules/_validation.scss +0 -51
  232. package/package/frontend/toolkit/index.js +0 -10
  233. package/package/index.js +0 -351
  234. package/package/lib/deindex.js +0 -18
  235. package/package/lib/encryption.js +0 -23
  236. package/package/lib/ga-tag.js +0 -89
  237. package/package/lib/health.js +0 -26
  238. package/package/lib/helpers.js +0 -66
  239. package/package/lib/logger.js +0 -65
  240. package/package/lib/markdown.js +0 -46
  241. package/package/lib/router.js +0 -111
  242. package/package/lib/serve-static.js +0 -12
  243. package/package/lib/sessions.js +0 -82
  244. package/package/lib/settings.js +0 -74
  245. package/package/lib/which.js +0 -28
  246. package/package/middleware/cookies.js +0 -43
  247. package/package/middleware/deep-translate.js +0 -32
  248. package/package/middleware/errors.js +0 -119
  249. package/package/middleware/index.js +0 -10
  250. package/package/middleware/not-found.js +0 -38
  251. package/package/middleware/rate-limiter.js +0 -98
  252. package/package/middleware/service-unavailable.js +0 -64
  253. package/package/model/apis/axios-settings.js +0 -21
  254. package/package/model/apis/html-to-pdf-converter.js +0 -35
  255. package/package/model/apis/index.js +0 -5
  256. package/package/model/index.js +0 -348
  257. package/package/package.json +0 -147
  258. package/package/sandbox/README.md +0 -66
  259. package/package/sandbox/apps/sandbox/behaviours/clear-session.js +0 -8
  260. package/package/sandbox/apps/sandbox/behaviours/country-select.js +0 -10
  261. package/package/sandbox/apps/sandbox/behaviours/international-number.js +0 -22
  262. package/package/sandbox/apps/sandbox/fields.js +0 -128
  263. package/package/sandbox/apps/sandbox/index.js +0 -99
  264. package/package/sandbox/apps/sandbox/lib/staticAppealStages.js +0 -189
  265. package/package/sandbox/apps/sandbox/sections/summary-data-sections.js +0 -43
  266. package/package/sandbox/apps/sandbox/translations/src/en/errors.json +0 -5
  267. package/package/sandbox/apps/sandbox/translations/src/en/exit.json +0 -4
  268. package/package/sandbox/apps/sandbox/translations/src/en/fields.json +0 -101
  269. package/package/sandbox/apps/sandbox/translations/src/en/journey.json +0 -7
  270. package/package/sandbox/apps/sandbox/translations/src/en/pages.json +0 -72
  271. package/package/sandbox/apps/sandbox/translations/src/en/validation.json +0 -54
  272. package/package/sandbox/apps/sandbox/views/form-guidance-link.html +0 -8
  273. package/package/sandbox/apps/sandbox/views/save-and-exit.html +0 -19
  274. package/package/sandbox/assets/images/icons/icon-caret-left.png +0 -0
  275. package/package/sandbox/assets/images/icons/icon-complete.png +0 -0
  276. package/package/sandbox/assets/images/icons/icon-cross-remove-sign.png +0 -0
  277. package/package/sandbox/assets/js/index.js +0 -70
  278. package/package/sandbox/assets/scss/app.scss +0 -27
  279. package/package/sandbox/codecept.conf.js +0 -15
  280. package/package/sandbox/config.js +0 -17
  281. package/package/sandbox/package.json +0 -26
  282. package/package/sandbox/server.js +0 -23
  283. package/package/sandbox/yarn.lock +0 -262
  284. package/package/transpiler/index.js +0 -2
  285. package/package/transpiler/lib/aggregate.js +0 -32
  286. package/package/transpiler/lib/build.js +0 -15
  287. package/package/transpiler/lib/compile.js +0 -12
  288. package/package/transpiler/lib/expand-dirs.js +0 -14
  289. package/package/transpiler/lib/write-files.js +0 -24
  290. package/package/utilities/autofill/index.js +0 -189
  291. package/package/utilities/autofill/inputs.js +0 -60
  292. package/package/utilities/countries.js +0 -12
  293. package/package/utilities/helpers/index.js +0 -189
  294. package/package/utilities/index.js +0 -9
  295. package/package/utilities/reqres/index.js +0 -18
  296. package/package/utilities/test-data/data/domain.json +0 -7
  297. package/package/utilities/test-data/data/firstname.json +0 -16
  298. package/package/utilities/test-data/data/lastname.json +0 -10
  299. package/package/utilities/test-data/data/postcode.json +0 -12
  300. package/package/utilities/test-data/data/streetname.json +0 -8
  301. package/package/utilities/test-data/data/streetsuffix.json +0 -7
  302. package/package/utilities/test-data/data/town.json +0 -9
  303. package/package/utilities/test-data/index.js +0 -67
  304. package/package/wizard/behaviours/complete.js +0 -20
  305. package/package/wizard/behaviours/index.js +0 -5
  306. package/package/wizard/index.js +0 -124
  307. package/package/wizard/middleware/back-links.js +0 -68
  308. package/package/wizard/middleware/check-complete.js +0 -13
  309. package/package/wizard/middleware/check-progress.js +0 -139
  310. package/package/wizard/middleware/check-session.js +0 -17
  311. package/package/wizard/middleware/csrf.js +0 -47
  312. package/package/wizard/middleware/session-model.js +0 -11
  313. package/package/wizard/middleware/session.js +0 -9
  314. package/package/wizard/model.js +0 -29
  315. package/package/wizard/util/constants.js +0 -5
  316. package/package/wizard/util/helpers.js +0 -19
@@ -1,520 +0,0 @@
1
- /* eslint-disable no-param-reassign, max-len, consistent-return */
2
- 'use strict';
3
-
4
- const fs = require('fs');
5
- const path = require('path');
6
-
7
- const Hogan = require('hogan.js');
8
- const _ = require('underscore');
9
-
10
- const renderer = require('./render');
11
-
12
- const PANELMIXIN = 'partials/mixins/panel';
13
- const PARTIALS = [
14
- 'partials/forms/input-text-group',
15
- 'partials/forms/input-text-date',
16
- 'partials/forms/input-submit',
17
- 'partials/forms/select',
18
- 'partials/forms/checkbox',
19
- 'partials/forms/textarea-group',
20
- 'partials/forms/option-group',
21
- 'partials/forms/checkbox-group'
22
- ];
23
-
24
- // This returns a middleware that places mixins against the `res.locals` object.
25
- //
26
- // It should be given:
27
- // - options:
28
- // - viewDirectory: the folder in which templates are found in.
29
- // - viewEngine: the type of view, defaults to 'html'.
30
- // - sharedTranslationsKey: used to find translations relatively within
31
- // the translations.json. Useful for field and button labels.
32
- module.exports = function (options) {
33
- const compiled = {};
34
- const templateCache = {};
35
-
36
- function maxlength(field) {
37
- const validation = field.validate || [];
38
- const ml = _.findWhere(validation, { type: 'maxlength' }) || _.findWhere(validation, { type: 'exactlength' });
39
- if (ml) {
40
- return _.isArray(ml.arguments) ? ml.arguments[0] : ml.arguments;
41
- }
42
- return null;
43
- }
44
-
45
- function maxword(field) {
46
- const validation = field.validate || [];
47
- const mw = _.findWhere(validation, { type: 'maxword' });
48
- if (mw) {
49
- return _.isArray(mw.arguments) ? mw.arguments[0] : mw.arguments;
50
- }
51
- return null;
52
- }
53
-
54
- function type(field) {
55
- return field.type || 'text';
56
- }
57
-
58
- function classNameString(name) {
59
- if (_.isArray(name)) {
60
- return name.join(' ');
61
- }
62
- return name;
63
- }
64
-
65
- function classNames(field, prop) {
66
- prop = prop || 'className';
67
- if (field[prop]) {
68
- return classNameString(field[prop]);
69
- }
70
- return '';
71
- }
72
-
73
- return function (req, res, next) {
74
- const roots = [].concat(req.app.get('views')).concat(options.viewsDirectory);
75
- const View = req.app.get('view');
76
-
77
- // wrap in try catch to throw an error if any one template cannot be resolved
78
- try {
79
- PARTIALS.forEach(relativeTemplatePath => {
80
- if (compiled[relativeTemplatePath]) {
81
- return;
82
- }
83
- const viewExtension = '.' + options.viewEngine;
84
- const engines = {};
85
- engines[viewExtension] = {};
86
- const view = new View(relativeTemplatePath, {
87
- defaultEngine: options.viewEngine,
88
- root: roots,
89
- engines: engines
90
- });
91
- if (!view.path) {
92
- throw new Error('Could not find template file: ' + relativeTemplatePath);
93
- }
94
- const compiledTemplate = Hogan.compile(fs.readFileSync(view.path).toString());
95
- compiled[relativeTemplatePath] = compiledTemplate;
96
- });
97
- } catch (e) {
98
- return next(e);
99
- }
100
-
101
- const hoganRender = renderer(res);
102
-
103
- const t = function (key) {
104
- return hoganRender(req.translate(options.sharedTranslationsKey + key), this);
105
- };
106
-
107
- // Like t() but returns null on failed translations
108
- const conditionalTranslate = function (key) {
109
- key = options.sharedTranslationsKey + key;
110
- const translated = req.translate(key);
111
- return translated !== key ? translated : null;
112
- };
113
-
114
- const getTranslationKey = function (field, key, property) {
115
- return field[property] ? field[property] : 'fields.' + key + '.' + property;
116
- };
117
-
118
- function readTemplate(name) {
119
- if (templateCache[name]) {
120
- return templateCache[name];
121
- }
122
- const data = fs.readFileSync(`${name}.${options.viewEngine}`).toString();
123
- templateCache[name] = data;
124
- return data;
125
- }
126
-
127
- /*
128
- * helper function which takes a child string which
129
- * can either be the name of a partial in the format
130
- * partial/{partial-name}, the name of a template mixin
131
- * or a raw template string to render
132
- */
133
- function getTemplate(child) {
134
- res.locals.partials = res.locals.partials || {};
135
-
136
-
137
- const re = /^partials\/(.+)/i;
138
- const match = child.match(re);
139
-
140
- if (match) {
141
- return readTemplate(res.locals.partials['partials-' + match[1]]);
142
- } else if (child === 'html' || res.locals[child]) {
143
- if (res.locals.partials['partials-mixins-panel']) {
144
- return readTemplate(res.locals.partials['partials-mixins-panel']);
145
- }
146
- const panelPath = path.join(options.viewsDirectory, PANELMIXIN);
147
- return readTemplate(panelPath);
148
- }
149
- return child;
150
- }
151
-
152
- function isRequired(field) {
153
- if (field.required !== undefined) {
154
- return field.required;
155
- } else if (field.validate) {
156
- return field.validate.indexOf('required') > -1;
157
- }
158
- return false;
159
- }
160
-
161
- function renderMixin() {
162
- return function () {
163
- if (this.child) {
164
- if (this.child === 'html') {
165
- try {
166
- const key = this.toggle;
167
- return res.locals.fields.find(function (field) {
168
- return field.key === key;
169
- }).html;
170
- } catch (err) {
171
- const msg = `html property not set on field: ${this.toggle}. Did you forget to use a component?`;
172
- next(new Error(msg));
173
- }
174
- }
175
- if (this[this.child]) {
176
- return this[this.child]().call(this, this.toggle);
177
- }
178
- }
179
- };
180
- }
181
-
182
- function renderChild() {
183
- return function () {
184
- if (this.child) {
185
- const templateString = getTemplate(this.child, this.toggle);
186
- const template = Hogan.compile(templateString);
187
- return template.render(Object.assign({
188
- renderMixin: renderMixin.bind(this)
189
- }, res.locals, this), _.mapObject(res.locals.partials, function (partialpath) {
190
- return readTemplate(partialpath);
191
- }));
192
- }
193
- };
194
- }
195
-
196
- // eslint-disable-next-line complexity
197
- function inputText(key, extension) {
198
- extension = extension || {};
199
-
200
- const field = Object.assign({}, this.options.fields[key] || options.fields[key]);
201
- const hKey = getTranslationKey(field, key, 'hint');
202
- const lKey = getTranslationKey(field, key, 'label');
203
- const hint = conditionalTranslate(hKey);
204
- const required = isRequired(field);
205
- const labelClassName = classNames(field, 'labelClassName');
206
- const autocomplete = field.autocomplete || extension.autocomplete;
207
-
208
- return Object.assign({}, extension, {
209
- id: key,
210
- className: extension.className || classNames(field),
211
- type: extension.type || type(field),
212
- value: this.values && this.values[key],
213
- label: t(lKey),
214
- labelClassName: labelClassName ? `govuk-label ${labelClassName}` : 'govuk-label',
215
- formGroupClassName: classNames(field, 'formGroupClassName') || extension.formGroupClassName || 'govuk-form-group',
216
- hint: hint,
217
- hintId: extension.hintId || (hint ? key + '-hint' : null),
218
- error: this.errors && this.errors[key],
219
- maxlengthAttribute: field.maxlengthAttribute === true,
220
- maxlength: maxlength(field) || extension.maxlength,
221
- maxword: maxword(field) || extension.maxword,
222
- required: required,
223
- pattern: extension.pattern,
224
- date: extension.date,
225
- autocomplete: autocomplete,
226
- child: field.child,
227
- isPageHeading: field.isPageHeading,
228
- attributes: field.attributes,
229
- isPrefixOrSuffix: _.map(field.attributes, item => {if (item.prefix || item.suffix !== undefined) return true;}),
230
- isMaxlengthOrMaxword: maxlength(field) || extension.maxlength || maxword(field) || extension.maxword,
231
- renderChild: renderChild.bind(this)
232
- });
233
- }
234
-
235
- function optionGroup(key, opts) {
236
- opts = opts || {};
237
- const field = Object.assign({}, this.options.fields[key] || options.fields[key]);
238
- const legend = field.legend;
239
- const detail = field.detail;
240
- const warningValue = 'fields.' + key + '.warning';
241
- let legendClassName;
242
- let legendValue = 'fields.' + key + '.legend';
243
- if (legend) {
244
- if (legend.className) {
245
- legendClassName = classNameString(legend.className);
246
- }
247
- if (typeof legend.value !== 'undefined') {
248
- legendValue = legend.value;
249
- }
250
- }
251
- return {
252
- key: key,
253
- error: this.errors && this.errors[key],
254
- legend: t(legendValue),
255
- legendClassName: legendClassName,
256
- role: opts.type === 'radio' ? 'radiogroup' : 'group',
257
- isPageHeading: field.isPageHeading,
258
- isWarning: field.isWarning,
259
- warning: t(warningValue),
260
- detail: detail ? detail : '',
261
- hint: conditionalTranslate(getTranslationKey(field, key, 'hint')),
262
- options: _.map(field.options, function (obj) {
263
- let selected = false;
264
- let label;
265
- let value;
266
- let toggle;
267
- let child;
268
- let optionHint;
269
- let useHintText;
270
-
271
- if (typeof obj === 'string') {
272
- value = obj;
273
- label = 'fields.' + key + '.options.' + obj + '.label';
274
- optionHint = 'fields.' + key + '.options.' + obj + '.hint';
275
- } else {
276
- value = obj.value;
277
- label = obj.label || 'fields.' + key + '.options.' + obj.value + '.label';
278
- toggle = obj.toggle;
279
- child = obj.child;
280
- useHintText = obj.useHintText;
281
- optionHint = obj.hint || 'fields.' + key + '.options.' + obj.value + '.hint';
282
- }
283
-
284
- if (this.values && this.values[key] !== undefined) {
285
- const selectedValue = this.values[key];
286
- selected = Array.isArray(selectedValue)
287
- ? selectedValue.indexOf(value) > -1
288
- : selectedValue === value;
289
- }
290
-
291
- return {
292
- label: t(label) || '',
293
- value: value,
294
- type: opts.type,
295
- selected: selected,
296
- radioOption: opts.type === 'radio',
297
- toggle: toggle,
298
- child: child,
299
- optionHint: useHintText ? optionHint : conditionalTranslate(optionHint) || ''
300
- };
301
- }, this),
302
- className: classNames(field),
303
- renderChild: renderChild.bind(this)
304
- };
305
- }
306
-
307
- // eslint-disable-next-line complexity
308
- function checkbox(key, opts) {
309
- opts = opts || {};
310
- const field = Object.assign({}, this.options.fields[key] || options.fields[key]);
311
- opts.required = opts.required || false;
312
- opts.toggle = field.toggle;
313
- let selected = false;
314
- const fieldLabel = field.label ? field.label : false;
315
- if (this.values && this.values[key] !== undefined) {
316
- selected = this.values[key].toString() === 'true';
317
- }
318
- return Object.assign(opts, {
319
- key: key,
320
- error: this.errors && this.errors[key],
321
- invalid: this.errors && this.errors[key] && opts.required,
322
- label: t(fieldLabel || 'fields.' + key + '.label'),
323
- hint: conditionalTranslate(getTranslationKey(field, key, 'hint')),
324
- selected: selected,
325
- className: classNames(field) || 'govuk-label govuk-checkboxes__label',
326
- child: field.child,
327
- renderChild: renderChild.bind(this)
328
- });
329
- }
330
-
331
- const mixins = {
332
- 'input-text': {
333
- path: 'partials/forms/input-text-group',
334
- renderWith: inputText
335
- },
336
- 'input-text-compound': {
337
- path: 'partials/forms/input-text-group',
338
- renderWith: inputText,
339
- options: {
340
- compound: true
341
- }
342
- },
343
- 'input-text-code': {
344
- path: 'partials/forms/input-text-group',
345
- renderWith: inputText,
346
- options: {
347
- className: 'input-code'
348
- }
349
- },
350
- 'input-number': {
351
- path: 'partials/forms/input-text-group',
352
- renderWith: inputText,
353
- options: {
354
- pattern: '[0-9]*'
355
- }
356
- },
357
- 'input-phone': {
358
- path: 'partials/forms/input-text-group',
359
- renderWith: inputText,
360
- options: {
361
- maxlength: 18
362
- }
363
- },
364
- 'input-file': {
365
- path: 'partials/forms/input-text-group',
366
- renderWith: inputText,
367
- options: {
368
- type: 'file'
369
- }
370
- },
371
- textarea: {
372
- path: 'partials/forms/textarea-group',
373
- renderWith: inputText
374
- },
375
- 'radio-group': {
376
- path: 'partials/forms/option-group',
377
- renderWith: optionGroup,
378
- options: {
379
- type: 'radio'
380
- }
381
- },
382
- 'checkbox-group': {
383
- path: 'partials/forms/checkbox-group',
384
- renderWith: optionGroup,
385
- options: {
386
- type: 'checkbox'
387
- }
388
- },
389
- select: {
390
- path: 'partials/forms/select',
391
- renderWith: inputText,
392
- options: optionGroup
393
- },
394
- checkbox: {
395
- path: 'partials/forms/checkbox',
396
- renderWith: checkbox
397
- },
398
- 'checkbox-compound': {
399
- path: 'partials/forms/checkbox',
400
- renderWith: checkbox,
401
- options: {
402
- compound: true
403
- }
404
- },
405
- 'checkbox-required': {
406
- path: 'partials/forms/checkbox',
407
- renderWith: checkbox,
408
- options: {
409
- required: true
410
- }
411
- },
412
- 'input-submit': {
413
- handler: function () {
414
- return function (props) {
415
- props = (props || '').split(' ');
416
- const def = 'next';
417
- const value = props[0] || def;
418
- const id = props[1];
419
-
420
- const obj = {
421
- value: t('buttons.' + value),
422
- id: id
423
- };
424
- return compiled['partials/forms/input-submit'].render(obj);
425
- };
426
- }
427
- },
428
- 'input-date': {
429
- handler: function () {
430
- /**
431
- * props: '[value] [id]'
432
- */
433
- return function (key) {
434
- const field = Object.assign({}, this.options.fields[key] || options.fields[key]);
435
- key = hoganRender(key, this);
436
- // Exact unless there is a inexact property against the fields key.
437
- const isExact = field.inexact !== true;
438
-
439
- let autocomplete = field.autocomplete || {};
440
- if (autocomplete === 'off') {
441
- autocomplete = {
442
- day: 'off',
443
- month: 'off',
444
- year: 'off'
445
- };
446
- } else if (typeof autocomplete === 'string') {
447
- autocomplete = {
448
- day: autocomplete + '-day',
449
- month: autocomplete + '-month',
450
- year: autocomplete + '-year'
451
- };
452
- }
453
- const isThisRequired = field.validate ? field.validate.indexOf('required') > -1 : false;
454
- const formGroupClassName = (field.formGroup && field.formGroup.className) ? field.formGroup.className : '';
455
- const classNameDay = (field.controlsClass && field.controlsClass.day) ? field.controlsClass.day : 'govuk-date-input__input govuk-input--width-2';
456
- const classNameMonth = (field.controlsClass && field.controlsClass.month) ? field.controlsClass.month : 'govuk-date-input__input govuk-input--width-2';
457
- const classNameYear = (field.controlsClass && field.controlsClass.year) ? field.controlsClass.year : 'govuk-date-input__input govuk-input--width-4';
458
-
459
- const parts = [];
460
-
461
- if (isExact) {
462
- 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 }));
463
- parts.push(dayPart);
464
- }
465
-
466
- 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 }));
467
- 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 }));
468
-
469
- return parts.concat(monthPart, yearPart).join('\n');
470
- };
471
- }
472
- }
473
- };
474
-
475
- // loop through mixins object and attach their handler methods
476
- // to res.locals['mixin-name'].
477
- _.each(mixins, function (mixin, name) {
478
- const handler = _.isFunction(mixin.handler) ? mixin.handler : function () {
479
- return function (key) {
480
- this.options = this.options || {};
481
- this.options.fields = this.options.fields || {};
482
- key = hoganRender(key, this);
483
- return compiled[mixin.path]
484
- .render(mixin.renderWith.call(this, key, _.isFunction(mixin.options)
485
- ? mixin.options.call(this, key)
486
- : mixin.options
487
- ));
488
- };
489
- };
490
- res.locals[name] = handler;
491
- });
492
-
493
- res.locals.renderField = function () {
494
- return function (key) {
495
- if (key) {
496
- const fields = this.fields || res.locals.fields;
497
- const field = fields.find(f => f.key === key);
498
- if (field) {
499
- Object.assign(this, field);
500
- } else {
501
- throw new Error('Could not find field: ' + key);
502
- }
503
- }
504
- if (this.disableRender) {
505
- return null;
506
- }
507
- if (this.html) {
508
- return this.html;
509
- }
510
- const mixin = this.mixin || 'input-text';
511
- if (mixin && res.locals[mixin] && typeof res.locals[mixin] === 'function') {
512
- return res.locals[mixin]().call(Object.assign({}, res.locals), this.key);
513
- }
514
- throw new Error('Mixin: "' + mixin + '" not found');
515
- };
516
- };
517
-
518
- next();
519
- };
520
- };
@@ -1,47 +0,0 @@
1
- <div id="{{key}}-group" class="govuk-form-group{{#className}} {{className}} {{/className}}{{#formGroupClassName}} {{formGroupClassName}}{{/formGroupClassName}}{{#error}} govuk-form-group--error{{/error}}">
2
- <fieldset class="govuk-fieldset" {{#hint}} aria-describedby="{{key}}-hint"{{/hint}}>
3
- <legend class="govuk-fieldset__legend {{#isPageHeading}}govuk-fieldset__legend--l{{/isPageHeading}}{{#legendClassName}} {{legendClassName}}{{/legendClassName}}">
4
- {{#isPageHeading}}<h1 class="govuk-fieldset__heading">{{/isPageHeading}}
5
- {{legend}}
6
- {{#isPageHeading}}</h1>{{/isPageHeading}}
7
- </legend>
8
- {{#isWarning}}
9
- <div class="govuk-warning-text">
10
- <span class="govuk-warning-text__icon" aria-hidden="true">!</span>
11
- <strong class="govuk-warning-text__text">
12
- <span class="govuk-warning-text__assistive">Warning</span>
13
- {{warning}}
14
- </strong>
15
- </div>
16
- {{/isWarning}}
17
- {{#hint}}<div id="{{key}}-hint" class="govuk-hint">{{{hint}}}</div>{{/hint}}
18
- {{#error}}
19
- <p id="{{key}}-error" class="govuk-error-message">
20
- <span class="govuk-visually-hidden">Error:</span> {{error.message}}
21
- </span>
22
- {{/error}}
23
- {{{detail}}}
24
- <div class="govuk-checkboxes" data-module="govuk-checkboxes">
25
- {{#options}}
26
- <div class="govuk-checkboxes__item">
27
- <input
28
- class="govuk-checkboxes__input"
29
- type="{{type}}"
30
- name="{{key}}"
31
- id="{{key}}-{{value}}"
32
- value="{{value}}"
33
- {{#toggle}} data-toggle="{{toggle}}"{{/toggle}}
34
- {{#selected}} checked="checked"{{/selected}}
35
- {{^error}}{{#optionHint}} aria-describedby="{{key}}-{{value}}-hint"{{/optionHint}}{{^optionHint}}{{#hint}} aria-describedby="{{key}}-hint"{{/hint}}{{/optionHint}}{{/error}}
36
- {{#error}} aria-describedby="{{key}}-error" aria-invalid="true"{{/error}}
37
- >
38
- <label class="govuk-label govuk-checkboxes__label" for="{{key}}-{{value}}">
39
- {{{label}}}
40
- {{#optionHint}}<div id="{{key}}-{{value}}-item-hint" class="govuk-hint">{{optionHint}}</div>{{/optionHint}}
41
- </label>
42
- </div>
43
- {{#renderChild}}{{/renderChild}}
44
- {{/options}}
45
- </div>
46
- </fieldset>
47
- </div>
@@ -1,16 +0,0 @@
1
- <div id="{{key}}-group" class="govuk-form-group {{#compound}} form-group-compound{{/compound}}{{#formGroupClassName}} {{formGroupClassName}}{{/formGroupClassName}}{{#error}} govuk-form-group--error{{/error}}">
2
- {{#error}}<p class="govuk-error-message" aria-hidden="true">{{error.message}}</p>{{/error}}
3
- <div class="govuk-checkboxes__item">
4
- <input class="govuk-checkboxes__input" type="checkbox" id="{{key}}" name="{{key}}" value="true" aria-required="{{required}}"{{#error}} aria-invalid="true"{{/error}}{{^error}}{{#toggle}} data-toggle="{{toggle}}"{{/toggle}}{{#selected}} checked="checked"{{/selected}}{{/error}}>
5
- <label for="{{key}}" class="{{#className}}{{className}} {{/className}}{{#invalid}}invalid-input{{/invalid}}">
6
- {{{label}}}
7
- {{#error}}<span class="visuallyhidden">{{error.message}}</span>{{/error}}
8
- </label>
9
- {{#hint}}
10
- <div id="{{key}}-hint" class="govuk-hint govuk-checkboxes__hint">
11
- {{{hint}}}
12
- </div>
13
- {{/hint}}
14
- </div>
15
- {{#renderChild}}{{/renderChild}}
16
- </div>
@@ -1 +0,0 @@
1
- <input type="submit" {{#id}}id="{{id}}"{{/id}} value="{{{value}}}" class="govuk-button">
@@ -1,37 +0,0 @@
1
- <div class="govuk-date-input__item">
2
- <div id="{{id}}-group" class="{{#formGroupClassName}} {{formGroupClassName}}{{/formGroupClassName}}">
3
- <label for="{{id}}" class="{{labelClassName}}">
4
- <span class="label-text">{{{label}}}</span>
5
- </label>
6
- {{#hint}}<span {{$hintId}}id="{{hintId}}" {{/hintId}}class="govuk-hint">{{{hint}}}</span>{{/hint}}
7
- {{#renderChild}}{{/renderChild}}
8
- {{#attributes}}
9
- {{#prefix}}
10
- <div class="govuk-input__prefix" aria-hidden="true">{{prefix}}</div>
11
- {{/prefix}}
12
- {{/attributes}}
13
- <input
14
- type="{{type}}"
15
- name="{{id}}"
16
- id="{{id}}"
17
- class="govuk-input{{#className}} {{className}}{{/className}}{{#error}} govuk-input--error{{/error}}"
18
- aria-required="{{required}}"
19
- {{#value}} value="{{value}}"{{/value}}
20
- {{#min}} min="{{min}}"{{/min}}
21
- {{#max}} max="{{max}}"{{/max}}
22
- {{#maxlength}} maxlength="{{maxlength}}"{{/maxlength}}
23
- {{#pattern}} pattern="{{pattern}}"{{/pattern}}
24
- {{#hintId}} aria-describedby="{{hintId}}"{{/hintId}}
25
- {{#error}} aria-invalid="true"{{/error}}
26
- {{#autocomplete}} autocomplete="{{autocomplete}}"{{/autocomplete}}
27
- {{#attributes}}
28
- {{attribute}}="{{value}}"
29
- {{/attributes}}
30
- >
31
- {{#attributes}}
32
- {{#suffix}}
33
- <div class="govuk-input__prefix" aria-hidden="true">{{suffix}}</div>
34
- {{/suffix}}
35
- {{/attributes}}
36
- </div>
37
- </div>
@@ -1,45 +0,0 @@
1
- <div id="{{id}}-group" class="{{#compound}} form-group-compound{{/compound}}{{#formGroupClassName}}{{formGroupClassName}}{{/formGroupClassName}}{{#error}} govuk-form-group--error{{/error}}">
2
- {{#isPageHeading}}<h1 class="govuk-label-wrapper">{{/isPageHeading}}<label for="{{id}}" class="{{labelClassName}} {{#isPageHeading}}govuk-label--l{{/isPageHeading}}">
3
- {{{label}}}
4
- </label>
5
- {{#isPageHeading}}</h1>{{/isPageHeading}}
6
- {{#hint}}<span {{$hintId}}id="{{hintId}}" {{/hintId}}class="govuk-hint">{{{hint}}}</span>{{/hint}}
7
- {{#error}}
8
- <p class="govuk-error-message">
9
- <span class="govuk-visually-hidden">Error:</span> {{error.message}}
10
- </p>
11
- {{/error}}
12
- {{#renderChild}}{{/renderChild}}
13
- {{#isPrefixOrSuffix}}<div class="govuk-input__wrapper">{{/isPrefixOrSuffix}}
14
- {{#attributes}}
15
- {{#prefix}}
16
- <div class="govuk-input__prefix" aria-hidden="true">{{prefix}}</div>
17
- {{/prefix}}
18
- {{/attributes}}
19
- <input
20
- type="{{type}}"
21
- name="{{id}}"
22
- id="{{id}}"
23
- class="{{^className}}govuk-input{{/className}}{{#className}}{{className}}{{/className}}{{#error}} govuk-input--error{{/error}}"
24
- aria-required="{{required}}"
25
- {{#value}} value="{{value}}"{{/value}}
26
- {{#min}} min="{{min}}"{{/min}}
27
- {{#max}} max="{{max}}"{{/max}}
28
- {{#maxlengthAttribute}}
29
- {{#maxlength}} maxlength="{{maxlength}}"{{/maxlength}}
30
- {{/maxlengthAttribute}}
31
- {{#pattern}} pattern="{{pattern}}"{{/pattern}}
32
- {{#hintId}} aria-describedby="{{hintId}}"{{/hintId}}
33
- {{#error}} aria-invalid="true"{{/error}}
34
- {{#autocomplete}} autocomplete="{{autocomplete}}"{{/autocomplete}}
35
- {{#attributes}}
36
- {{attribute}}="{{value}}"
37
- {{/attributes}}
38
- >
39
- {{#attributes}}
40
- {{#suffix}}
41
- <div class="govuk-input__suffix" aria-hidden="true">{{suffix}}</div>
42
- {{/suffix}}
43
- {{/attributes}}
44
- {{#isPrefixOrSuffix}}</div>{{/isPrefixOrSuffix}}
45
- </div>