govuk_publishing_components 32.0.0 → 33.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (206) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/component_guide/accessibility-test.js +0 -1
  3. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-core.js +175 -0
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-ecommerce-tracker.js +1 -1
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-event-tracker.js +5 -13
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-link-tracker.js +80 -309
  7. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-page-views.js +2 -2
  8. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/ga4-specialist-link-tracker.js +140 -0
  9. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/init-ga4.js +3 -0
  10. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +1 -0
  11. data/app/assets/javascripts/govuk_publishing_components/components/accordion.js +12 -1
  12. data/app/assets/javascripts/govuk_publishing_components/components/layout-super-navigation-header.js +13 -4
  13. data/app/assets/javascripts/govuk_publishing_components/components/single-page-notification-button.js +24 -8
  14. data/app/assets/javascripts/govuk_publishing_components/vendor/lux/lux-reporter.js +83 -86
  15. data/app/assets/stylesheets/govuk_publishing_components/components/_big-number.scss +2 -5
  16. data/app/assets/stylesheets/govuk_publishing_components/components/_image-card.scss +1 -5
  17. data/app/assets/stylesheets/govuk_publishing_components/components/_input.scss +3 -5
  18. data/app/assets/stylesheets/govuk_publishing_components/components/_layout-super-navigation-header.scss +10 -30
  19. data/app/assets/stylesheets/govuk_publishing_components/components/_search.scss +0 -7
  20. data/app/assets/stylesheets/govuk_publishing_components/components/_share-links.scss +0 -6
  21. data/app/views/govuk_publishing_components/components/_accordion.html.erb +14 -1
  22. data/app/views/govuk_publishing_components/components/_error_summary.html.erb +27 -26
  23. data/app/views/govuk_publishing_components/components/_layout_super_navigation_header.html.erb +2 -2
  24. data/app/views/govuk_publishing_components/components/_phase_banner.html.erb +1 -1
  25. data/app/views/govuk_publishing_components/components/_share_links.html.erb +18 -15
  26. data/app/views/govuk_publishing_components/components/_single_page_notification_button.html.erb +1 -1
  27. data/app/views/govuk_publishing_components/components/docs/accordion.yml +15 -3
  28. data/app/views/govuk_publishing_components/components/docs/button.yml +10 -0
  29. data/app/views/govuk_publishing_components/components/docs/share_links.yml +59 -30
  30. data/app/views/govuk_publishing_components/components/docs/single_page_notification_button.yml +10 -1
  31. data/app/views/govuk_publishing_components/components/feedback/_yes_no_banner.html.erb +3 -3
  32. data/config/locales/ar.yml +4 -1
  33. data/config/locales/az.yml +4 -1
  34. data/config/locales/be.yml +4 -1
  35. data/config/locales/bg.yml +4 -1
  36. data/config/locales/bn.yml +4 -1
  37. data/config/locales/cs.yml +4 -1
  38. data/config/locales/cy.yml +4 -1
  39. data/config/locales/da.yml +4 -1
  40. data/config/locales/de.yml +4 -1
  41. data/config/locales/dr.yml +4 -1
  42. data/config/locales/el.yml +4 -1
  43. data/config/locales/en.yml +20 -17
  44. data/config/locales/es-419.yml +4 -1
  45. data/config/locales/es.yml +4 -1
  46. data/config/locales/et.yml +4 -1
  47. data/config/locales/fa.yml +4 -1
  48. data/config/locales/fi.yml +4 -1
  49. data/config/locales/fr.yml +4 -1
  50. data/config/locales/gd.yml +4 -1
  51. data/config/locales/gu.yml +4 -1
  52. data/config/locales/he.yml +4 -1
  53. data/config/locales/hi.yml +4 -1
  54. data/config/locales/hr.yml +4 -1
  55. data/config/locales/hu.yml +4 -1
  56. data/config/locales/hy.yml +4 -1
  57. data/config/locales/id.yml +4 -1
  58. data/config/locales/is.yml +4 -1
  59. data/config/locales/it.yml +4 -1
  60. data/config/locales/ja.yml +4 -1
  61. data/config/locales/ka.yml +4 -1
  62. data/config/locales/kk.yml +4 -1
  63. data/config/locales/ko.yml +4 -1
  64. data/config/locales/lt.yml +4 -1
  65. data/config/locales/lv.yml +4 -1
  66. data/config/locales/ms.yml +4 -1
  67. data/config/locales/mt.yml +4 -1
  68. data/config/locales/nl.yml +4 -1
  69. data/config/locales/no.yml +4 -1
  70. data/config/locales/pa-pk.yml +4 -1
  71. data/config/locales/pa.yml +4 -1
  72. data/config/locales/pl.yml +4 -1
  73. data/config/locales/ps.yml +4 -1
  74. data/config/locales/pt.yml +4 -1
  75. data/config/locales/ro.yml +4 -1
  76. data/config/locales/ru.yml +4 -1
  77. data/config/locales/si.yml +4 -1
  78. data/config/locales/sk.yml +4 -1
  79. data/config/locales/sl.yml +4 -1
  80. data/config/locales/so.yml +4 -1
  81. data/config/locales/sq.yml +4 -1
  82. data/config/locales/sr.yml +4 -1
  83. data/config/locales/sv.yml +4 -1
  84. data/config/locales/sw.yml +4 -1
  85. data/config/locales/ta.yml +4 -1
  86. data/config/locales/th.yml +4 -1
  87. data/config/locales/tk.yml +4 -1
  88. data/config/locales/tr.yml +4 -1
  89. data/config/locales/uk.yml +4 -1
  90. data/config/locales/ur.yml +4 -1
  91. data/config/locales/uz.yml +4 -1
  92. data/config/locales/vi.yml +4 -1
  93. data/config/locales/zh-hk.yml +4 -1
  94. data/config/locales/zh-tw.yml +4 -1
  95. data/config/locales/zh.yml +4 -1
  96. data/lib/govuk_publishing_components/presenters/button_helper.rb +7 -1
  97. data/lib/govuk_publishing_components/presenters/single_page_notification_button_helper.rb +25 -1
  98. data/lib/govuk_publishing_components/version.rb +1 -1
  99. data/node_modules/axe-core/axe.js +4567 -4678
  100. data/node_modules/axe-core/axe.min.js +2 -2
  101. data/node_modules/axe-core/package.json +2 -2
  102. data/node_modules/axe-core/sri-history.json +8 -0
  103. data/node_modules/govuk-frontend/README.md +1 -2
  104. data/node_modules/govuk-frontend/govuk/all.js +1398 -273
  105. data/node_modules/govuk-frontend/govuk/common/closest-attribute-value.js +70 -0
  106. data/node_modules/govuk-frontend/govuk/common/index.js +172 -0
  107. data/node_modules/govuk-frontend/govuk/common/normalise-dataset.js +373 -0
  108. data/node_modules/govuk-frontend/govuk/common.js +138 -3
  109. data/node_modules/govuk-frontend/govuk/components/accordion/accordion.js +753 -25
  110. data/node_modules/govuk-frontend/govuk/components/accordion/fixtures.json +54 -22
  111. data/node_modules/govuk-frontend/govuk/components/accordion/macro-options.json +36 -0
  112. data/node_modules/govuk-frontend/govuk/components/accordion/template.njk +7 -1
  113. data/node_modules/govuk-frontend/govuk/components/back-link/fixtures.json +12 -12
  114. data/node_modules/govuk-frontend/govuk/components/breadcrumbs/fixtures.json +22 -22
  115. data/node_modules/govuk-frontend/govuk/components/button/_index.scss +23 -5
  116. data/node_modules/govuk-frontend/govuk/components/button/button.js +365 -107
  117. data/node_modules/govuk-frontend/govuk/components/button/fixtures.json +85 -66
  118. data/node_modules/govuk-frontend/govuk/components/button/template.njk +1 -1
  119. data/node_modules/govuk-frontend/govuk/components/character-count/_index.scss +9 -0
  120. data/node_modules/govuk-frontend/govuk/components/character-count/character-count.js +1033 -121
  121. data/node_modules/govuk-frontend/govuk/components/character-count/fixtures.json +112 -36
  122. data/node_modules/govuk-frontend/govuk/components/character-count/macro-options.json +42 -0
  123. data/node_modules/govuk-frontend/govuk/components/character-count/template.njk +27 -3
  124. data/node_modules/govuk-frontend/govuk/components/checkboxes/checkboxes.js +30 -2
  125. data/node_modules/govuk-frontend/govuk/components/checkboxes/fixtures.json +96 -93
  126. data/node_modules/govuk-frontend/govuk/components/cookie-banner/fixtures.json +46 -46
  127. data/node_modules/govuk-frontend/govuk/components/date-input/fixtures.json +50 -50
  128. data/node_modules/govuk-frontend/govuk/components/details/details.js +43 -13
  129. data/node_modules/govuk-frontend/govuk/components/details/fixtures.json +20 -20
  130. data/node_modules/govuk-frontend/govuk/components/error-message/fixtures.json +20 -20
  131. data/node_modules/govuk-frontend/govuk/components/error-summary/error-summary.js +268 -6
  132. data/node_modules/govuk-frontend/govuk/components/error-summary/fixtures.json +44 -35
  133. data/node_modules/govuk-frontend/govuk/components/error-summary/template.njk +25 -21
  134. data/node_modules/govuk-frontend/govuk/components/fieldset/fixtures.json +51 -39
  135. data/node_modules/govuk-frontend/govuk/components/file-upload/fixtures.json +26 -26
  136. data/node_modules/govuk-frontend/govuk/components/footer/_index.scss +1 -1
  137. data/node_modules/govuk-frontend/govuk/components/footer/fixtures.json +46 -46
  138. data/node_modules/govuk-frontend/govuk/components/footer/macro-options.json +2 -2
  139. data/node_modules/govuk-frontend/govuk/components/header/fixtures.json +93 -38
  140. data/node_modules/govuk-frontend/govuk/components/header/header.js +6 -0
  141. data/node_modules/govuk-frontend/govuk/components/header/macro-options.json +8 -2
  142. data/node_modules/govuk-frontend/govuk/components/header/template.njk +4 -2
  143. data/node_modules/govuk-frontend/govuk/components/hint/fixtures.json +12 -12
  144. data/node_modules/govuk-frontend/govuk/components/input/fixtures.json +80 -80
  145. data/node_modules/govuk-frontend/govuk/components/inset-text/fixtures.json +12 -12
  146. data/node_modules/govuk-frontend/govuk/components/label/fixtures.json +34 -34
  147. data/node_modules/govuk-frontend/govuk/components/notification-banner/fixtures.json +56 -46
  148. data/node_modules/govuk-frontend/govuk/components/notification-banner/notification-banner.js +252 -2
  149. data/node_modules/govuk-frontend/govuk/components/notification-banner/template.njk +1 -1
  150. data/node_modules/govuk-frontend/govuk/components/pagination/_index.scss +10 -7
  151. data/node_modules/govuk-frontend/govuk/components/pagination/fixtures.json +33 -26
  152. data/node_modules/govuk-frontend/govuk/components/panel/fixtures.json +18 -18
  153. data/node_modules/govuk-frontend/govuk/components/phase-banner/fixtures.json +14 -14
  154. data/node_modules/govuk-frontend/govuk/components/radios/fixtures.json +94 -91
  155. data/node_modules/govuk-frontend/govuk/components/radios/radios.js +30 -2
  156. data/node_modules/govuk-frontend/govuk/components/select/fixtures.json +32 -32
  157. data/node_modules/govuk-frontend/govuk/components/skip-link/fixtures.json +22 -20
  158. data/node_modules/govuk-frontend/govuk/components/skip-link/skip-link.js +10 -4
  159. data/node_modules/govuk-frontend/govuk/components/summary-list/fixtures.json +50 -50
  160. data/node_modules/govuk-frontend/govuk/components/table/_index.scss +1 -1
  161. data/node_modules/govuk-frontend/govuk/components/table/fixtures.json +40 -40
  162. data/node_modules/govuk-frontend/govuk/components/tabs/fixtures.json +29 -29
  163. data/node_modules/govuk-frontend/govuk/components/tabs/tabs.js +28 -0
  164. data/node_modules/govuk-frontend/govuk/components/tag/fixtures.json +28 -28
  165. data/node_modules/govuk-frontend/govuk/components/textarea/fixtures.json +34 -34
  166. data/node_modules/govuk-frontend/govuk/components/warning-text/fixtures.json +14 -14
  167. data/node_modules/govuk-frontend/govuk/core/_section-break.scss +1 -1
  168. data/node_modules/govuk-frontend/govuk/helpers/_colour.scss +2 -2
  169. data/node_modules/govuk-frontend/govuk/helpers/_links.scss +6 -6
  170. data/node_modules/govuk-frontend/govuk/i18n.js +390 -0
  171. data/node_modules/govuk-frontend/govuk/macros/i18n.njk +15 -0
  172. data/node_modules/govuk-frontend/govuk/settings/_all.scss +1 -0
  173. data/node_modules/govuk-frontend/govuk/settings/_colours-palette.scss +12 -0
  174. data/node_modules/govuk-frontend/govuk/settings/_compatibility.scss +26 -0
  175. data/node_modules/govuk-frontend/govuk/settings/_typography-font.scss +23 -0
  176. data/node_modules/govuk-frontend/govuk/settings/_typography-responsive.scss +12 -0
  177. data/node_modules/govuk-frontend/govuk/settings/_warnings.scss +53 -0
  178. data/node_modules/govuk-frontend/govuk/tools/_compatibility.scss +20 -6
  179. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Date/now.js +21 -0
  180. data/node_modules/govuk-frontend/govuk/vendor/polyfills/Element/prototype/dataset.js +300 -0
  181. data/node_modules/govuk-frontend/govuk/vendor/polyfills/String/prototype/trim.js +21 -0
  182. data/node_modules/govuk-frontend/govuk-esm/all.mjs +50 -27
  183. data/node_modules/govuk-frontend/govuk-esm/common/closest-attribute-value.mjs +15 -0
  184. data/node_modules/govuk-frontend/govuk-esm/common/index.mjs +159 -0
  185. data/node_modules/govuk-frontend/govuk-esm/common/normalise-dataset.mjs +58 -0
  186. data/node_modules/govuk-frontend/govuk-esm/common.mjs +6 -28
  187. data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs +113 -43
  188. data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs +67 -30
  189. data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs +325 -123
  190. data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs +9 -3
  191. data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs +22 -8
  192. data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs +48 -6
  193. data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs +6 -0
  194. data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs +32 -2
  195. data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs +9 -3
  196. data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs +10 -4
  197. data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs +8 -2
  198. data/node_modules/govuk-frontend/govuk-esm/i18n.mjs +380 -0
  199. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Date/now.mjs +13 -0
  200. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/dataset.mjs +68 -0
  201. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/String/prototype/trim.mjs +13 -0
  202. data/node_modules/govuk-frontend/govuk-prototype-kit/init.js +7 -0
  203. data/node_modules/govuk-frontend/govuk-prototype-kit/init.scss +12 -0
  204. data/node_modules/govuk-frontend/govuk-prototype-kit.config.json +138 -7
  205. data/node_modules/govuk-frontend/package.json +1 -1
  206. metadata +22 -3
