govuk_publishing_components 29.13.0 → 29.15.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (159) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/govuk_publishing_components/action-link-arrow--white.png +0 -0
  3. data/app/assets/images/govuk_publishing_components/action-link-arrow--white.svg +1 -0
  4. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/gtm-page-views.js +5 -3
  5. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4/pii-remover.js +135 -0
  6. data/app/assets/javascripts/govuk_publishing_components/analytics-ga4.js +2 -0
  7. data/app/assets/javascripts/govuk_publishing_components/components/accordion.js +27 -22
  8. data/app/assets/javascripts/govuk_publishing_components/components/table.js +52 -0
  9. data/app/assets/stylesheets/govuk_publishing_components/components/_action-link.scss +7 -0
  10. data/app/assets/stylesheets/govuk_publishing_components/components/_previous-and-next-navigation.scss +1 -92
  11. data/app/models/govuk_publishing_components/audit_applications.rb +31 -9
  12. data/app/models/govuk_publishing_components/audit_comparer.rb +15 -9
  13. data/app/views/govuk_publishing_components/audit/_components.html.erb +20 -2
  14. data/app/views/govuk_publishing_components/components/_action_link.html.erb +2 -0
  15. data/app/views/govuk_publishing_components/components/_previous_and_next_navigation.html.erb +33 -36
  16. data/app/views/govuk_publishing_components/components/_table.html.erb +61 -30
  17. data/app/views/govuk_publishing_components/components/docs/accordion.yml +2 -1
  18. data/app/views/govuk_publishing_components/components/docs/action_link.yml +8 -0
  19. data/app/views/govuk_publishing_components/components/docs/back_link.yml +1 -1
  20. data/app/views/govuk_publishing_components/components/docs/big_number.yml +2 -2
  21. data/app/views/govuk_publishing_components/components/docs/breadcrumbs.yml +2 -2
  22. data/app/views/govuk_publishing_components/components/docs/button.yml +41 -40
  23. data/app/views/govuk_publishing_components/components/docs/cards.yml +2 -0
  24. data/app/views/govuk_publishing_components/components/docs/checkboxes.yml +216 -216
  25. data/app/views/govuk_publishing_components/components/docs/cookie_banner.yml +2 -1
  26. data/app/views/govuk_publishing_components/components/docs/copy_to_clipboard.yml +2 -2
  27. data/app/views/govuk_publishing_components/components/docs/details.yml +5 -1
  28. data/app/views/govuk_publishing_components/components/docs/document_list.yml +1 -2
  29. data/app/views/govuk_publishing_components/components/docs/error_alert.yml +4 -0
  30. data/app/views/govuk_publishing_components/components/docs/error_summary.yml +4 -6
  31. data/app/views/govuk_publishing_components/components/docs/image_card.yml +2 -1
  32. data/app/views/govuk_publishing_components/components/docs/intervention.yml +25 -25
  33. data/app/views/govuk_publishing_components/components/docs/organisation_logo.yml +1 -2
  34. data/app/views/govuk_publishing_components/components/docs/previous_and_next_navigation.yml +1 -1
  35. data/app/views/govuk_publishing_components/components/docs/print_link.yml +5 -1
  36. data/app/views/govuk_publishing_components/components/docs/select.yml +101 -98
  37. data/app/views/govuk_publishing_components/components/docs/table.yml +36 -1
  38. data/app/views/govuk_publishing_components/components/docs/tabs.yml +4 -0
  39. data/config/locales/ar.yml +6 -0
  40. data/config/locales/az.yml +6 -0
  41. data/config/locales/be.yml +6 -0
  42. data/config/locales/bg.yml +6 -0
  43. data/config/locales/bn.yml +6 -0
  44. data/config/locales/cs.yml +6 -0
  45. data/config/locales/cy.yml +6 -0
  46. data/config/locales/da.yml +6 -0
  47. data/config/locales/de.yml +6 -0
  48. data/config/locales/dr.yml +6 -0
  49. data/config/locales/el.yml +6 -0
  50. data/config/locales/en.yml +6 -0
  51. data/config/locales/es-419.yml +6 -0
  52. data/config/locales/es.yml +6 -0
  53. data/config/locales/et.yml +6 -0
  54. data/config/locales/fa.yml +6 -0
  55. data/config/locales/fi.yml +6 -0
  56. data/config/locales/fr.yml +6 -0
  57. data/config/locales/gd.yml +6 -0
  58. data/config/locales/gu.yml +6 -0
  59. data/config/locales/he.yml +6 -0
  60. data/config/locales/hi.yml +6 -0
  61. data/config/locales/hr.yml +6 -0
  62. data/config/locales/hu.yml +6 -0
  63. data/config/locales/hy.yml +6 -0
  64. data/config/locales/id.yml +6 -0
  65. data/config/locales/is.yml +6 -0
  66. data/config/locales/it.yml +6 -0
  67. data/config/locales/ja.yml +6 -0
  68. data/config/locales/ka.yml +6 -0
  69. data/config/locales/kk.yml +6 -0
  70. data/config/locales/ko.yml +6 -0
  71. data/config/locales/lt.yml +6 -0
  72. data/config/locales/lv.yml +6 -0
  73. data/config/locales/ms.yml +6 -0
  74. data/config/locales/mt.yml +6 -0
  75. data/config/locales/nl.yml +6 -0
  76. data/config/locales/no.yml +6 -0
  77. data/config/locales/pa-pk.yml +6 -0
  78. data/config/locales/pa.yml +6 -0
  79. data/config/locales/pl.yml +6 -0
  80. data/config/locales/ps.yml +6 -0
  81. data/config/locales/pt.yml +6 -0
  82. data/config/locales/ro.yml +6 -0
  83. data/config/locales/ru.yml +6 -0
  84. data/config/locales/si.yml +6 -0
  85. data/config/locales/sk.yml +6 -0
  86. data/config/locales/sl.yml +6 -0
  87. data/config/locales/so.yml +6 -0
  88. data/config/locales/sq.yml +6 -0
  89. data/config/locales/sr.yml +6 -0
  90. data/config/locales/sv.yml +6 -0
  91. data/config/locales/sw.yml +6 -0
  92. data/config/locales/ta.yml +6 -0
  93. data/config/locales/th.yml +6 -0
  94. data/config/locales/tk.yml +6 -0
  95. data/config/locales/tr.yml +6 -0
  96. data/config/locales/uk.yml +6 -0
  97. data/config/locales/ur.yml +6 -0
  98. data/config/locales/uz.yml +6 -0
  99. data/config/locales/vi.yml +6 -0
  100. data/config/locales/zh-hk.yml +6 -0
  101. data/config/locales/zh-tw.yml +6 -0
  102. data/config/locales/zh.yml +6 -0
  103. data/lib/govuk_publishing_components/app_helpers/table_helper.rb +4 -2
  104. data/lib/govuk_publishing_components/version.rb +1 -1
  105. data/node_modules/govuk-frontend/govuk/components/_all.scss +1 -0
  106. data/node_modules/govuk-frontend/govuk/components/accordion/_index.scss +1 -0
  107. data/node_modules/govuk-frontend/govuk/components/character-count/fixtures.json +2 -1
  108. data/node_modules/govuk-frontend/govuk/components/checkboxes/fixtures.json +102 -44
  109. data/node_modules/govuk-frontend/govuk/components/checkboxes/macro-options.json +7 -1
  110. data/node_modules/govuk-frontend/govuk/components/checkboxes/template.njk +3 -2
  111. data/node_modules/govuk-frontend/govuk/components/cookie-banner/fixtures.json +10 -10
  112. data/node_modules/govuk-frontend/govuk/components/fieldset/fixtures.json +92 -1
  113. data/node_modules/govuk-frontend/govuk/components/file-upload/fixtures.json +2 -1
  114. data/node_modules/govuk-frontend/govuk/components/header/_index.scss +3 -0
  115. data/node_modules/govuk-frontend/govuk/components/header/fixtures.json +14 -6
  116. data/node_modules/govuk-frontend/govuk/components/header/template.njk +9 -3
  117. data/node_modules/govuk-frontend/govuk/components/input/fixtures.json +2 -1
  118. data/node_modules/govuk-frontend/govuk/components/input/macro-options.json +1 -1
  119. data/node_modules/govuk-frontend/govuk/components/label/fixtures.json +76 -1
  120. data/node_modules/govuk-frontend/govuk/components/pagination/README.md +15 -0
  121. data/node_modules/govuk-frontend/govuk/components/pagination/_index.scss +244 -0
  122. data/node_modules/govuk-frontend/govuk/components/pagination/_pagination.scss +2 -0
  123. data/node_modules/govuk-frontend/govuk/components/pagination/fixtures.json +300 -0
  124. data/node_modules/govuk-frontend/govuk/components/pagination/macro-options.json +128 -0
  125. data/node_modules/govuk-frontend/govuk/components/pagination/macro.njk +3 -0
  126. data/node_modules/govuk-frontend/govuk/components/pagination/template.njk +62 -0
  127. data/node_modules/govuk-frontend/govuk/components/radios/fixtures.json +147 -43
  128. data/node_modules/govuk-frontend/govuk/components/radios/macro-options.json +7 -1
  129. data/node_modules/govuk-frontend/govuk/components/radios/template.njk +3 -2
  130. data/node_modules/govuk-frontend/govuk/components/select/fixtures.json +56 -2
  131. data/node_modules/govuk-frontend/govuk/components/select/macro-options.json +7 -1
  132. data/node_modules/govuk-frontend/govuk/components/select/template.njk +1 -1
  133. data/node_modules/govuk-frontend/govuk/components/textarea/fixtures.json +2 -1
  134. data/node_modules/govuk-frontend/govuk-esm/all.mjs +12 -12
  135. data/node_modules/govuk-frontend/govuk-esm/components/accordion/accordion.mjs +3 -3
  136. data/node_modules/govuk-frontend/govuk-esm/components/button/button.mjs +2 -2
  137. data/node_modules/govuk-frontend/govuk-esm/components/character-count/character-count.mjs +3 -3
  138. data/node_modules/govuk-frontend/govuk-esm/components/checkboxes/checkboxes.mjs +4 -4
  139. data/node_modules/govuk-frontend/govuk-esm/components/details/details.mjs +3 -3
  140. data/node_modules/govuk-frontend/govuk-esm/components/error-summary/error-summary.mjs +3 -3
  141. data/node_modules/govuk-frontend/govuk-esm/components/header/header.mjs +3 -3
  142. data/node_modules/govuk-frontend/govuk-esm/components/notification-banner/notification-banner.mjs +1 -1
  143. data/node_modules/govuk-frontend/govuk-esm/components/radios/radios.mjs +4 -4
  144. data/node_modules/govuk-frontend/govuk-esm/components/skip-link/skip-link.mjs +3 -3
  145. data/node_modules/govuk-frontend/govuk-esm/components/tabs/tabs.mjs +6 -6
  146. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/{DOMTokenList.js → DOMTokenList.mjs} +0 -0
  147. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/{Document.js → Document.mjs} +0 -0
  148. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/{classList.js → classList.mjs} +4 -4
  149. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/{closest.js → closest.mjs} +1 -1
  150. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/{matches.js → matches.mjs} +0 -0
  151. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/{nextElementSibling.js → nextElementSibling.mjs} +2 -2
  152. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Element/prototype/{previousElementSibling.js → previousElementSibling.mjs} +2 -2
  153. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/{Element.js → Element.mjs} +1 -1
  154. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/{Event.js → Event.mjs} +3 -3
  155. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Function/prototype/{bind.js → bind.mjs} +1 -1
  156. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/Object/{defineProperty.js → defineProperty.mjs} +0 -0
  157. data/node_modules/govuk-frontend/govuk-esm/vendor/polyfills/{Window.js → Window.mjs} +0 -0
  158. data/node_modules/govuk-frontend/package.json +8 -2
  159. metadata +26 -15
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dafa42cbe074f0cac7f3d82ad2475eee0cbd895e755279ff94a0fb8862d0f7c2
4
- data.tar.gz: 2b06381bc10381652f927ce42a46dc3d1a008b3e78c26646816b6f4809bd2605
3
+ metadata.gz: d9201a328c875b8cb5c93315a6365ea7dbc632027d0b973f9b0e700c86e01f6a
4
+ data.tar.gz: 78cd444356c208537d7108cda4c471774a09b140c9db3e7aec1b0899adebf968
5
5
  SHA512:
