hof 21.0.0-instrumentation-beta.0 → 21.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. package/.github/workflows/automate-publish.yml +1 -1
  2. package/.github/workflows/automate-tag.yml +4 -4
  3. package/.nyc_output/39365c14-40b7-4634-b733-940b72a11984.json +1 -0
  4. package/.nyc_output/processinfo/39365c14-40b7-4634-b733-940b72a11984.json +1 -0
  5. package/.nyc_output/processinfo/index.json +1 -1
  6. package/CHANGELOG.md +21 -0
  7. package/README.md +340 -256
  8. package/build/tasks/sass/index.js +3 -1
  9. package/build/tasks/watch/index.js +1 -1
  10. package/codeReviewChecklist.md +22 -0
  11. package/components/combine-and-loop-fields/Readme.md +42 -0
  12. package/components/combine-and-loop-fields/index.js +156 -0
  13. package/components/date/index.js +3 -1
  14. package/components/date/templates/date.html +15 -12
  15. package/components/homeoffice-countries/index.js +22 -0
  16. package/components/index.js +2 -0
  17. package/components/notify/notify.js +2 -2
  18. package/components/summary/index.js +3 -2
  19. package/config/builder-defaults.js +3 -1
  20. package/config/component-defaults.js +13 -0
  21. package/config/hof-defaults.js +8 -0
  22. package/controller/controller.js +57 -1
  23. package/controller/formatting/formatters.js +12 -0
  24. package/controller/validation/index.js +2 -1
  25. package/controller/validation/validators.js +4 -0
  26. package/frontend/govuk-template/build/config.js +2 -2
  27. package/frontend/govuk-template/build/govuk_template.html +102 -0
  28. package/frontend/govuk-template/build/index.js +2 -2
  29. package/frontend/govuk-template/govuk_template_generated.html +102 -0
  30. package/frontend/govuk-template/index.js +4 -4
  31. package/frontend/template-mixins/mixins/template-mixins.js +40 -11
  32. package/frontend/template-mixins/partials/forms/checkbox-group.html +47 -0
  33. package/frontend/template-mixins/partials/forms/checkbox.html +9 -4
  34. package/frontend/template-mixins/partials/forms/input-submit.html +1 -1
  35. package/frontend/template-mixins/partials/forms/input-text-date.html +37 -0
  36. package/frontend/template-mixins/partials/forms/input-text-group.html +15 -10
  37. package/frontend/template-mixins/partials/forms/option-group.html +42 -26
  38. package/frontend/template-mixins/partials/forms/select.html +10 -5
  39. package/frontend/template-mixins/partials/forms/textarea-group.html +37 -23
  40. package/frontend/template-mixins/partials/mixins/panel.html +3 -4
  41. package/frontend/template-partials/views/accessibility.html +4 -4
  42. package/frontend/template-partials/views/cookies.html +1 -1
  43. package/frontend/template-partials/views/layout.html +24 -17
  44. package/frontend/template-partials/views/partials/back.html +1 -1
  45. package/frontend/template-partials/views/partials/bullet-list.html +1 -1
  46. package/frontend/template-partials/views/partials/confirmation-alert.html +4 -3
  47. package/frontend/template-partials/views/partials/continue.html +1 -1
  48. package/frontend/template-partials/views/partials/cookie-banner.html +27 -24
  49. package/frontend/template-partials/views/partials/cookie-settings-radio.html +6 -6
  50. package/frontend/template-partials/views/partials/external-link.html +1 -1
  51. package/frontend/template-partials/views/partials/form.html +2 -1
  52. package/frontend/template-partials/views/partials/gatag.html +0 -1
  53. package/frontend/template-partials/views/partials/head.html +23 -0
  54. package/frontend/template-partials/views/partials/maincontent-left.html +4 -4
  55. package/frontend/template-partials/views/partials/navigation.html +7 -6
  56. package/frontend/template-partials/views/partials/session-cookies-table.html +6 -6
  57. package/frontend/template-partials/views/partials/summary-table-row.html +2 -2
  58. package/frontend/template-partials/views/partials/table.html +7 -7
  59. package/frontend/template-partials/views/partials/validation-list.html +2 -2
  60. package/frontend/template-partials/views/partials/validation-summary.html +14 -13
  61. package/frontend/template-partials/views/partials/warn.html +7 -0
  62. package/frontend/template-partials/views/session-timeout.html +3 -2
  63. package/frontend/themes/gov-uk/client-js/cookieSettings.js +1 -1
  64. package/frontend/themes/gov-uk/client-js/govuk-cookies.js +121 -0
  65. package/frontend/themes/gov-uk/client-js/index.js +6 -1
  66. package/frontend/themes/gov-uk/client-js/skip-to-main.js +19 -0
  67. package/frontend/themes/gov-uk/styles/_cookie-banner.scss +51 -1
  68. package/frontend/themes/gov-uk/styles/govuk.scss +4 -0
  69. package/frontend/themes/gov-uk/styles/modules/_validation.scss +5 -5
  70. package/frontend/toolkit/assets/javascript/character-count.js +4 -4
  71. package/frontend/toolkit/assets/javascript/progressive-reveal.js +3 -1
  72. package/frontend/toolkit/assets/javascript/validation.js +5 -1
  73. package/frontend/toolkit/assets/stylesheets/modules/_validation.scss +3 -3
  74. package/index.js +15 -2
  75. package/lib/ga-tag.js +33 -7
  76. package/lib/settings.js +18 -2
  77. package/middleware/cookies.js +2 -0
  78. package/middleware/errors.js +2 -3
  79. package/middleware/not-found.js +0 -3
  80. package/middleware/rate-limiter.js +1 -0
  81. package/model/apis/axios-settings.js +21 -0
  82. package/model/apis/html-to-pdf-converter.js +10 -8
  83. package/model/index.js +102 -87
  84. package/package.json +18 -17
  85. package/pull_request.md +16 -0
  86. package/sandbox/README.md +3 -3
  87. package/sandbox/apps/sandbox/fields.js +33 -11
  88. package/sandbox/apps/sandbox/index.js +4 -0
  89. package/sandbox/apps/sandbox/sections/summary-data-sections.js +3 -0
  90. package/sandbox/apps/sandbox/translations/en/default.json +220 -0
  91. package/sandbox/apps/sandbox/translations/src/en/fields.json +11 -4
  92. package/sandbox/apps/sandbox/translations/src/en/journey.json +4 -1
  93. package/sandbox/apps/sandbox/translations/src/en/pages.json +7 -25
  94. package/sandbox/apps/sandbox/translations/src/en/validation.json +5 -1
  95. package/sandbox/assets/js/index.js +1 -1
  96. package/sandbox/assets/scss/app.scss +16 -16
  97. package/sandbox/package.json +7 -2
  98. package/sandbox/public/css/app.css +9632 -0
  99. package/sandbox/public/images/icons/icon-caret-left.png +0 -0
  100. package/sandbox/public/images/icons/icon-complete.png +0 -0
  101. package/sandbox/public/images/icons/icon-cross-remove-sign.png +0 -0
  102. package/sandbox/public/js/bundle.js +46721 -0
  103. package/sandbox/server.js +2 -1
  104. package/sandbox/yarn.lock +249 -2
  105. package/wizard/index.js +0 -13
  106. package/wizard/middleware/check-progress.js +36 -1
  107. package/.nyc_output/4d5a4574-78fc-4fcb-9412-3658f6ce33ff.json +0 -1
  108. package/.nyc_output/processinfo/4d5a4574-78fc-4fcb-9412-3658f6ce33ff.json +0 -1
  109. package/frontend/govuk-template/govuk_template.html +0 -109
  110. package/frontend/themes/gov-uk/views/partials/form.html +0 -9
  111. package/frontend/themes/gov-uk/views/partials/forms/option-group.html +0 -28
  112. package/frontend/themes/gov-uk/views/partials/mixins/panel.html +0 -3
  113. package/frontend/themes/gov-uk/views/partials/validation-summary.html +0 -24
  114. package/middleware/monitor.js +0 -20
  115. package/sandbox/apps/sandbox/views/confirmation.html +0 -15
