govuk_publishing_components 32.0.0 → 33.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (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
  }