6
- metadata.gz: f5adab3000ea81b5eaae1506a4d2070ac0e35bf499e4d4ca2500534a087fb67b8e79ac6012faae9590142122f432f7ea36d3c90db819a515d2b623d570e6cb70
7
- data.tar.gz: 278fabdee01f0785b2fc2b26dfc07f9c122cd640cf78a8666a846d54d3b44b5e009544c1428d4ed7a24e3ea8af07cfa9d440710e8606bf19e3bc94b46d7e0b2b
6
+ metadata.gz: cf29058c5c655fed33c3f10e34728752117387c0006893c70dccf563862a5cc98dae584218e974b40b63b71f64aef1ea8ffb9b9f0c98dde7bbc49fcea331da99
7
+ data.tar.gz: 94bac53144fd6f7685976fbc884485d054ac991f07e1bee42c31707509cf6702063f3c1b9f67314e54dc48ea5f5d08ab00562a68e2af65b9b7dd0f98a7d5e1e5
@@ -0,0 +1 @@
1
+ <svg width="39" height="39" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M17.01 6.818l-2.828 2.828 7.853 7.854-22 .066L0 21.5h22.035l-7.853 7.854 2.828 2.828L29.69 19.5zM39 19.5C39 30.27 30.27 39 19.5 39 9.373 39 1.05 31.28.092 21.405A19.737 19.737 0 010 19.5C0 8.73 8.73 0 19.5 0S39 8.73 39 19.5z" fill="#fff"/></svg>
@@ -4,6 +4,8 @@
4
4
  var GOVUK = global.GOVUK || {}