@@ -0,0 +1,102 @@
1
+
2
+ <!DOCTYPE html>
3
+ <!--[if lt IE 9]><html class="lte-ie8" lang="{{ htmlLang }}"><![endif]-->
4
+ <!--[if gt IE 8]><!--><html lang="{{ htmlLang }}" class="govuk-template"><!--<![endif]-->
5
+ <head>
6
+ <meta charset="utf-8" />
7
+ <title>{{ pageTitle }}</title>
8
+ {{{ head }}}
9
+
10
+ <link rel="shortcut icon" sizes="16x16 32x32 48x48" href="{{assetPath}}images/favicon.ico" type="image/x-icon">
11
+ <link rel="mask-icon" href="{{assetPath}}images/govuk-mask-icon.svg" color="#0b0c0c">
12
+ <link rel="apple-touch-icon" sizes="180x180" href="{{assetPath}}images/govuk-apple-touch-icon-180x180.png">
13
+ <link rel="apple-touch-icon" sizes="167x167" href="{{assetPath}}images/govuk-apple-touch-icon-167x167.png">
14
+ <link rel="apple-touch-icon" sizes="152x152" href="{{assetPath}}images/govuk-apple-touch-icon-152x152.png">
15
+ <link rel="apple-touch-icon" href="{{assetPath}}images/govuk-apple-touch-icon.png">
16
+
17
+
18
+ <meta name="theme-color" content="#0b0c0c" />
19
+
20
+ <meta name="viewport" content="width=device-width, initial-scale=1">
21
+
22
+
23
+ <meta property="og:image" content="{{assetPath}}images/opengraph-image.png">
24
+ </head>
25
+
26
+ <body class="{{ bodyClasses }} govuk-template__body js-enabled" >
27
+ <script>document.body.className = ((document.body.className) ? document.body.className + ' js-enabled' : 'js-enabled');</script>
28
+
29
+
30
+
31
+ <div id="global-cookie-message" class="gem-c-cookie-banner govuk-clearfix" data-module="cookie-banner" role="region" aria-label="cookie banner" data-nosnippet="">
32
+ {{{ cookieMessage }}}
33
+ </div>
34
+
35
+ {{{ bodyStart }}}
36
+
37
+ <header role="banner" id="govuk-header" class="{{{ headerClass }}}">
38
+ <div class="govuk-header__container govuk-width-container">
39
+
40
+ <div class="govuk-header__logo">
41
+ <a href="{{{ homepageUrl }}}" title="{{ logoLinkTitle }}" id="logo" class="govuk-header__link govuk-header__link--homepage" target="_blank" data-module="track-click" data-track-category="homeLinkClicked" data-track-action="homeHeader">
42
+ <span class="govuk-header__logotype">
43
+ <!--[if gt IE 8]><!-->
44
+ <svg aria-hidden="true" focusable="false" class="govuk-header__logotype-crown" xmlns="http://www.w3.org/2000/svg\" viewBox="0 0 32 30" height="30" width="32">
45
+ <path fill="currentColor" fill-rule="evenodd" d="M22.6 10.4c-1 .4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s-.1 2-1 2.4m-5.9 6.7c-.9.4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s-.1 2-1 2.4m10.8-3.7c-1 .4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s0 2-1 2.4m3.3 4.8c-1 .4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s-.1 2-1 2.4M17 4.7l2.3 1.2V2.5l-2.3.7-.2-.2.9-3h-3.4l.9 3-.2.2c-.1.1-2.3-.7-2.3-.7v3.4L15 4.7c.1.1.1.2.2.2l-1.3 4c-.1.2-.1.4-.1.6 0 1.1.8 2 1.9 2.2h.7c1-.2 1.9-1.1 1.9-2.1 0-.2 0-.4-.1-.6l-1.3-4c-.1-.2 0-.2.1-.3m-7.6 5.7c.9.4 2-.1 2.4-1 .4-.9-.1-2-1-2.4-.9-.4-2 .1-2.4 1s0 2 1 2.4m-5 3c.9.4 2-.1 2.4-1 .4-.9-.1-2-1-2.4-.9-.4-2 .1-2.4 1s.1 2 1 2.4m-3.2 4.8c.9.4 2-.1 2.4-1 .4-.9-.1-2-1-2.4-.9-.4-2 .1-2.4 1s0 2 1 2.4m14.8 11c4.4 0 8.6.3 12.3.8 1.1-4.5 2.4-7 3.7-8.8l-2.5-.9c.2 1.3.3 1.9 0 2.7-.4-.4-.8-1.1-1.1-2.3l-1.2 4c.7-.5 1.3-.8 2-.9-1.1 2.5-2.6 3.1-3.5 3-1.1-.2-1.7-1.2-1.5-2.1.3-1.2 1.5-1.5 2.1-.1 1.1-2.3-.8-3-2-2.3 1.9-1.9 2.1-3.5.6-5.6-2.1 1.6-2.1 3.2-1.2 5.5-1.2-1.4-3.2-.6-2.5 1.6.9-1.4 2.1-.5 1.9.8-.2 1.1-1.7 2.1-3.5 1.9-2.7-.2-2.9-2.1-2.9-3.6.7-.1 1.9.5 2.9 1.9l.4-4.3c-1.1 1.1-2.1 1.4-3.2 1.4.4-1.2 2.1-3 2.1-3h-5.4s1.7 1.9 2.1 3c-1.1 0-2.1-.2-3.2-1.4l.4 4.3c1-1.4 2.2-2 2.9-1.9-.1 1.5-.2 3.4-2.9 3.6-1.9.2-3.4-.8-3.5-1.9-.2-1.3 1-2.2 1.9-.8.7-2.3-1.2-3-2.5-1.6.9-2.2.9-3.9-1.2-5.5-1.5 2-1.3 3.7.6 5.6-1.2-.7-3.1 0-2 2.3.6-1.4 1.8-1.1 2.1.1.2.9-.3 1.9-1.5 2.1-.9.2-2.4-.5-3.5-3 .6 0 1.2.3 2 .9l-1.2-4c-.3 1.1-.7 1.9-1.1 2.3-.3-.8-.2-1.4 0-2.7l-2.9.9C1.3 23 2.6 25.5 3.7 30c3.7-.5 7.9-.8 12.3-.8\"></path>
46
+ </svg>
47
+ <!--<![endif]-->
48
+ <!--[if IE 8]>
49
+ <img src="{{ assetPath }}images/govuk-logotype-tudor-crown.png" class="govuk-header__logotype-crown-fallback-image" width="32" height="30" alt="">
50
+ <![endif]-->
51
+ </span>
52
+ <span class="govuk-header__logotype-text">
53
+ {{{ globalHeaderText }}}
54
+ </span>
55
+ </a>
56
+ </div>
57
+ {{{ insideHeader }}}
58
+
59
+ {{{ propositionHeader }}}
60
+ </div>
61
+ </header>
62
+
63
+
64
+ {{{ afterHeader }}}
65
+
66
+
67
+ {{{ content }}}
68
+
69
+ <footer class="govuk-footer" id="footer" role="contentinfo">
70
+
71
+ <div class="govuk-width-container">
72
+ {{{ footerTop }}}
73
+
74
+ <div class="govuk-footer__meta">
75
+ <div class="govuk-footer__meta-item govuk-footer__meta-item--grow">
76
+ <h2 class="govuk-visually-hidden">Support links</h2>
77
+ {{{ footerSupportLinks }}}
78
+
79
+ <svg aria-hidden="true" focusable="false" class="govuk-footer__licence-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 483.2 195.7" height="17" width="41">
80
+ <path fill="currentColor" d="M421.5 142.8V.1l-50.7 32.3v161.1h112.4v-50.7zm-122.3-9.6A47.12 47.12 0 0 1 221 97.8c0-26 21.1-47.1 47.1-47.1 16.7 0 31.4 8.7 39.7 21.8l42.7-27.2A97.63 97.63 0 0 0 268.1 0c-36.5 0-68.3 20.1-85.1 49.7A98 98 0 0 0 97.8 0C43.9 0 0 43.9 0 97.8s43.9 97.8 97.8 97.8c36.5 0 68.3-20.1 85.1-49.7a97.76 97.76 0 0 0 149.6 25.4l19.4 22.2h3v-87.8h-80l24.3 27.5zM97.8 145c-26 0-47.1-21.1-47.1-47.1s21.1-47.1 47.1-47.1 47.2 21 47.2 47S123.8 145 97.8 145"></path>
81
+ </svg>
82
+
83
+ <span class="govuk-footer__licence-description">{{{ licenceMessage }}}</span>
84
+ </div>
85
+
86
+ <div class="govuk-footer__meta-item">
87
+ <a class="govuk-footer__link govuk-footer__copyright-logo" id="copyright-logo" target="_blank" href="https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/">{{{ crownCopyrightMessage }}}</a>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </footer>
92
+
93
+ <div id="global-app-error" class="app-error hidden"></div>
94
+
95
+
96
+ {{{ bodyEnd }}}
97
+
98
+
99
+ <script {{#nonce}}nonce="{{nonce}}"{{/nonce}}>if (typeof window.GOVUK === 'undefined') document.body.className = document.body.className.replace('js-enabled', '');</script>
100
+
101
+ </body>
102
+ </html>
@@ -12,12 +12,12 @@ function addNonceValueAttributeToInlineScripts(compiledTemplateString) {
12
12
  }
13
13
 
14
14
  module.exports = () => {
15
- const template = require.resolve('govuk_template_mustache/views/layouts/govuk_template.html');
15
+ const template = require.resolve('./govuk_template.html');
16
16
 
17
17
  const govukTemplate = fs.readFileSync(template, { encoding: 'utf-8' });
18
18
  const compiledTemplate = Hogan.compile(govukTemplate).render(govukConfig);
19
19
  const parsedTemplate = addNonceValueAttributeToInlineScripts(compiledTemplate);
20
- const output = path.resolve(__dirname, '../govuk_template.html');
20
+ const output = path.resolve(__dirname, '../govuk_template_generated.html');
21
21
 
22
22
  fs.writeFileSync(output, parsedTemplate, { encoding: 'utf-8' });
23
23
  };
@@ -0,0 +1,102 @@
1
+
2
+ <!DOCTYPE html>
3
+ <!--[if lt IE 9]><html class="lte-ie8" lang="{{htmlLang}}"><![endif]-->
4
+ <!--[if gt IE 8]><!--><html lang="{{htmlLang}}" class="govuk-template"><!--<![endif]-->
5
+ <head>
6
+ <meta charset="utf-8" />
7
+ <title>{{$pageTitle}}{{/pageTitle}}</title>
8
+ {{$head}}{{/head}}
9
+
10
+ <link rel="shortcut icon" sizes="16x16 32x32 48x48" href="{{govukAssetPath}}images/favicon.ico" type="image/x-icon">
11
+ <link rel="mask-icon" href="{{govukAssetPath}}images/govuk-mask-icon.svg" color="#0b0c0c">
12
+ <link rel="apple-touch-icon" sizes="180x180" href="{{govukAssetPath}}images/govuk-apple-touch-icon-180x180.png">
13
+ <link rel="apple-touch-icon" sizes="167x167" href="{{govukAssetPath}}images/govuk-apple-touch-icon-167x167.png">
14
+ <link rel="apple-touch-icon" sizes="152x152" href="{{govukAssetPath}}images/govuk-apple-touch-icon-152x152.png">
15
+ <link rel="apple-touch-icon" href="{{govukAssetPath}}images/govuk-apple-touch-icon.png">
16
+
17
+
18
+ <meta name="theme-color" content="#0b0c0c" />
19
+
20
+ <meta name="viewport" content="width=device-width, initial-scale=1">
21
+
22
+
23
+ <meta property="og:image" content="{{govukAssetPath}}images/opengraph-image.png">
24
+ </head>
25
+
26
+ <body class="{{$bodyClasses}}{{/bodyClasses}} govuk-template__body js-enabled" >
27
+ <script {{#nonce}}nonce="{{nonce}}"{{/nonce}}>document.body.className = ((document.body.className) ? document.body.className + ' js-enabled' : 'js-enabled');</script>
28
+
29
+
30
+
31
+ <div id="global-cookie-message" class="gem-c-cookie-banner govuk-clearfix" data-module="cookie-banner" role="region" aria-label="cookie banner" data-nosnippet="">
32
+ {{$cookieMessage}}{{/cookieMessage}}
33
+ </div>
34
+
35
+ {{$bodyStart}}{{/bodyStart}}
36
+
37
+ <header role="banner" id="govuk-header" class="{{$headerClass}}{{/headerClass}}">
38
+ <div class="govuk-header__container govuk-width-container">
39
+
40
+ <div class="govuk-header__logo">
41
+ <a href="{{$homepageUrl}}https://www.gov.uk{{/homepageUrl}}" title="{{$logoLinkTitle}}Go to the GOV.UK homepage{{/logoLinkTitle}}" id="logo" class="govuk-header__link govuk-header__link--homepage" target="_blank" data-module="track-click" data-track-category="homeLinkClicked" data-track-action="homeHeader">
42
+ <span class="govuk-header__logotype">
43
+ <!--[if gt IE 8]><!-->
44
+ <svg aria-hidden="true" focusable="false" class="govuk-header__logotype-crown" xmlns="http://www.w3.org/2000/svg\" viewBox="0 0 32 30" height="30" width="32">
45
+ <path fill="currentColor" fill-rule="evenodd" d="M22.6 10.4c-1 .4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s-.1 2-1 2.4m-5.9 6.7c-.9.4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s-.1 2-1 2.4m10.8-3.7c-1 .4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s0 2-1 2.4m3.3 4.8c-1 .4-2-.1-2.4-1-.4-.9.1-2 1-2.4.9-.4 2 .1 2.4 1s-.1 2-1 2.4M17 4.7l2.3 1.2V2.5l-2.3.7-.2-.2.9-3h-3.4l.9 3-.2.2c-.1.1-2.3-.7-2.3-.7v3.4L15 4.7c.1.1.1.2.2.2l-1.3 4c-.1.2-.1.4-.1.6 0 1.1.8 2 1.9 2.2h.7c1-.2 1.9-1.1 1.9-2.1 0-.2 0-.4-.1-.6l-1.3-4c-.1-.2 0-.2.1-.3m-7.6 5.7c.9.4 2-.1 2.4-1 .4-.9-.1-2-1-2.4-.9-.4-2 .1-2.4 1s0 2 1 2.4m-5 3c.9.4 2-.1 2.4-1 .4-.9-.1-2-1-2.4-.9-.4-2 .1-2.4 1s.1 2 1 2.4m-3.2 4.8c.9.4 2-.1 2.4-1 .4-.9-.1-2-1-2.4-.9-.4-2 .1-2.4 1s0 2 1 2.4m14.8 11c4.4 0 8.6.3 12.3.8 1.1-4.5 2.4-7 3.7-8.8l-2.5-.9c.2 1.3.3 1.9 0 2.7-.4-.4-.8-1.1-1.1-2.3l-1.2 4c.7-.5 1.3-.8 2-.9-1.1 2.5-2.6 3.1-3.5 3-1.1-.2-1.7-1.2-1.5-2.1.3-1.2 1.5-1.5 2.1-.1 1.1-2.3-.8-3-2-2.3 1.9-1.9 2.1-3.5.6-5.6-2.1 1.6-2.1 3.2-1.2 5.5-1.2-1.4-3.2-.6-2.5 1.6.9-1.4 2.1-.5 1.9.8-.2 1.1-1.7 2.1-3.5 1.9-2.7-.2-2.9-2.1-2.9-3.6.7-.1 1.9.5 2.9 1.9l.4-4.3c-1.1 1.1-2.1 1.4-3.2 1.4.4-1.2 2.1-3 2.1-3h-5.4s1.7 1.9 2.1 3c-1.1 0-2.1-.2-3.2-1.4l.4 4.3c1-1.4 2.2-2 2.9-1.9-.1 1.5-.2 3.4-2.9 3.6-1.9.2-3.4-.8-3.5-1.9-.2-1.3 1-2.2 1.9-.8.7-2.3-1.2-3-2.5-1.6.9-2.2.9-3.9-1.2-5.5-1.5 2-1.3 3.7.6 5.6-1.2-.7-3.1 0-2 2.3.6-1.4 1.8-1.1 2.1.1.2.9-.3 1.9-1.5 2.1-.9.2-2.4-.5-3.5-3 .6 0 1.2.3 2 .9l-1.2-4c-.3 1.1-.7 1.9-1.1 2.3-.3-.8-.2-1.4 0-2.7l-2.9.9C1.3 23 2.6 25.5 3.7 30c3.7-.5 7.9-.8 12.3-.8\"></path>
46
+ </svg>
47
+ <!--<![endif]-->
48
+ <!--[if IE 8]>
49
+ <img src="{{govukAssetPath}}images/govuk-logotype-tudor-crown.png" class="govuk-header__logotype-crown-fallback-image" width="32" height="30" alt="">
50
+ <![endif]-->
51
+ </span>
52
+ <span class="govuk-header__logotype-text">
53
+ {{$globalHeaderText}}GOV.UK{{/globalHeaderText}}
54
+ </span>
55
+ </a>
56
+ </div>
57
+ {{$insideHeader}}{{/insideHeader}}
58
+
59
+ {{$propositionHeader}}{{/propositionHeader}}
60
+ </div>
61
+ </header>
62
+
63
+
64
+ {{$afterHeader}}{{/afterHeader}}
65
+
66
+
67
+ {{$main}}{{/main}}
68
+
69
+ <footer class="govuk-footer" id="footer" role="contentinfo">
70
+
71
+ <div class="govuk-width-container">
72
+ {{$footerTop}}{{/footerTop}}
73
+
74
+ <div class="govuk-footer__meta">
75
+ <div class="govuk-footer__meta-item govuk-footer__meta-item--grow">
76
+ <h2 class="govuk-visually-hidden">Support links</h2>
77
+ {{$footerSupportLinks}}{{/footerSupportLinks}}
78
+
79
+ <svg aria-hidden="true" focusable="false" class="govuk-footer__licence-logo" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 483.2 195.7" height="17" width="41">
80
+ <path fill="currentColor" d="M421.5 142.8V.1l-50.7 32.3v161.1h112.4v-50.7zm-122.3-9.6A47.12 47.12 0 0 1 221 97.8c0-26 21.1-47.1 47.1-47.1 16.7 0 31.4 8.7 39.7 21.8l42.7-27.2A97.63 97.63 0 0 0 268.1 0c-36.5 0-68.3 20.1-85.1 49.7A98 98 0 0 0 97.8 0C43.9 0 0 43.9 0 97.8s43.9 97.8 97.8 97.8c36.5 0 68.3-20.1 85.1-49.7a97.76 97.76 0 0 0 149.6 25.4l19.4 22.2h3v-87.8h-80l24.3 27.5zM97.8 145c-26 0-47.1-21.1-47.1-47.1s21.1-47.1 47.1-47.1 47.2 21 47.2 47S123.8 145 97.8 145"></path>
81
+ </svg>
82
+
83
+ <span class="govuk-footer__licence-description">{{$licenceMessage}}All content is available under the <a href="https://www.nationalarchives.gov.uk/doc/open-government-licence/version/3/" id="open-government-licence" class="govuk-footer__link" target="_blank" rel="license">Open Government Licence v3.0</a>, except where otherwise stated{{/licenceMessage}}</span>
84
+ </div>
85
+
86
+ <div class="govuk-footer__meta-item">
87
+ <a class="govuk-footer__link govuk-footer__copyright-logo" id="copyright-logo" target="_blank" href="https://www.nationalarchives.gov.uk/information-management/re-using-public-sector-information/uk-government-licensing-framework/crown-copyright/">{{$crownCopyrightMessage}}© Crown copyright{{/crownCopyrightMessage}}</a>
88
+ </div>
89
+ </div>
90
+ </div>
91
+ </footer>
92
+
93
+ <div id="global-app-error" class="app-error hidden"></div>
94
+
95
+
96
+ {{$bodyEnd}}{{/bodyEnd}}
97
+
98
+
99
+ <script {{#nonce}}nonce="{{nonce}}"{{/nonce}}>if (typeof window.GOVUK === 'undefined') document.body.className = document.body.className.replace('js-enabled', '');</script>
100
+
101
+ </body>
102
+ </html>
@@ -5,18 +5,18 @@ const servestatic = require('serve-static');
5
5
  const Router = require('express').Router;
6
6
  const buildTemplateLayout = require('./build');
7
7
 
8
- const basedir = path.dirname(require.resolve('govuk_template_mustache/package.json'));
8
+ const basedir = path.dirname(require.resolve('govuk-frontend/package.json'));
9
9
 
10
10
  const setup = (opts, router) => {
11
11
  buildTemplateLayout();
12
12
  const options = opts || {};
13
- options.path = options.path || '/govuk-assets';
13
+ options.path = options.path || '/assets';
14
14
 
15
- router.use(options.path, servestatic(path.join(basedir, './assets'), options));
15
+ router.use(options.path, servestatic(path.join(basedir, './govuk/assets'), options));
16
16
  router.use((req, res, next) => {
17
17
  res.locals.govukAssetPath = req.baseUrl + options.path + '/';
18
18
  res.locals.partials = res.locals.partials || {};
19
- res.locals.partials['govuk-template'] = path.resolve(__dirname, './govuk_template');
19
+ res.locals.partials['govuk-template'] = path.resolve(__dirname, './govuk_template_generated');
20
20
  next();
21
21
  });
22
22
 
@@ -12,11 +12,13 @@ const renderer = require('./render');
12
12
  const PANELMIXIN = 'partials/mixins/panel';
13
13
  const PARTIALS = [
14
14
  'partials/forms/input-text-group',
15
+ 'partials/forms/input-text-date',
15
16
  'partials/forms/input-submit',
16
17
  'partials/forms/select',
17
18
  'partials/forms/checkbox',
18
19
  'partials/forms/textarea-group',
19
- 'partials/forms/option-group'
20
+ 'partials/forms/option-group',
21
+ 'partials/forms/checkbox-group'
20
22
  ];
21
23
 
22
24
  // This returns a middleware that places mixins against the `res.locals` object.
@@ -40,6 +42,15 @@ module.exports = function (options) {
40
42
  return null;
41
43
  }
42
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
+
43
54
  function type(field) {
44
55
  return field.type || 'text';
45
56
  }
@@ -191,6 +202,7 @@ module.exports = function (options) {
191
202
  const lKey = getTranslationKey(field, key, 'label');
192
203
  const hint = conditionalTranslate(hKey);
193
204
  const required = isRequired(field);
205
+ const labelClassName = classNames(field, 'labelClassName');
194
206
  const autocomplete = field.autocomplete || extension.autocomplete;
195
207
 
196
208
  return Object.assign({}, extension, {
@@ -199,18 +211,22 @@ module.exports = function (options) {
199
211
  type: extension.type || type(field),
200
212
  value: this.values && this.values[key],
201
213
  label: t(lKey),
202
- labelClassName: classNames(field, 'labelClassName') || 'form-label',
203
- formGroupClassName: classNames(field, 'formGroupClassName') || extension.formGroupClassName || 'form-group',
214
+ labelClassName: labelClassName ? `govuk-label ${labelClassName}` : 'govuk-label',
215
+ formGroupClassName: classNames(field, 'formGroupClassName') || extension.formGroupClassName || 'govuk-form-group',
204
216
  hint: hint,
205
217
  hintId: extension.hintId || (hint ? key + '-hint' : null),
206
218
  error: this.errors && this.errors[key],
207
219
  maxlength: maxlength(field) || extension.maxlength,
220
+ maxword: maxword(field) || extension.maxword,
208
221
  required: required,
209
222
  pattern: extension.pattern,
210
223
  date: extension.date,
211
224
  autocomplete: autocomplete,
212
225
  child: field.child,
226
+ isPageHeading: field.isPageHeading,
213
227
  attributes: field.attributes,
228
+ isPrefixOrSuffix: _.map(field.attributes, item => {if (item.prefix || item.suffix !== undefined) return true;}),
229
+ isMaxlengthOrMaxword: maxlength(field) || extension.maxlength || maxword(field) || extension.maxword,
214
230
  renderChild: renderChild.bind(this)
215
231
  });
216
232
  }
@@ -219,7 +235,8 @@ module.exports = function (options) {
219
235
  opts = opts || {};
220
236
  const field = Object.assign({}, this.options.fields[key] || options.fields[key]);
221
237
  const legend = field.legend;
222
-
238
+ const detail = field.detail;
239
+ const warningValue = 'fields.' + key + '.warning';
223
240
  let legendClassName;
224
241
  let legendValue = 'fields.' + key + '.legend';
225
242
  if (legend) {
@@ -236,7 +253,10 @@ module.exports = function (options) {
236
253
  legend: t(legendValue),
237
254
  legendClassName: legendClassName,
238
255
  role: opts.type === 'radio' ? 'radiogroup' : 'group',
239
- ariaRequired: opts.type === 'radio',
256
+ isPageHeading: field.isPageHeading,
257
+ isWarning: field.isWarning,
258
+ warning: t(warningValue),
259
+ detail: detail ? detail : '',
240
260
  hint: conditionalTranslate(getTranslationKey(field, key, 'hint')),
241
261
  options: _.map(field.options, function (obj) {
242
262
  let selected = false;
@@ -245,6 +265,7 @@ module.exports = function (options) {
245
265
  let toggle;
246
266
  let child;
247
267
  let optionHint;
268
+ let useHintText;
248
269
 
249
270
  if (typeof obj === 'string') {
250
271
  value = obj;
@@ -255,6 +276,7 @@ module.exports = function (options) {
255
276
  label = obj.label || 'fields.' + key + '.options.' + obj.value + '.label';
256
277
  toggle = obj.toggle;
257
278
  child = obj.child;
279
+ useHintText = obj.useHintText;
258
280
  optionHint = obj.hint || 'fields.' + key + '.options.' + obj.value + '.hint';
259
281
  }
260
282
 
@@ -270,9 +292,10 @@ module.exports = function (options) {
270
292
  value: value,
271
293
  type: opts.type,
272
294
  selected: selected,
295
+ radioOption: opts.type === 'radio',
273
296
  toggle: toggle,
274
297
  child: child,
275
- optionHint: conditionalTranslate(optionHint) || ''
298
+ optionHint: useHintText ? optionHint : conditionalTranslate(optionHint) || ''
276
299
  };
277
300
  }, this),
278
301
  className: classNames(field),
@@ -296,8 +319,9 @@ module.exports = function (options) {
296
319
  error: this.errors && this.errors[key],
297
320
  invalid: this.errors && this.errors[key] && opts.required,
298
321
  label: t(fieldLabel || 'fields.' + key + '.label'),
322
+ hint: conditionalTranslate(getTranslationKey(field, key, 'hint')),
299
323
  selected: selected,
300
- className: classNames(field) || 'block-label',
324
+ className: classNames(field) || 'govuk-label govuk-checkboxes__label',
301
325
  child: field.child,
302
326
  renderChild: renderChild.bind(this)
303
327
  });
@@ -355,7 +379,7 @@ module.exports = function (options) {
355
379
  }
356
380
  },
357
381
  'checkbox-group': {
358
- path: 'partials/forms/option-group',
382
+ path: 'partials/forms/checkbox-group',
359
383
  renderWith: optionGroup,
360
384
  options: {
361
385
  type: 'checkbox'
@@ -425,16 +449,21 @@ module.exports = function (options) {
425
449
  year: autocomplete + '-year'
426
450
  };
427
451
  }
452
+ const isThisRequired = field.validate ? field.validate.indexOf('required') > -1 : false;
453
+ const formGroupClassName = (field.formGroup && field.formGroup.className) ? field.formGroup.className : '';
454
+ const classNameDay = (field.controlsClass && field.controlsClass.day) ? field.controlsClass.day : 'govuk-date-input__input govuk-input--width-2';
455
+ const classNameMonth = (field.controlsClass && field.controlsClass.month) ? field.controlsClass.month : 'govuk-date-input__input govuk-input--width-2';
456
+ const classNameYear = (field.controlsClass && field.controlsClass.year) ? field.controlsClass.year : 'govuk-date-input__input govuk-input--width-4';
428
457
 
429
458
  const parts = [];
430
459
 
431
460
  if (isExact) {
432
- const dayPart = compiled['partials/forms/input-text-group'].render(inputText.call(this, key + '-day', { pattern: '[0-9]*', min: 1, max: 31, maxlength: 2, hintId: key + '-hint', date: true, autocomplete: autocomplete.day }));
461
+ 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 }));
433
462
  parts.push(dayPart);
434
463
  }
435
464
 
436
- const monthPart = compiled['partials/forms/input-text-group'].render(inputText.call(this, key + '-month', { pattern: '[0-9]*', min: 1, max: 12, maxlength: 2, hintId: key + '-hint', date: true, autocomplete: autocomplete.month }));
437
- const yearPart = compiled['partials/forms/input-text-group'].render(inputText.call(this, key + '-year', { pattern: '[0-9]*', maxlength: 4, hintId: key + '-hint', date: true, formGroupClassName: 'form-group-year', autocomplete: autocomplete.year }));
465
+ 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 }));
466
+ 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 }));
438
467
 
439
468
  return parts.concat(monthPart, yearPart).join('\n');
440
469
  };
@@ -0,0 +1,47 @@
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,11 +1,16 @@
1
- <div id="{{key}}-group" class="form-group{{#compound}} form-group-compound{{/compound}}{{#formGroupClassName}} {{formGroupClassName}}{{/formGroupClassName}}{{#error}} validation-error{{/error}}">
2
- {{#error}}<p class="error-message" aria-hidden="true">{{error.message}}</p>{{/error}}
3
- <div class="multiple-choice">
4
- <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}}>
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
5
  <label for="{{key}}" class="{{#className}}{{className}} {{/className}}{{#invalid}}invalid-input{{/invalid}}">
6
6
  {{{label}}}
7
7
  {{#error}}<span class="visuallyhidden">{{error.message}}</span>{{/error}}
8
8
  </label>
9
+ {{#hint}}
10
+ <div id="{{key}}-hint" class="govuk-hint govuk-checkboxes__hint">
11
+ {{hint}}
12
+ </div>
13
+ {{/hint}}
9
14
  </div>
10
15
  {{#renderChild}}{{/renderChild}}
11
16
  </div>
@@ -1 +1 @@
1
- <input type="submit" {{#id}}id="{{id}}"{{/id}} value="{{{value}}}" class="button">
1
+ <input type="submit" {{#id}}id="{{id}}"{{/id}} value="{{{value}}}" class="govuk-button">
@@ -0,0 +1,37 @@
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,11 +1,16 @@
1
- <div id="{{id}}-group" class="form-group{{#compound}} form-group-compound{{/compound}}{{#formGroupClassName}} {{formGroupClassName}}{{/formGroupClassName}}{{^date}}{{#error}} validation-error{{/error}}{{/date}}">
2
- <label for="{{id}}" class="{{labelClassName}}">
3
- <span class="label-text">{{{label}}}</span>
4
- {{#hint}}<span {{$hintId}}id="{{hintId}}" {{/hintId}}class="form-hint">{{hint}}</span>{{/hint}}
5
- {{^date}}{{#error}}<span class="error-message">{{error.message}}</span>{{/error}}{{/date}}
6
- </label>
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}}
7
12
  {{#renderChild}}{{/renderChild}}
8
- <div class="govuk-input__wrapper">
13
+ {{#isPrefixOrSuffix}}<div class="govuk-input__wrapper">{{/isPrefixOrSuffix}}
9
14
  {{#attributes}}
10
15
  {{#prefix}}
11
16
  <div class="govuk-input__prefix" aria-hidden="true">{{prefix}}</div>
@@ -15,7 +20,7 @@
15
20
  type="{{type}}"
16
21
  name="{{id}}"
17
22
  id="{{id}}"
18
- class="form-control{{#className}} {{className}}{{/className}}{{#error}} invalid-input{{/error}}"
23
+ class="{{^className}}govuk-input{{/className}}{{#className}}{{className}}{{/className}}{{#error}} govuk-input--error{{/error}}"
19
24
  aria-required="{{required}}"
20
25
  {{#value}} value="{{value}}"{{/value}}
21
26
  {{#min}} min="{{min}}"{{/min}}
@@ -31,8 +36,8 @@
31
36
  >
32
37
  {{#attributes}}
33
38
  {{#suffix}}
34
- <div class="govuk-input__prefix" aria-hidden="true">{{suffix}}</div>
39
+ <div class="govuk-input__suffix" aria-hidden="true">{{suffix}}</div>
35
40
  {{/suffix}}
36
41
  {{/attributes}}
37
- </div>
42
+ {{#isPrefixOrSuffix}}</div>{{/isPrefixOrSuffix}}
38
43
  </div>