@@ -0,0 +1,390 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
3
+ typeof define === 'function' && define.amd ? define('GOVUKFrontend', ['exports'], factory) :
4
+ (factory((global.GOVUKFrontend = {})));
5
+ }(this, (function (exports) { 'use strict';
6
+
7
+ /**
8
+ * Internal support for selecting messages to render, with placeholder
9
+ * interpolation and locale-aware number formatting and pluralisation
10
+ *
11
+ * @class
12
+ * @private
13
+ * @param {TranslationsFlattened} translations - Key-value pairs of the translation strings to use.
14
+ * @param {object} [config] - Configuration options for the function.
15
+ * @param {string} config.locale - An overriding locale for the PluralRules functionality.
16
+ */
17
+ function I18n (translations, config) {
18
+ // Make list of translations available throughout function
19
+ this.translations = translations || {};
20
+
21
+ // The locale to use for PluralRules and NumberFormat
22
+ this.locale = (config && config.locale) || document.documentElement.lang || 'en';
23
+ }
24
+
25
+ /**
26
+ * The most used function - takes the key for a given piece of UI text and
27
+ * returns the appropriate string.
28
+ *
29
+ * @param {string} lookupKey - The lookup key of the string to use.
30
+ * @param {object} options - Any options passed with the translation string, e.g: for string interpolation.
31
+ * @returns {string} The appropriate translation string.
32
+ */
33
+ I18n.prototype.t = function (lookupKey, options) {
34
+ if (!lookupKey) {
35
+ // Print a console error if no lookup key has been provided
36
+ throw new Error('i18n: lookup key missing')
37
+ }
38
+
39
+ // If the `count` option is set, determine which plural suffix is needed and
40
+ // change the lookupKey to match. We check to see if it's undefined instead of
41
+ // falsy, as this could legitimately be 0.
42
+ if (options && typeof options.count !== 'undefined') {
43
+ // Get the plural suffix
44
+ lookupKey = lookupKey + '.' + this.getPluralSuffix(lookupKey, options.count);
45
+ }
46
+
47
+ if (lookupKey in this.translations) {
48
+ // Fetch the translation string for that lookup key
49
+ var translationString = this.translations[lookupKey];
50
+
51
+ // Check for ${} placeholders in the translation string
52
+ if (translationString.match(/%{(.\S+)}/)) {
53
+ if (!options) {
54
+ throw new Error('i18n: cannot replace placeholders in string if no option data provided')
55
+ }
56
+
57
+ return this.replacePlaceholders(translationString, options)
58
+ } else {
59
+ return translationString
60
+ }
61
+ } else {
62
+ // If the key wasn't found in our translations object,
63
+ // return the lookup key itself as the fallback
64
+ return lookupKey
65
+ }
66
+ };
67
+
68
+ /**
69
+ * Takes a translation string with placeholders, and replaces the placeholders
70
+ * with the provided data
71
+ *
72
+ * @param {string} translationString - The translation string
73
+ * @param {object} options - Any options passed with the translation string, e.g: for string interpolation.
74
+ * @returns {string} The translation string to output, with ${} placeholders replaced
75
+ */
76
+ I18n.prototype.replacePlaceholders = function (translationString, options) {
77
+ var formatter;
78
+
79
+ if (this.hasIntlNumberFormatSupport()) {
80
+ formatter = new Intl.NumberFormat(this.locale);
81
+ }
82
+
83
+ return translationString.replace(/%{(.\S+)}/g, function (placeholderWithBraces, placeholderKey) {
84
+ if (Object.prototype.hasOwnProperty.call(options, placeholderKey)) {
85
+ var placeholderValue = options[placeholderKey];
86
+
87
+ // If a user has passed `false` as the value for the placeholder
88
+ // treat it as though the value should not be displayed
89
+ if (placeholderValue === false) {
90
+ return ''
91
+ }
92
+
93
+ // If the placeholder's value is a number, localise the number formatting
94
+ if (typeof placeholderValue === 'number' && formatter) {
95
+ return formatter.format(placeholderValue)
96
+ }
97
+
98
+ return placeholderValue
99
+ } else {
100
+ throw new Error('i18n: no data found to replace ' + placeholderWithBraces + ' placeholder in string')
101
+ }
102
+ })
103
+ };
104
+
105
+ /**
106
+ * Check to see if the browser supports Intl and Intl.PluralRules.
107
+ *
108
+ * It requires all conditions to be met in order to be supported:
109
+ * - The browser supports the Intl class (true in IE11)
110
+ * - The implementation of Intl supports PluralRules (NOT true in IE11)
111
+ * - The browser/OS has plural rules for the current locale (browser dependent)
112
+ *
113
+ * @returns {boolean} Returns true if all conditions are met. Returns false otherwise.
114
+ */
115
+ I18n.prototype.hasIntlPluralRulesSupport = function () {
116
+ return Boolean(window.Intl && ('PluralRules' in window.Intl && Intl.PluralRules.supportedLocalesOf(this.locale).length))
117
+ };
118
+
119
+ /**
120
+ * Check to see if the browser supports Intl and Intl.NumberFormat.
121
+ *
122
+ * It requires all conditions to be met in order to be supported:
123
+ * - The browser supports the Intl class (true in IE11)
124
+ * - The implementation of Intl supports NumberFormat (also true in IE11)
125
+ * - The browser/OS has number formatting rules for the current locale (browser dependent)
126
+ *
127
+ * @returns {boolean} Returns true if all conditions are met. Returns false otherwise.
128
+ */
129
+ I18n.prototype.hasIntlNumberFormatSupport = function () {
130
+ return Boolean(window.Intl && ('NumberFormat' in window.Intl && Intl.NumberFormat.supportedLocalesOf(this.locale).length))
131
+ };
132
+
133
+ /**
134
+ * Get the appropriate suffix for the plural form.
135
+ *
136
+ * Uses Intl.PluralRules (or our own fallback implementation) to get the
137
+ * 'preferred' form to use for the given count.
138
+ *
139
+ * Checks that a translation has been provided for that plural form – if it
140
+ * hasn't, it'll fall back to the 'other' plural form (unless that doesn't exist
141
+ * either, in which case an error will be thrown)
142
+ *
143
+ * @param {string} lookupKey - The lookup key of the string to use.
144
+ * @param {number} count - Number used to determine which pluralisation to use.
145
+ * @returns {PluralRule} The suffix associated with the correct pluralisation for this locale.
146
+ */
147
+ I18n.prototype.getPluralSuffix = function (lookupKey, count) {
148
+ // Validate that the number is actually a number.
149
+ //
150
+ // Number(count) will turn anything that can't be converted to a Number type
151
+ // into 'NaN'. isFinite filters out NaN, as it isn't a finite number.
152
+ count = Number(count);
153
+ if (!isFinite(count)) { return 'other' }
154
+
155
+ var preferredForm;
156
+
157
+ // Check to verify that all the requirements for Intl.PluralRules are met.
158
+ // If so, we can use that instead of our custom implementation. Otherwise,
159
+ // use the hardcoded fallback.
160
+ if (this.hasIntlPluralRulesSupport()) {
161
+ preferredForm = new Intl.PluralRules(this.locale).select(count);
162
+ } else {
163
+ preferredForm = this.selectPluralFormUsingFallbackRules(count);
164
+ }
165
+
166
+ // Use the correct plural form if provided
167
+ if (lookupKey + '.' + preferredForm in this.translations) {
168
+ return preferredForm
169
+ // Fall back to `other` if the plural form is missing, but log a warning
170
+ // to the console
171
+ } else if (lookupKey + '.other' in this.translations) {
172
+ if (console && 'warn' in console) {
173
+ console.warn('i18n: Missing plural form ".' + preferredForm + '" for "' +
174
+ this.locale + '" locale. Falling back to ".other".');
175
+ }
176
+
177
+ return 'other'
178
+ // If the required `other` plural form is missing, all we can do is error
179
+ } else {
180
+ throw new Error(
181
+ 'i18n: Plural form ".other" is required for "' + this.locale + '" locale'
182
+ )
183
+ }
184
+ };
185
+
186
+ /**
187
+ * Get the plural form using our fallback implementation
188
+ *
189
+ * This is split out into a separate function to make it easier to test the
190
+ * fallback behaviour in an environment where Intl.PluralRules exists.
191
+ *
192
+ * @param {number} count - Number used to determine which pluralisation to use.
193
+ * @returns {PluralRule} The pluralisation form for count in this locale.
194
+ */
195
+ I18n.prototype.selectPluralFormUsingFallbackRules = function (count) {
196
+ // Currently our custom code can only handle positive integers, so let's
197
+ // make sure our number is one of those.
198
+ count = Math.abs(Math.floor(count));
199
+
200
+ var ruleset = this.getPluralRulesForLocale();
201
+
202
+ if (ruleset) {
203
+ return I18n.pluralRules[ruleset](count)
204
+ }
205
+
206
+ return 'other'
207
+ };
208
+
209
+ /**
210
+ * Work out which pluralisation rules to use for the current locale
211
+ *
212
+ * The locale may include a regional indicator (such as en-GB), but we don't
213
+ * usually care about this part, as pluralisation rules are usually the same
214
+ * regardless of region. There are exceptions, however, (e.g. Portuguese) so
215
+ * this searches by both the full and shortened locale codes, just to be sure.
216
+ *
217
+ * @returns {PluralRuleName | undefined} The name of the pluralisation rule to use (a key for one
218
+ * of the functions in this.pluralRules)
219
+ */
220
+ I18n.prototype.getPluralRulesForLocale = function () {
221
+ var locale = this.locale;
222
+ var localeShort = locale.split('-')[0];
223
+
224
+ // Look through the plural rules map to find which `pluralRule` is
225
+ // appropriate for our current `locale`.
226
+ for (var pluralRule in I18n.pluralRulesMap) {
227
+ if (Object.prototype.hasOwnProperty.call(I18n.pluralRulesMap, pluralRule)) {
228
+ var languages = I18n.pluralRulesMap[pluralRule];
229
+ for (var i = 0; i < languages.length; i++) {
230
+ if (languages[i] === locale || languages[i] === localeShort) {
231
+ return pluralRule
232
+ }
233
+ }
234
+ }
235
+ }
236
+ };
237
+
238
+ /**
239
+ * Map of plural rules to languages where those rules apply.
240
+ *
241
+ * Note: These groups are named for the most dominant or recognisable language
242
+ * that uses each system. The groupings do not imply that the languages are
243
+ * related to one another. Many languages have evolved the same systems
244
+ * independently of one another.
245
+ *
246
+ * Code to support more languages can be found in the i18n spike:
247
+ * {@link https://github.com/alphagov/govuk-frontend/blob/spike-i18n-support/src/govuk/i18n.mjs}
248
+ *
249
+ * Languages currently supported:
250
+ *
251
+ * Arabic: Arabic (ar)
252
+ * Chinese: Burmese (my), Chinese (zh), Indonesian (id), Japanese (ja),
253
+ * Javanese (jv), Korean (ko), Malay (ms), Thai (th), Vietnamese (vi)
254
+ * French: Armenian (hy), Bangla (bn), French (fr), Gujarati (gu), Hindi (hi),
255
+ * Persian Farsi (fa), Punjabi (pa), Zulu (zu)
256
+ * German: Afrikaans (af), Albanian (sq), Azerbaijani (az), Basque (eu),
257
+ * Bulgarian (bg), Catalan (ca), Danish (da), Dutch (nl), English (en),
258
+ * Estonian (et), Finnish (fi), Georgian (ka), German (de), Greek (el),
259
+ * Hungarian (hu), Luxembourgish (lb), Norwegian (no), Somali (so),
260
+ * Swahili (sw), Swedish (sv), Tamil (ta), Telugu (te), Turkish (tr),
261
+ * Urdu (ur)
262
+ * Irish: Irish Gaelic (ga)
263
+ * Russian: Russian (ru), Ukrainian (uk)
264
+ * Scottish: Scottish Gaelic (gd)
265
+ * Spanish: European Portuguese (pt-PT), Italian (it), Spanish (es)
266
+ * Welsh: Welsh (cy)
267
+ *
268
+ * @type {Object<PluralRuleName, string[]>}
269
+ */
270
+ I18n.pluralRulesMap = {
271
+ arabic: ['ar'],
272
+ chinese: ['my', 'zh', 'id', 'ja', 'jv', 'ko', 'ms', 'th', 'vi'],
273
+ french: ['hy', 'bn', 'fr', 'gu', 'hi', 'fa', 'pa', 'zu'],
274
+ german: [
275
+ 'af', 'sq', 'az', 'eu', 'bg', 'ca', 'da', 'nl', 'en', 'et', 'fi', 'ka',
276
+ 'de', 'el', 'hu', 'lb', 'no', 'so', 'sw', 'sv', 'ta', 'te', 'tr', 'ur'
277
+ ],
278
+ irish: ['ga'],
279
+ russian: ['ru', 'uk'],
280
+ scottish: ['gd'],
281
+ spanish: ['pt-PT', 'it', 'es'],
282
+ welsh: ['cy']
283
+ };
284
+
285
+ /**
286
+ * Different pluralisation rule sets
287
+ *
288
+ * Returns the appropriate suffix for the plural form associated with `n`.
289
+ * Possible suffixes: 'zero', 'one', 'two', 'few', 'many', 'other' (the actual
290
+ * meaning of each differs per locale). 'other' should always exist, even in
291
+ * languages without plurals, such as Chinese.
292
+ * {@link https://cldr.unicode.org/index/cldr-spec/plural-rules}
293
+ *
294
+ * The count must be a positive integer. Negative numbers and decimals aren't accounted for
295
+ *
296
+ * @type {Object<string, function(number): PluralRule>}
297
+ */
298
+ I18n.pluralRules = {
299
+ arabic: function (n) {
300
+ if (n === 0) { return 'zero' }
301
+ if (n === 1) { return 'one' }
302
+ if (n === 2) { return 'two' }
303
+ if (n % 100 >= 3 && n % 100 <= 10) { return 'few' }
304
+ if (n % 100 >= 11 && n % 100 <= 99) { return 'many' }
305
+ return 'other'
306
+ },
307
+ chinese: function () {
308
+ return 'other'
309
+ },
310
+ french: function (n) {
311
+ return n === 0 || n === 1 ? 'one' : 'other'
312
+ },
313
+ german: function (n) {
314
+ return n === 1 ? 'one' : 'other'
315
+ },
316
+ irish: function (n) {
317
+ if (n === 1) { return 'one' }
318
+ if (n === 2) { return 'two' }
319
+ if (n >= 3 && n <= 6) { return 'few' }
320
+ if (n >= 7 && n <= 10) { return 'many' }
321
+ return 'other'
322
+ },
323
+ russian: function (n) {
324
+ var lastTwo = n % 100;
325
+ var last = lastTwo % 10;
326
+ if (last === 1 && lastTwo !== 11) { return 'one' }
327
+ if (last >= 2 && last <= 4 && !(lastTwo >= 12 && lastTwo <= 14)) { return 'few' }
328
+ if (last === 0 || (last >= 5 && last <= 9) || (lastTwo >= 11 && lastTwo <= 14)) { return 'many' }
329
+ // Note: The 'other' suffix is only used by decimal numbers in Russian.
330
+ // We don't anticipate it being used, but it's here for consistency.
331
+ return 'other'
332
+ },
333
+ scottish: function (n) {
334
+ if (n === 1 || n === 11) { return 'one' }
335
+ if (n === 2 || n === 12) { return 'two' }
336
+ if ((n >= 3 && n <= 10) || (n >= 13 && n <= 19)) { return 'few' }
337
+ return 'other'
338
+ },
339
+ spanish: function (n) {
340
+ if (n === 1) { return 'one' }
341
+ if (n % 1000000 === 0 && n !== 0) { return 'many' }
342
+ return 'other'
343
+ },
344
+ welsh: function (n) {
345
+ if (n === 0) { return 'zero' }
346
+ if (n === 1) { return 'one' }
347
+ if (n === 2) { return 'two' }
348
+ if (n === 3) { return 'few' }
349
+ if (n === 6) { return 'many' }
350
+ return 'other'
351
+ }
352
+ };
353
+
354
+ /**
355
+ * Supported languages for plural rules
356
+ *
357
+ * @typedef {'arabic' | 'chinese' | 'french' | 'german' | 'irish' | 'russian' | 'scottish' | 'spanish' | 'welsh'} PluralRuleName
358
+ */
359
+
360
+ /**
361
+ * Plural rule category mnemonic tags
362
+ *
363
+ * @typedef {'zero' | 'one' | 'two' | 'few' | 'many' | 'other'} PluralRule
364
+ */
365
+
366
+ /**
367
+ * Translated message by plural rule they correspond to.
368
+ *
369
+ * Allows to group pluralised messages under a single key when passing
370
+ * translations to a component's constructor
371
+ *
372
+ * @typedef {object} TranslationPluralForms
373
+ * @property {string} [other] - General plural form
374
+ * @property {string} [zero] - Plural form used with 0
375
+ * @property {string} [one] - Plural form used with 1
376
+ * @property {string} [two] - Plural form used with 2
377
+ * @property {string} [few] - Plural form used for a few
378
+ * @property {string} [many] - Plural form used for many
379
+ */
380
+
381
+ /**
382
+ * Translated messages (flattened)
383
+ *
384
+ * @private
385
+ * @typedef {Object<string, string> | {}} TranslationsFlattened
386
+ */
387
+
388
+ exports.I18n = I18n;
389
+
390
+ })));
@@ -0,0 +1,15 @@
1
+ {#
2
+ # Renders the data attributes for the different plural forms
3
+ # of the given translation key.
4
+ #
5
+ # Helps reduce the boilerplate in component templates as they're quite verbose
6
+ #
7
+ # @private
8
+ # @param {string} translationKey - The kebab-cased name of the translation key
9
+ # @param {object} pluralForms
10
+ # An object associating translation messages to the plural form they correspond to
11
+ # http://unicode.org/reports/tr35/tr35-numbers.html#Language_Plural_Rules
12
+ #}
13
+ {% macro govukPluralisedI18nAttributes(translationKey, pluralForms) %}
14
+ {% for pluralType, message in pluralForms %} data-i18n.{{translationKey}}.{{pluralType}}="{{message | escape}}"{% endfor %}
15
+ {% endmacro %}
@@ -3,6 +3,7 @@
3
3
 
4
4
  @import "assets";
5
5
 
6
+ @import "warnings";
6
7
  @import "compatibility";
7
8
  @import "global-styles";
8
9
  @import "ie8";
@@ -15,6 +15,8 @@
15
15
  ///
16
16
  /// @type Boolean
17
17
  /// @access public
18
+ /// @deprecated Will be removed in v5.0 with the rest of the compatibility mode
19
+ /// suite of tools and settings
18
20
 
19
21
  $govuk-use-legacy-palette: if(
20
22
  (
@@ -26,6 +28,16 @@ $govuk-use-legacy-palette: if(
26
28
  false
27
29
  ) !default;
28
30
 
31
+ // Only show the deprecation warning if user is setting $govuk-use-legacy-palette
32
+ // manually instead of automatically via compatibility variables
33
+ @if $govuk-use-legacy-palette == true and
34
+ $govuk-compatibility-govukfrontendtoolkit == false and
35
+ $govuk-compatibility-govuktemplate == false and
36
+ $govuk-compatibility-govukelements == false {
37
+ @include _warning(legacy-palette, "$govuk-use-legacy-palette is deprecated. " +
38
+ "Only the modern colour palette will be supported from v5.0.");
39
+ }
40
+
29
41
  /// Modern colour palette
30
42
  ///
31
43
  /// This exists only because you cannot easily set a !default variable
@@ -23,9 +23,17 @@
23
23
  ///
24
24
  /// @type Boolean
25
25
  /// @access public
26
+ /// @deprecated Will be removed in v5.0 with the rest of the compatibility mode
27
+ /// suite of tools and settings
26
28
 
27
29
  $govuk-compatibility-govukfrontendtoolkit: false !default;
28
30
 
31
+ @if $govuk-compatibility-govukfrontendtoolkit == true {
32
+ @include _warning("compatibility-mode", "$govuk-compatibility-govukfrontendtoolkit " +
33
+ "is deprecated. From version 5.0, GOV.UK Frontend will remove compatibility " +
34
+ "with the legacy library govuk_frontend_toolkit.");
35
+ }
36
+
29
37
  /// Compatibility Mode: alphagov/govuk_template
30
38
  ///
31
39
  /// Enabling this will:
@@ -41,9 +49,17 @@ $govuk-compatibility-govukfrontendtoolkit: false !default;
41
49
  ///
42
50
  /// @type Boolean
43
51
  /// @access public
52
+ /// @deprecated Will be removed in v5.0 with the rest of the compatibility mode
53
+ /// suite of tools and settings
44
54
 
45
55
  $govuk-compatibility-govuktemplate: false !default;
46
56
 
57
+ @if $govuk-compatibility-govuktemplate == true {
58
+ @include _warning("compatibility-mode", "$govuk-compatibility-govuktemplate " +
59
+ "is deprecated. From version 5.0, GOV.UK Frontend will remove " +
60
+ "compatibility with the legacy library govuk_template.");
61
+ }
62
+
47
63
  /// Compatibility Mode: alphagov/govuk_elements
48
64
  ///
49
65
  /// Enabling this will:
@@ -56,9 +72,17 @@ $govuk-compatibility-govuktemplate: false !default;
56
72
  ///
57
73
  /// @type Boolean
58
74
  /// @access public
75
+ /// @deprecated Will be removed in v5.0 with the rest of the compatibility mode
76
+ /// suite of tools and settings
59
77
 
60
78
  $govuk-compatibility-govukelements: false !default;
61
79
 
80
+ @if $govuk-compatibility-govukelements == true {
81
+ @include _warning("compatibility-mode", "$govuk-compatibility-govukelements " +
82
+ "is deprecated. From version 5.0, GOV.UK Frontend will remove compatibility " +
83
+ "with the legacy library govuk_elements.");
84
+ }
85
+
62
86
  /// Compatibility Product Map
63
87
  ///
64
88
  /// Maps product names to their settings that we can use to lookup states from
@@ -66,6 +90,8 @@ $govuk-compatibility-govukelements: false !default;
66
90
  ///
67
91
  /// @type Map
68
92
  /// @access private
93
+ /// @deprecated Will be removed in v5.0 with the rest of the compatibility mode
94
+ /// suite of tools and settings
69
95
 
70
96
  $_govuk-compatibility: (
71
97
  govuk_frontend_toolkit: $govuk-compatibility-govukfrontendtoolkit,
@@ -13,6 +13,8 @@
13
13
  ///
14
14
  /// @type Boolean
15
15
  /// @access public
16
+ /// @deprecated Will be removed in v5.0 with the rest of the compatibility mode
17
+ /// suite of tools and settings
16
18
 
17
19
  $govuk-use-legacy-font: if(
18
20
  (
@@ -24,6 +26,17 @@ $govuk-use-legacy-font: if(
24
26
  false
25
27
  ) !default;
26
28
 
29
+ // Only show the deprecation warning if user is setting $govuk-use-legacy-font
30
+ // manually instead of automatically via compatibility variables
31
+ @if $govuk-use-legacy-font == true and
32
+ $govuk-compatibility-govukfrontendtoolkit == false and
33
+ $govuk-compatibility-govuktemplate == false and
34
+ $govuk-compatibility-govukelements == false {
35
+ @include _warning(legacy-font, "$govuk-use-legacy-font is deprecated. " +
36
+ "From version 5.0, GOV.UK Frontend will only support the included version " +
37
+ "of GDS Transport.");
38
+ }
39
+
27
40
  // =========================================================
28
41
  // Font families
29
42
  // =========================================================
@@ -43,6 +56,8 @@ $govuk-font-family: if(
43
56
  ///
44
57
  /// @type List
45
58
  /// @access public
59
+ /// @deprecated Will be removed in v5.0 with the rest of the compatibility mode
60
+ /// suite of tools and settings
46
61
 
47
62
  $govuk-font-family-tabular: if(
48
63
  $govuk-use-legacy-font,
@@ -50,6 +65,14 @@ $govuk-font-family-tabular: if(
50
65
  false
51
66
  ) !default;
52
67
 
68
+ // Only show the deprecation warning if user is setting $govuk-font-family-tabular
69
+ // manually instead of automatically via $govuk-use-legacy-font
70
+ @if $govuk-font-family-tabular != false and $govuk-use-legacy-font == false {
71
+ @include _warning(tabular-font-face, "$govuk-font-family-tabular is deprecated. " +
72
+ "From version 5.0, GOV.UK Frontend will not support using a separate " +
73
+ "font-face for tabular numbers.");
74
+ }
75
+
53
76
  /// Font families to use for print media
54
77
  ///
55
78
  /// We recommend that you use system fonts when printing. This will avoid issues
@@ -13,6 +13,8 @@
13
13
  ///
14
14
  /// @type Boolean
15
15
  /// @access public
16
+ /// @deprecated Will be removed in v5.0 with the rest of the compatibility mode
17
+ /// suite of tools and settings
16
18
 
17
19
  $govuk-typography-use-rem: if(
18
20
  (
@@ -24,6 +26,16 @@ $govuk-typography-use-rem: if(
24
26
  true
25
27
  ) !default;
26
28
 
29
+ // Only show the deprecation warning if user is setting $govuk-typography-use-rem
30
+ // manually instead of automatically via compatibility variables
31
+ @if $govuk-typography-use-rem == false and
32
+ $govuk-compatibility-govukfrontendtoolkit == false and
33
+ $govuk-compatibility-govuktemplate == false and
34
+ $govuk-compatibility-govukelements == false {
35
+ @include _warning(allow-not-using-rem, "$govuk-typography-use-rem is deprecated. " +
36
+ "From version 5.0, GOV.UK Frontend will not support disabling rem font sizes.");
37
+ }
38
+
27
39
  /// Root font size
28
40
  ///
29
41
  /// This is used to calculate rem sizes for the typography, and should match the
@@ -0,0 +1,53 @@
1
+ ////
2
+ /// @group settings/warnings
3
+ ////
4
+
5
+ /// Suppressed warnings map
6
+ ///
7
+ /// This map is used to determine which deprecation warnings to **not** show
8
+ /// to users when compiling sass. This is in place for codebases that do not
9
+ /// have the necessary capacity to upgrade and remove the deprecation,
10
+ /// particularly if the deprecation is significant. For example, removal of
11
+ /// compatibility with legacy libraries such as govuk_elements.
12
+ ///
13
+ /// You can add to this map and define which warnings to suppress by appending to
14
+ /// it using the warning key, found in the warning message. For example:
15
+ ///
16
+ /// @example scss:
17
+ /// // warning message:
18
+ /// // $foobar is no longer supported. To silence this warning, update
19
+ /// // $govuk-suppressed-warnings with key: "foobar"
20
+ /// $govuk-suppressed-warnings: (
21
+ /// foobar
22
+ /// );
23
+ ///
24
+ /// @type List
25
+ /// @access public
26
+
27
+ $govuk-suppressed-warnings: () !default;
28
+
29
+ /// Warnings
30
+ ///
31
+ /// Acts as a wrapper for the built in `@warn` sass function
32
+ ///
33
+ /// We use this instead of using `@warn` for 3 reasons:
34
+ ///
35
+ /// - To check if a warning is being suppressed through `$govuk-suppressed-warnings`,
36
+ /// in which case we don't call `@warn` and printing the warning to the user
37
+ /// - To format the passed warning `$message` with the warning key at the end
38
+ /// - To prevent duplicate warnings by adding the passed `$key` to
39
+ /// `$govuk-suppressed-warnings` after `@warn` is called to ensure it only runs
40
+ /// once per sass compilation
41
+ ///
42
+ /// @param {String} $key - The key to be checked against `$govuk-suppressed-warnings`
43
+ /// and then passed to it to prevent multiple of the same warning.
44
+ /// @param {String} $message - The message to use when calling `@warn`
45
+ /// @access private
46
+
47
+ @mixin _warning($key, $message) {
48
+ @if not index($govuk-suppressed-warnings, $key) {
49
+ @warn $message + " To silence this warning, update $govuk-suppressed-warnings " +
50
+ "with key: \"#{$key}\"";
51
+ $govuk-suppressed-warnings: append($govuk-suppressed-warnings, $key) !global;
52
+ }
53
+ }
@@ -2,6 +2,20 @@
2
2
  /// @group tools/compatibility-mode
3
3
  ////
4
4
 
5
+ /// Temporary private version of govuk-compatibility to avoid deprecation warnings
6
+ ///
7
+ /// @access private
8
+
9
+ @mixin _govuk-compatibility($product) {
10
+ @if map-has-key($_govuk-compatibility, $product) {
11
+ @if map-get($_govuk-compatibility, $product) == true {
12
+ @content;
13
+ }
14
+ } @else {
15
+ @error "Non existent product '#{$product}'";
16
+ }
17
+ }
18
+
5
19
  /// Conditional Compatibility Mixin
6
20
  ///
7
21
  /// Selectively output a block (available to the mixin as @content) if a given
@@ -24,13 +38,13 @@
24
38
  /// this product
25
39
  /// @throw Errors if product name is not recognised
26
40
  /// @access public
41
+ /// @deprecated Will be removed in v5.0 with the rest of the compatibility mode
42
+ /// suite of tools and settings
27
43
 
28
44
  @mixin govuk-compatibility($product) {
29
- @if map-has-key($_govuk-compatibility, $product) {
30
- @if map-get($_govuk-compatibility, $product) == true {
31
- @content;
32
- }
33
- } @else {
34
- @error "Non existent product '#{$product}'";
45
+ @include _warning(compatibility-helper, "govuk-compatibility is deprecated. " +
46
+ "From version 5.0, GOV.UK Frontend will not support compatibility mode.");
47
+ @include _govuk-compatibility($product) {
48
+ @content;
35
49
  }
36
50
  }