5
5
 
6
6
  GOVUK.Gtm = {
7
+ PIIRemover: new GOVUK.analyticsGA4.PIIRemover(), // imported in analytics-ga4.js
8
+
7
9
  sendPageView: function () {
8
10
  if (window.dataLayer) {
9
11
  var data = {
@@ -48,15 +50,15 @@
48
50
  },
49
51
 
50
52
  getLocation: function () {
51
- return document.location.href
53
+ return this.PIIRemover.stripPII(document.location.href)
52
54
  },
53
55
 
54
56
  getReferrer: function () {
55
- return document.referrer
57
+ return this.PIIRemover.stripPIIWithOverride(document.referrer, true, true)
56
58
  },
57
59
 
58
60
  getTitle: function () {
59
- return document.title
61
+ return this.PIIRemover.stripPII(document.title)
60
62
  },
61
63
 
62
64
  // window.httpStatusCode is set in the source of the error page in static
@@ -0,0 +1,135 @@
1
+ ;(function (global) {
2
+ 'use strict'
3
+
4
+ var GOVUK = global.GOVUK || {}
5
+ var EMAIL_PATTERN = /[^\s=/?&#]+(?:@|%40)[^\s=/?&]+/g
6
+ var POSTCODE_PATTERN = /\b[A-PR-UWYZ][A-HJ-Z]?[0-9][0-9A-HJKMNPR-Y]?(?:[\s+]|%20)*[0-9](?!refund)[ABD-HJLNPQ-Z]{2,3}\b/gi
7
+ var DATE_PATTERN = /\d{4}(-?)\d{2}(-?)\d{2}/g
8
+ var ESCAPE_REGEX_PATTERN = /[|\\{}()[\]^$+*?.]/g
9
+
10
+ // specific URL parameters to be redacted from accounts URLs
11
+ var RESET_PASSWORD_TOKEN_PATTERN = /reset_password_token=[a-zA-Z0-9-]+/g
12
+ var UNLOCK_TOKEN_PATTERN = /unlock_token=[a-zA-Z0-9-]+/g
13
+ var STATE_PATTERN = /state=.[^&]+/g
14
+
15
+ function shouldStripDates () {
16
+ var metas = document.querySelectorAll('meta[name="govuk:static-analytics:strip-dates"]')
17
+ return metas.length > 0
18
+ }
19
+
20
+ function shouldStripPostcodes () {
21
+ var metas = document.querySelectorAll('meta[name="govuk:static-analytics:strip-postcodes"]')
22
+ return metas.length > 0
23
+ }
24
+
25
+ function queryStringParametersToStrip () {
26
+ var meta = document.querySelector('meta[name="govuk:static-analytics:strip-query-string-parameters"]')
27
+ var value = false
28
+ if (meta) {
29
+ value = meta.getAttribute('content')
30
+ }
31
+ var parameters = []
32
+
33
+ if (value) {
34
+ var split = value.split(',')
35
+ for (var i = 0; i < split.length; i++) {
36
+ parameters.push(split[i].trim())
37
+ }
38
+ }
39
+
40
+ return parameters
41
+ }
42
+
43
+ var PIIRemover = function () {
44
+ this.stripDatePII = shouldStripDates()
45
+ this.stripPostcodePII = shouldStripPostcodes()
46
+ this.queryStringParametersToStrip = queryStringParametersToStrip()
47
+ }
48
+
49
+ PIIRemover.prototype.PIISafe = function (value) {
50
+ this.value = value
51
+ }
52
+
53
+ PIIRemover.prototype.stripPII = function (value) {
54
+ if (typeof value === 'string') {
55
+ return this.stripPIIFromString(value)
56
+ } else if (Object.prototype.toString.call(value) === '[object Array]' || Object.prototype.toString.call(value) === '[object Arguments]') {
57
+ return this.stripPIIFromArray(value)
58
+ } else if (typeof value === 'object') {
59
+ return this.stripPIIFromObject(value)
60
+ } else {
61
+ return value
62
+ }
63
+ }
64
+
65
+ PIIRemover.prototype.stripPIIWithOverride = function (value, enableDateStripping, enablePostcodeStripping) {
66
+ var oldStripDatePII = this.stripDatePII
67
+ var oldPostcodePII = this.stripPostcodePII
68
+
69
+ this.stripDatePII = enableDateStripping
70
+ this.stripPostcodePII = enablePostcodeStripping
71
+
72
+ var strippedValue = this.stripPII(value)
73
+
74
+ this.stripDatePII = oldStripDatePII
75
+ this.stripPostcodePII = oldPostcodePII
76
+
77
+ return strippedValue
78
+ }
79
+
80
+ PIIRemover.prototype.stripPIIFromString = function (string) {
81
+ var stripped = string.replace(EMAIL_PATTERN, '[email]')
82
+ stripped = stripped.replace(RESET_PASSWORD_TOKEN_PATTERN, 'reset_password_token=[reset_password_token]')
83
+ stripped = stripped.replace(UNLOCK_TOKEN_PATTERN, 'unlock_token=[unlock_token]')
84
+ stripped = stripped.replace(STATE_PATTERN, 'state=[state]')
85
+ stripped = this.stripQueryStringParameters(stripped)
86
+
87
+ if (this.stripDatePII === true) {
88
+ stripped = stripped.replace(DATE_PATTERN, '[date]')
89
+ }
90
+ if (this.stripPostcodePII === true) {
91
+ stripped = stripped.replace(POSTCODE_PATTERN, '[postcode]')
92
+ }
93
+ return stripped
94
+ }
95
+
96
+ PIIRemover.prototype.stripPIIFromObject = function (object) {
97
+ if (object) {
98
+ if (object instanceof this.PIISafe) {
99
+ return object.value
100
+ } else {
101
+ for (var property in object) {
102
+ var value = object[property]
103
+
104
+ object[property] = this.stripPII(value)
105
+ }
106
+ return object
107
+ }
108
+ }
109
+ }
110
+
111
+ PIIRemover.prototype.stripPIIFromArray = function (array) {
112
+ for (var i = 0, l = array.length; i < l; i++) {
113
+ var elem = array[i]
114
+
115
+ array[i] = this.stripPII(elem)
116
+ }
117
+ return array
118
+ }
119
+
120
+ PIIRemover.prototype.stripQueryStringParameters = function (string) {
121
+ for (var i = 0; i < this.queryStringParametersToStrip.length; i++) {
122
+ var parameter = this.queryStringParametersToStrip[i]
123
+ var escaped = parameter.replace(ESCAPE_REGEX_PATTERN, '\\$&')
124
+ var regexp = new RegExp('((?:\\?|&)' + escaped + '=)(?:[^&#\\s]*)', 'g')
125
+ string = string.replace(regexp, '$1[' + parameter + ']')
126
+ }
127
+
128
+ return string
129
+ }
130
+
131
+ GOVUK.analyticsGA4 = GOVUK.analyticsGA4 || {}
132
+ GOVUK.analyticsGA4.PIIRemover = PIIRemover
133
+
134
+ global.GOVUK = GOVUK
135
+ })(window)
@@ -1,3 +1,5 @@
1
+ // The following modules are imported in a specific order
2
+ //= require ./analytics-ga4/pii-remover
1
3
  //= require ./analytics-ga4/gtm-page-views
2
4
  //= require ./analytics-ga4/gtm-click-tracking
3
5
 
@@ -10,27 +10,22 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
10
10
  function GemAccordion ($module) {
11
11
  this.$module = $module
12
12
  this.sectionClass = 'govuk-accordion__section'
13
- this.sectionClassExpanded = 'govuk-accordion__section--expanded'
14
- this.sectionHeaderClass = 'govuk-accordion__section-header'
15
- this.sectionInnerContent = 'govuk-accordion__section-content'
16
- this.showAllControls = 'govuk-accordion__show-all'
17
- this.sectionButton = 'govuk-accordion__section-button'
18
- this.headingText = 'govuk-accordion__section-heading-text'
19
-
20
- // Translated component content and language attribute pulled from data attributes
13
+ this.sectionExpandedClass = 'govuk-accordion__section--expanded'
14
+ this.sectionInnerContentClass = 'govuk-accordion__section-content'
15
+
16
+ this.sectionHeader = '.govuk-accordion__section-header'
17
+ this.showAllControls = '.govuk-accordion__show-all'
18
+ this.sectionButton = '.govuk-accordion__section-button'
19
+ this.headingText = '.govuk-accordion__section-heading-text'
20
+
21
+ // language attribute pulled from data attributes
21
22
  this.$module.actions = {}
22
23
  this.$module.actions.locale = this.$module.getAttribute('data-locale')
23
- this.$module.actions.showText = this.$module.getAttribute('data-show-text')
24
- this.$module.actions.hideText = this.$module.getAttribute('data-hide-text')
25
- this.$module.actions.showAllText = this.$module.getAttribute('data-show-all-text')
26
- this.$module.actions.hideAllText = this.$module.getAttribute('data-hide-all-text')
27
- this.$module.actions.thisSectionVisuallyHidden = this.$module.getAttribute('data-this-section-visually-hidden')
28
24
  }
29
25
 
30
26
  GemAccordion.prototype.init = function () {
31
27
  // Indicate that JavaScript has worked
32
- this.$module.classList.add('gem-c-accordion--active')
33
- this.$module.querySelector('.' + this.showAllControls).classList.add('gem-c-accordion__show-all')
28
+ this.$module.querySelector(this.showAllControls).classList.add('gem-c-accordion__show-all')
34
29
 
35
30
  // Feature flag for anchor tag navigation used on manuals
36
31
  if (this.$module.getAttribute('data-anchor-navigation') === 'true') {
@@ -50,7 +45,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
50
45
  var showAllAttributes = this.$module.getAttribute('data-show-all-attributes')
51
46
  if (showAllAttributes) {
52
47
  try {
53
- var showAll = this.$module.querySelector('.' + this.showAllControls)
48
+ var showAll = this.$module.querySelector(this.showAllControls)
54
49
  var values = JSON.parse(showAllAttributes)
55
50
  var keys = Object.keys(values)
56
51
  for (var i = 0; i < keys.length; i++) {
@@ -74,7 +69,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
74
69
  // Add event listeners for links to open accordion sections when navigated to using said anchor links on the page
75
70
  // Adding an event listener to all anchor link a tags in an accordion is risky but we circumvent this risk partially by only being a layer of accordion behaviour instead of any sort of change to link behaviour
76
71
  GemAccordion.prototype.addEventListenersForAnchors = function () {
77
- var links = this.$module.querySelectorAll('.' + this.sectionInnerContent + ' a[href*="#"]')
72
+ var links = this.$module.querySelectorAll(this.sectionInnerContentClass + ' a[href*="#"]')
78
73
 
79
74
  nodeListForEach(links, function (link) {
80
75
  if (link.pathname === window.location.pathname) {
@@ -87,7 +82,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
87
82
  GemAccordion.prototype.openForAnchor = function (hash) {
88
83
  var target = document.getElementById(hash)
89
84
  var $section = this.getContainingSection(target)
90
- var $header = $section.querySelector('.' + this.sectionHeaderClass)
85
+ var $header = $section.querySelector(this.sectionHeader)
91
86
  var $expanded = this.getContainingSection($section)
92
87
  var $parent = $header.parentElement
93
88
 
@@ -95,7 +90,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
95
90
  // Should the target anchor link be within the same page, open section - navigate normally
96
91
  // Should the target anchor link be within a different, closed section, open this section
97
92
  // Should the target anchor link be within a different page and different, closed section open this section
98
- if ($expanded && (!$parent.classList.contains(this.sectionClassExpanded))) {
93
+ if ($expanded && (!$parent.classList.contains(this.sectionExpandedClass))) {
99
94
  $header.click()
100
95
  }
101
96
  }
@@ -119,11 +114,21 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
119
114
 
120
115
  // To track the Accordion's "Show all sections" / "Hide all sections" button click events and pass them to the GA event tracking
121
116
  GemAccordion.prototype.addAccordionOpenAllTracking = function () {
122
- this.$module.querySelector('.' + this.showAllControls).addEventListener('click', function (event) {
117
+ this.$module.querySelector(this.showAllControls).addEventListener('click', function (event) {
123
118
  var expanded = event.target.getAttribute('aria-expanded') === 'true'
124
119
  var label = expanded ? 'Show all sections' : 'Hide all sections'
125
120
  var action = expanded ? 'accordionOpened' : 'accordionClosed'
126
121
  var options = { transport: 'beacon', label: label }
122
+
123
+ var extraOptions = event.target && event.target.getAttribute('data-track-options')
124
+
125
+ // this uses the same logic as track-click.js handleClick
126
+ // means we can add a custom dimensions on click
127
+ if (extraOptions) {
128
+ extraOptions = JSON.parse(extraOptions)
129
+ for (var k in extraOptions) options[k] = extraOptions[k]
130
+ }
131
+
127
132
  if (window.GOVUK.analytics && window.GOVUK.analytics.trackEvent) {
128
133
  window.GOVUK.analytics.trackEvent('pageElementInteraction', action, options)
129
134
  }
@@ -131,7 +136,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
131
136
  }
132
137
 
133
138
  GemAccordion.prototype.addEventListenerSections = function () {
134
- var sections = this.$module.querySelectorAll('.' + this.sectionButton)
139
+ var sections = this.$module.querySelectorAll(this.sectionButton)
135
140
  nodeListForEach(sections, function (section) {
136
141
  section.addEventListener('click', this.addAccordionSectionTracking.bind(this, section))
137
142
  }.bind(this))
@@ -140,7 +145,7 @@ window.GOVUK.Modules.GovukAccordion = window.GOVUKFrontend.Accordion;
140
145
  // If the Accordion's sections are opened on click, then pass them to the GA event tracking
141
146
  GemAccordion.prototype.addAccordionSectionTracking = function (section) {
142
147
  var expanded = section.getAttribute('aria-expanded') === 'false'
143
- var label = section.querySelector('.' + this.headingText).textContent
148
+ var label = section.querySelector(this.headingText).textContent
144
149
  var action = expanded ? 'accordionOpened' : 'accordionClosed'
145
150
  var options = { transport: 'beacon', label: label }
146
151
 
@@ -0,0 +1,52 @@
1
+ window.GOVUK = window.GOVUK || {}
2
+ window.GOVUK.Modules = window.GOVUK.Modules || {};
3
+
4
+ (function (Modules) {
5
+ function Table ($module) {
6
+ this.$module = $module
7
+ this.searchInput = $module.querySelector('input[name="filter"]')
8
+ this.tableRows = $module.querySelectorAll('.js-govuk-table__row')
9
+ this.filter = $module.querySelector('.js-gem-c-table__filter')
10
+ this.filterCount = this.filter.querySelector('.js-filter-count')
11
+ this.message = $module.querySelector('.js-gem-c-table__message')
12
+ this.hiddenClass = 'govuk-!-display-none'
13
+ this.filterCountText = this.filterCount.getAttribute('data-count-text')
14
+ this.tableRowsContent = []
15
+
16
+ for (var i = 0; i < this.tableRows.length; i++) {
17
+ this.tableRowsContent.push(this.tableRows[i].textContent.toUpperCase())
18
+ }
19
+ }
20
+
21
+ Table.prototype.init = function () {
22
+ this.$module.updateRows = this.updateRows.bind(this)
23
+ this.filter.classList.remove(this.hiddenClass)
24
+ this.searchInput.addEventListener('input', this.$module.updateRows)
25
+ }
26
+
27
+ // Reads value of input and filters content
28
+ Table.prototype.updateRows = function () {
29
+ var value = this.searchInput.value
30
+ var hiddenRows = 0
31
+ var length = this.tableRows.length
32
+
33
+ for (var i = 0; i < length; i++) {
34
+ if (this.tableRowsContent[i].includes(value.toUpperCase())) {
35
+ this.tableRows[i].classList.remove(this.hiddenClass)
36
+ } else {
37
+ this.tableRows[i].classList.add(this.hiddenClass)
38
+ hiddenRows++
39
+ }
40
+ }
41
+
42
+ this.filterCount.textContent = (length - hiddenRows) + ' ' + this.filterCountText
43
+
44
+ if (length === hiddenRows) {
45
+ this.message.classList.remove(this.hiddenClass)
46
+ } else {
47
+ this.message.classList.add(this.hiddenClass)
48
+ }
49
+ }
50
+
51
+ Modules.Table = Table
52
+ })(window.GOVUK.Modules)
@@ -92,6 +92,13 @@
92
92
  }
93
93
  }
94
94
 
95
+ .gem-c-action-link--white-arrow {
96
+ &:before {
97
+ background-image: image-url("govuk_publishing_components/action-link-arrow--white.png");
98
+ background-image: image-url("govuk_publishing_components/action-link-arrow--white.svg"), linear-gradient(transparent, transparent);
99
+ }
100
+ }
101
+
95
102
  .gem-c-action-link--blue-arrow {
96
103
  &:before {
97
104
  width: 36px;
@@ -1,92 +1 @@
1
- .gem-c-pagination {
2
- display: block;
3
- margin: govuk-spacing(8) 0;
4
- }
5
-
6
- .gem-c-pagination__list {
7
- margin: 0;
8
- padding: 0;
9
- }
10
-
11
- .gem-c-pagination__item {
12
- @include govuk-font($size: 19);
13
- list-style: none;
14
-
15
- &:first-child {
16
- margin-bottom: govuk-spacing(4);
17
- }
18
- }
19
-
20
- .gem-c-pagination__link {
21
- display: block;
22
- text-decoration: none;
23
- padding-bottom: govuk-spacing(4);
24
-
25
- &:hover,
26
- &:active,
27
- &:visited {
28
- color: $govuk-link-colour;
29
- }
30
-
31
- &:hover,
32
- &:active {
33
- background-color: govuk-colour("light-grey", $legacy: "grey-4");
34
-
35
- // Add govuk-link hover decoration to title if no label present
36
- .gem-c-pagination__link-text--decorated {
37
- @include govuk-link-decoration;
38
- }
39
-
40
- .gem-c-pagination__link-label,
41
- .gem-c-pagination__link-text--decorated {
42
- @include govuk-link-hover-decoration;
43
- }
44
- }
45
-
46
- &:focus {
47
- @include govuk-focused-text;
48
-
49
- .gem-c-pagination__link-title {
50
- border-top-color: transparent;
51
- }
52
-
53
- .gem-c-pagination__link-icon {
54
- fill: $govuk-text-colour;
55
- }
56
- }
57
- }
58
-
59
- .gem-c-pagination__link-title {
60
- display: block;
61
- border-top: 1px solid $govuk-border-colour;
62
- padding-top: govuk-spacing(3);
63
- }
64
-
65
- .gem-c-pagination__link-divider {
66
- @include govuk-visually-hidden;
67
- }
68
-
69
- .gem-c-pagination__link-text {
70
- @include govuk-font(19, $weight: bold);
71
- margin-left: govuk-spacing(2);
72
- }
73
-
74
- .gem-c-pagination__link-icon {
75
- @include govuk-font($size: 24, $line-height: (33.75 / 27));
76
- display: inline-block;
77
- margin-bottom: 1px;
78
- height: .482em;
79
- width: .63em;
80
- fill: govuk-colour("dark-grey", $legacy: "grey-1");
81
- }
82
-
83
- .gem-c-pagination__link-label {
84
- display: inline-block;
85
- margin-top: .1em;
86
- margin-left: govuk-spacing(5);
87
- @include govuk-link-decoration;
88
-
89
- @include govuk-media-query($from: tablet) {
90
- margin-left: govuk-spacing(6);
91
- }
92
- }
1
+ @import "govuk/components/pagination/pagination";
@@ -6,6 +6,7 @@ module GovukPublishingComponents
6
6
  @path = path
7
7
  application_found = application_exists(path)
8
8
  components_found = []
9
+ @component_locations = {}
9
10
  @gem_style_references = []
10
11
  @jquery_references = []
11
12
 
@@ -25,15 +26,15 @@ module GovukPublishingComponents
25
26
  @find_all_javascripts = /\/\/ *= require govuk_publishing_components\/all_components/
26
27
  find_javascripts = /(?<=require govuk_publishing_components\/components\/)[a-zA-Z_-]+/
27
28
 
28
- components_in_templates = find_components(templates, find_components, "templates") || []
29
- components_in_stylesheets = find_components(stylesheets, find_stylesheets, "stylesheets") || []
30
- components_in_print_stylesheets = find_components(stylesheets, find_print_stylesheets, "print_stylesheets") || []
31
- components_in_javascripts = find_components(javascripts, find_javascripts, "javascripts") || []
29
+ components_in_templates = find_components(templates, find_components, "templates", true) || []
30
+ components_in_stylesheets = find_components(stylesheets, find_stylesheets, "stylesheets", false) || []
31
+ components_in_print_stylesheets = find_components(stylesheets, find_print_stylesheets, "print_stylesheets", false) || []
32
+ components_in_javascripts = find_components(javascripts, find_javascripts, "javascripts", false) || []
32
33
 
33
34
  ruby_paths = %w[/app/helpers/ /app/presenters/ /lib/]
34
35
  components_in_ruby = []
35
36
  ruby_paths.each do |ruby_path|
36
- components_in_ruby << find_components(Dir["#{path}#{ruby_path}**/*.{rb,erb}"], find_components, "ruby") || []
37
+ components_in_ruby << find_components(Dir["#{path}#{ruby_path}**/*.{rb,erb}"], find_components, "ruby", true) || []
37
38
  end
38
39
  components_in_ruby = components_in_ruby.flatten.uniq
39
40
 
@@ -67,17 +68,32 @@ module GovukPublishingComponents
67
68
  components_found: components_found,
68
69
  gem_style_references: @gem_style_references.flatten.uniq.sort,
69
70
  jquery_references: @jquery_references.flatten.uniq.sort,
71
+ component_locations: @component_locations,
70
72
  }
71
73
  end
72
74
 
73
75
  private
74
76
 
75
- def find_components(files, find, type)
77
+ def find_components(files, find, type, keep_locations)
76
78
  components_found = []
77
79
 
78
80
  files.each do |file|
79
81
  src = File.read(file)
80
- components_found << find_match(find, src, type)
82
+
83
+ if keep_locations
84
+ components = find_match(find, src, type)
85
+ if components.any?
86
+ components_found << components
87
+ components.each do |component|
88
+ component_sym = component.to_sym
89
+ @component_locations[component_sym] = [] unless @component_locations[component_sym]
90
+ @component_locations[component_sym] << clean_file_path(file)
91
+ @component_locations[component_sym].sort!
92
+ end
93
+ end
94
+ else
95
+ components_found << find_match(find, src, type)
96
+ end
81
97
 
82
98
  if type == "javascripts"
83
99
  jquery_references = find_code_references(file, src, /\$\(/)
@@ -93,12 +109,16 @@ module GovukPublishingComponents
93
109
  components_found.flatten.uniq.sort
94
110
  end
95
111
 
112
+ # looks for components in the given src of a file
113
+ # returns an array of component names or an empty array
96
114
  def find_match(find, src, type)
97
115
  return %w[all] if src.match(@find_all_stylesheets) && type == "stylesheets"
98
116
  return %w[all] if src.match(@find_all_print_stylesheets) && type == "print_stylesheets"
99
117
  return %w[all] if src.match(@find_all_javascripts) && type == "javascripts"
100
118
 
101
119
  matches = src.scan(find)
120
+ return [] unless matches.any?
121
+
102
122
  all_matches = []
103
123
  matches.each do |match|
104
124
  all_matches << clean_file_name(match.tr('[])\'"', ""))
@@ -108,9 +128,11 @@ module GovukPublishingComponents
108
128
  end
109
129
 
110
130
  def find_code_references(file, src, regex)
111
- clean_file_path = /(?<=#{Regexp.escape(@path.to_s)}\/)[\/a-zA-Z_-]+.[a-zA-Z.]+/
131
+ return clean_file_path(file) if regex.match?(src)
132
+ end
112
133
 
113
- return file[clean_file_path] if regex.match?(src)
134
+ def clean_file_path(file)
135
+ file[/(?<=#{Regexp.escape(@path.to_s)}\/)[\/a-zA-Z_-]+.[a-zA-Z.]+/]
114
136
  end
115
137
 
116
138
  def clean_file_name(name)
@@ -106,6 +106,7 @@ module GovukPublishingComponents
106
106
  warning_count: warnings.length,
107
107
  gem_style_references: result[:gem_style_references],
108
108
  jquery_references: result[:jquery_references],
109
+ component_locations: result[:component_locations],
109
110
  }
110
111
  else
111
112
  data << {
@@ -244,28 +245,33 @@ module GovukPublishingComponents
244
245
  (haystack - needle).flatten.sort
245
246
  end
246
247
 
248
+ # returns details of component inclusion by applications
247
249
  def get_components_by_application
248
250
  results = []
249
251
  found_something = false
250
252
 
251
253
  @gem_data[:component_listing].each do |component|
252
- found_in_applications = []
254
+ component_name = component[:name]
255
+ locations = []
253
256
 
254
257
  @applications_data.each do |application|
255
- next unless application[:application_found]
258
+ next unless application[:application_found] && application[:component_locations][component_name.to_sym]
256
259
 
257
- name = application[:name]
260
+ application_name = application[:name]
258
261
  found_something = true
259
262
 
260
- application[:summary].each do |item|
261
- found_in_applications << name if item[:value].include?(component[:name])
262
- end
263
+ locations << {
264
+ name: application_name,
265
+ locations: application[:component_locations][component_name.to_sym],
266
+ }
263
267
  end
264
268
 
269
+ locations = locations.flatten
270
+
265
271
  results << {
266
- component: component[:name],
267
- count: found_in_applications.uniq.length,
268
- list: found_in_applications.uniq.join(", "),
272
+ component: component_name,
273
+ count: locations.length,
274
+ locations: locations,
269
275
  }
270
276
  end
271
277
 
@@ -63,10 +63,28 @@
63
63
  <% @components[:components_by_application].each do |component| %>
64
64
  <div class="govuk-summary-list__row">
65
65
  <dt class="govuk-summary-list__key">
66
- <%= component[:component] %> (<%= component[:count] %>)
66
+ <%= component[:component] %> (<%= pluralize(component[:count], 'use') %>)
67
67
  </dt>
68
68
  <dd class="govuk-summary-list__value">
69
- <%= component[:list] %>
69
+ <% component[:locations].each do |application| %>
70
+ <% github_link = 'https://github.com/alphagov/' + application[:name] + '/blob/main/' %>
71
+ <details class="govuk-details govuk-!-margin-bottom-2" data-module="govuk-details">
72
+ <summary class="govuk-details__summary">
73
+ <span class="govuk-details__summary-text">
74
+ <%= application[:name] %> (<%= application[:locations].length %>)
75
+ </span>
76
+ </summary>
77
+ <div class="govuk-details__text">
78
+ <ul class="govuk-list govuk-list--bullet">
79
+ <% application[:locations].each do |location| %>
80
+ <li>
81
+ <a href="<%= github_link %><%= location %>" class="govuk-link"><%= location %></a>
82
+ </li>
83
+ <% end %>
84
+ </ul>
85
+ </div>
86
+ </details>
87
+ <% end %>
70
88
  </dd>
71
89
  </div>
72
90
  <% end %>
@@ -10,6 +10,7 @@
10
10
  mobile_subtext ||= false
11
11
  light_text ||= false
12
12
  blue_arrow ||= false
13
+ white_arrow ||= false
13
14
  simple ||= false
14
15
  simple_light ||= false
15
16
  dark_icon ||= false
@@ -29,6 +30,7 @@
29
30
  css_classes << "gem-c-action-link--nhs" if nhs_icon
30
31
  css_classes << "gem-c-action-link--brexit" if brexit_icon
31
32
  css_classes << "gem-c-action-link--blue-arrow" if blue_arrow
33
+ css_classes << "gem-c-action-link--white-arrow" if white_arrow
32
34
  css_classes << "gem-c-action-link--simple" if simple
33
35
  css_classes << "gem-c-action-link--simple-light" if simple_light
34
36
  css_classes << "gem-c-action-link--with-subtext" if subtext