govspeak 6.5.0 → 6.5.5

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 (38) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +24 -2
  3. data/README.md +6 -5
  4. data/Rakefile +7 -4
  5. data/lib/govspeak.rb +116 -116
  6. data/lib/govspeak/header_extractor.rb +1 -1
  7. data/lib/govspeak/html_sanitizer.rb +12 -9
  8. data/lib/govspeak/kramdown_overrides.rb +2 -2
  9. data/lib/govspeak/link_extractor.rb +6 -6
  10. data/lib/govspeak/post_processor.rb +34 -14
  11. data/lib/govspeak/presenters/attachment_presenter.rb +39 -39
  12. data/lib/govspeak/presenters/contact_presenter.rb +2 -2
  13. data/lib/govspeak/presenters/h_card_presenter.rb +3 -3
  14. data/lib/govspeak/presenters/image_presenter.rb +4 -4
  15. data/lib/govspeak/structured_header_extractor.rb +2 -2
  16. data/lib/govspeak/version.rb +1 -1
  17. data/lib/kramdown/parser/govuk.rb +6 -7
  18. data/test/blockquote_extra_quote_remover_test.rb +24 -26
  19. data/test/govspeak_attachment_link_test.rb +0 -2
  20. data/test/govspeak_attachment_test.rb +0 -2
  21. data/test/govspeak_attachments_image_test.rb +12 -14
  22. data/test/govspeak_attachments_inline_test.rb +22 -24
  23. data/test/govspeak_button_test.rb +29 -31
  24. data/test/govspeak_contacts_test.rb +29 -31
  25. data/test/govspeak_extract_contact_content_ids_test.rb +1 -3
  26. data/test/govspeak_images_bang_test.rb +37 -39
  27. data/test/govspeak_images_test.rb +43 -45
  28. data/test/govspeak_link_extractor_test.rb +1 -1
  29. data/test/govspeak_link_test.rb +1 -3
  30. data/test/govspeak_structured_headers_test.rb +7 -6
  31. data/test/govspeak_table_with_headers_test.rb +68 -21
  32. data/test/govspeak_test.rb +98 -101
  33. data/test/govspeak_test_helper.rb +1 -1
  34. data/test/html_sanitizer_test.rb +17 -9
  35. data/test/html_validator_test.rb +2 -2
  36. data/test/presenters/h_card_presenter_test.rb +39 -41
  37. data/test/test_helper.rb +12 -8
  38. metadata +52 -40
@@ -49,7 +49,7 @@ module GovspeakTestHelper
49
49
  lines = text.split "\n"
50
50
  digits = Math.log10(lines.size + 2).ceil
51
51
  lines.map
52
- .with_index { |line, i| "%<number>#{digits}d: %<line>s" % { number: i + 1, line: line } }
52
+ .with_index { |line, i| sprintf("%<number>#{digits}d: %<line>s", number: i + 1, line: line) }
53
53
  .join("\n")
54
54
  end
55
55
  end
@@ -31,7 +31,7 @@ class HtmlSanitizerTest < Minitest::Test
31
31
  html = "<a href='#' data-module='cross-domain-tracking' data-tracking-code='UA-XXXXXX-Y' data-tracking-name='govspeakButtonTracker'></a>"
32
32
  assert_equal(
33
33
  "<a href=\"#\" data-module=\"cross-domain-tracking\" data-tracking-code=\"UA-XXXXXX-Y\" data-tracking-name=\"govspeakButtonTracker\"></a>",
34
- Govspeak::HtmlSanitizer.new(html).sanitize
34
+ Govspeak::HtmlSanitizer.new(html).sanitize,
35
35
  )
36
36
  end
37
37
 
@@ -40,19 +40,28 @@ class HtmlSanitizerTest < Minitest::Test
40
40
 
41
41
  assert_equal(
42
42
  "<a href=\"/\" data-module=\"track-click\" data-ecommerce-path=\"/\" data-track-category=\"linkClicked\">Test Link</a>",
43
- Govspeak::HtmlSanitizer.new(html).sanitize
43
+ Govspeak::HtmlSanitizer.new(html).sanitize,
44
+ )
45
+ end
46
+
47
+ test "allow data attributes on divs" do
48
+ html = "<div data-module='toggle' data-ecommerce-path='/' data-track-category='someDiv'>Test Div</div>"
49
+
50
+ assert_equal(
51
+ "<div data-module=\"toggle\" data-ecommerce-path=\"/\" data-track-category=\"someDiv\">Test Div</div>",
52
+ Govspeak::HtmlSanitizer.new(html).sanitize,
44
53
  )
45
54
  end
46
55
 
47
56
  test "allows images on whitelisted domains" do
48
57
  html = "<img src='http://allowed.com/image.jgp'>"
49
- sanitized_html = Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ['allowed.com']).sanitize
58
+ sanitized_html = Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ["allowed.com"]).sanitize
50
59
  assert_equal "<img src=\"http://allowed.com/image.jgp\">", sanitized_html
51
60
  end
52
61
 
53
62
  test "removes images not on whitelisted domains" do
54
63
  html = "<img src='http://evil.com/image.jgp'>"
55
- assert_equal "", Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ['allowed.com']).sanitize
64
+ assert_equal "", Govspeak::HtmlSanitizer.new(html, allowed_image_hosts: ["allowed.com"]).sanitize
56
65
  end
57
66
 
58
67
  test "allows table cells and table headings without a style attribute" do
@@ -62,15 +71,14 @@ class HtmlSanitizerTest < Minitest::Test
62
71
 
63
72
  test "strips table cells and headings that appear outside a table" do
64
73
  html = "<th>thing</th></tr><tr><td>thing</td>"
65
- assert_equal 'thingthing', Govspeak::HtmlSanitizer.new(html).sanitize
74
+ assert_equal "thingthing", Govspeak::HtmlSanitizer.new(html).sanitize
66
75
  end
67
76
 
68
77
  test "normalizes table tags to inject missing rows and bodies like a browser does" do
69
78
  html = "<table><th>thing</th><td>thing</td></table>"
70
- assert_equal '<table><tbody><tr><th>thing</th><td>thing</td></tr></tbody></table>', Govspeak::HtmlSanitizer.new(html).sanitize
79
+ assert_equal "<table><tbody><tr><th>thing</th><td>thing</td></tr></tbody></table>", Govspeak::HtmlSanitizer.new(html).sanitize
71
80
  end
72
81
 
73
-
74
82
  test "allows valid text-align properties on the style attribute for table cells and table headings" do
75
83
  %w[left right center].each do |alignment|
76
84
  html = "<table><thead><tr><th style=\"text-align: #{alignment}\">thing</th></tr></thead><tbody><tr><td style=\"text-align: #{alignment}\">thing</td></tr></tbody></table>"
@@ -82,10 +90,10 @@ class HtmlSanitizerTest < Minitest::Test
82
90
  "text-align: middle",
83
91
  "text-align: left; width: 10px",
84
92
  "background-image: url(javascript:alert('XSS'))",
85
- "expression(alert('XSS'));"
93
+ "expression(alert('XSS'));",
86
94
  ].each do |style|
87
95
  html = "<table><thead><tr><th style=\"#{style}\">thing</th></tr></thead><tbody><tr><td style=\"#{style}\">thing</td></tr></tbody></table>"
88
- assert_equal '<table><thead><tr><th>thing</th></tr></thead><tbody><tr><td>thing</td></tr></tbody></table>', Govspeak::HtmlSanitizer.new(html).sanitize
96
+ assert_equal "<table><thead><tr><th>thing</th></tr></thead><tbody><tr><td>thing</td></tr></tbody></table>", Govspeak::HtmlSanitizer.new(html).sanitize
89
97
  end
90
98
  end
91
99
  end
@@ -51,7 +51,7 @@ class HtmlValidatorTest < Minitest::Test
51
51
  $P
52
52
  ",
53
53
  ":england:content goes here:england:",
54
- ":scotland:content goes here:scotland:"
54
+ ":scotland:content goes here:scotland:",
55
55
  ]
56
56
  values.each do |value|
57
57
  assert Govspeak::HtmlValidator.new(value).valid?
@@ -88,7 +88,7 @@ class HtmlValidatorTest < Minitest::Test
88
88
 
89
89
  test "optionally disallow images not on a whitelisted domain" do
90
90
  html = "<img src='http://evil.com/image.jgp'>"
91
- assert Govspeak::HtmlValidator.new(html, allowed_image_hosts: ['allowed.com']).invalid?
91
+ assert Govspeak::HtmlValidator.new(html, allowed_image_hosts: ["allowed.com"]).invalid?
92
92
  end
93
93
 
94
94
  test "allow <div> and <span> HTML elements" do
@@ -1,93 +1,91 @@
1
- # encoding: utf-8
2
-
3
- require 'test_helper'
4
- require 'ostruct'
1
+ require "test_helper"
2
+ require "ostruct"
5
3
 
6
4
  class HCardPresenterTest < Minitest::Test
7
5
  def unindent(html)
8
- html.gsub(/^\s+/, '')
6
+ html.gsub(/^\s+/, "")
9
7
  end
10
8
 
11
9
  test "renders address in UK format" do
12
- assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, 'GB').render
10
+ assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, "GB").render
13
11
  end
14
12
 
15
13
  test "renders address in Spanish format" do
16
- assert_equal unindent(es_addr), HCardPresenter.new(addr_fields, 'ES').render
14
+ assert_equal unindent(es_addr), HCardPresenter.new(addr_fields, "ES").render
17
15
  end
18
16
 
19
17
  test "renders address in Japanese format" do
20
- assert_equal unindent(jp_addr), HCardPresenter.new(addr_fields, 'JP').render
18
+ assert_equal unindent(jp_addr), HCardPresenter.new(addr_fields, "JP").render
21
19
  end
22
20
 
23
21
  test "doesn't clobber address formats" do
24
- gb_format_before = HCardPresenter.address_formats['gb'].dup
25
- HCardPresenter.new(addr_fields, 'GB').render
22
+ gb_format_before = HCardPresenter.address_formats["gb"].dup
23
+ HCardPresenter.new(addr_fields, "GB").render
26
24
 
27
- assert_equal unindent(gb_format_before), HCardPresenter.address_formats['gb']
25
+ assert_equal unindent(gb_format_before), HCardPresenter.address_formats["gb"]
28
26
  end
29
27
 
30
28
  test "blank properties do not render extra line breaks" do
31
29
  fields_without_region = addr_fields
32
- fields_without_region.delete('region')
30
+ fields_without_region.delete("region")
33
31
 
34
- assert_equal unindent(addr_without_region), HCardPresenter.new(fields_without_region, 'GB').render
32
+ assert_equal unindent(addr_without_region), HCardPresenter.new(fields_without_region, "GB").render
35
33
  end
36
34
 
37
35
  test "doesn't render a property when it's a blank string" do
38
36
  fields = addr_fields
39
37
 
40
- fields['region'] = ''
41
- assert_equal unindent(addr_without_region), HCardPresenter.new(fields, 'GB').render
38
+ fields["region"] = ""
39
+ assert_equal unindent(addr_without_region), HCardPresenter.new(fields, "GB").render
42
40
 
43
- fields['region'] = ' '
44
- assert_equal unindent(addr_without_region), HCardPresenter.new(fields, 'GB').render
41
+ fields["region"] = " "
42
+ assert_equal unindent(addr_without_region), HCardPresenter.new(fields, "GB").render
45
43
  end
46
44
 
47
- test 'uses html escaping on property values' do
45
+ test "uses html escaping on property values" do
48
46
  fields = addr_fields
49
47
 
50
- fields['region'] = 'UK & Channel Islands'
51
- assert_includes HCardPresenter.new(fields, 'GB').render, "UK &amp; Channel Islands"
48
+ fields["region"] = "UK & Channel Islands"
49
+ assert_includes HCardPresenter.new(fields, "GB").render, "UK &amp; Channel Islands"
52
50
  end
53
51
 
54
52
  test "it defaults to UK format" do
55
- assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, 'FUBAR').render
53
+ assert_equal unindent(gb_addr), HCardPresenter.new(addr_fields, "FUBAR").render
56
54
  end
57
55
 
58
56
  test "it builds from a Contact" do
59
- contact = OpenStruct.new(recipient: 'Recipient',
60
- street_address: 'Street',
61
- locality: 'Locality',
62
- region: 'Region',
63
- postal_code: 'Postcode',
64
- country_name: 'Country',
65
- country_code: 'ES')
57
+ contact = OpenStruct.new(recipient: "Recipient",
58
+ street_address: "Street",
59
+ locality: "Locality",
60
+ region: "Region",
61
+ postal_code: "Postcode",
62
+ country_name: "Country",
63
+ country_code: "ES")
66
64
  hcard = HCardPresenter.from_contact(contact)
67
65
 
68
66
  assert_equal unindent(es_addr), hcard.render
69
67
  end
70
68
 
71
69
  test "it leaves out the country name when building a GB contact" do
72
- contact = OpenStruct.new(recipient: 'Recipient',
73
- street_address: 'Street',
74
- locality: 'Locality',
75
- region: 'Region',
76
- postal_code: 'Postcode',
77
- country_name: 'Country',
78
- country_code: 'GB')
70
+ contact = OpenStruct.new(recipient: "Recipient",
71
+ street_address: "Street",
72
+ locality: "Locality",
73
+ region: "Region",
74
+ postal_code: "Postcode",
75
+ country_name: "Country",
76
+ country_code: "GB")
79
77
  hcard = HCardPresenter.from_contact(contact)
80
78
 
81
79
  assert_equal unindent(addr_without_country), hcard.render
82
80
  end
83
81
 
84
82
  def addr_fields
85
- { 'fn' => 'Recipient',
86
- 'street-address' => 'Street',
87
- 'postal-code' => 'Postcode',
88
- 'locality' => 'Locality',
89
- 'region' => 'Region',
90
- 'country-name' => 'Country' }
83
+ { "fn" => "Recipient",
84
+ "street-address" => "Street",
85
+ "postal-code" => "Postcode",
86
+ "locality" => "Locality",
87
+ "region" => "Region",
88
+ "country-name" => "Country" }
91
89
  end
92
90
 
93
91
  def gb_addr
@@ -1,22 +1,26 @@
1
- require 'simplecov'
2
- require 'simplecov-rcov'
1
+ require "simplecov"
2
+ require "simplecov-rcov"
3
3
 
4
4
  SimpleCov.start
5
5
  SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
6
6
 
7
- $:.unshift(File.expand_path("../lib")) unless $:.include?(File.expand_path("../lib"))
7
+ $LOAD_PATH.unshift(File.expand_path("../lib")) unless $LOAD_PATH.include?(File.expand_path("../lib"))
8
8
 
9
- require 'bundler'
9
+ require "bundler"
10
10
  Bundler.setup :default, :development, :test
11
11
 
12
- require 'minitest/autorun'
12
+ require "minitest/autorun"
13
13
 
14
14
  class Minitest::Test
15
15
  class << self
16
16
  def test(name, &block)
17
- clean_name = name.gsub(/\s+/, '_')
17
+ clean_name = name.gsub(/\s+/, "_")
18
18
  method = "test_#{clean_name.gsub(/\s+/, '_')}".to_sym
19
- already_defined = instance_method(method) rescue false
19
+ already_defined = begin
20
+ instance_method(method)
21
+ rescue StandardError
22
+ false
23
+ end
20
24
  raise "#{method} exists" if already_defined
21
25
 
22
26
  define_method(method, &block)
@@ -24,4 +28,4 @@ class Minitest::Test
24
28
  end
25
29
  end
26
30
 
27
- require 'govspeak'
31
+ require "govspeak"
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: govspeak
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.5.0
4
+ version: 6.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - GOV.UK Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-23 00:00:00.000000000 Z
11
+ date: 2020-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: actionview
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '5.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '5.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: addressable
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -48,16 +54,16 @@ dependencies:
48
54
  name: govuk_publishing_components
49
55
  requirement: !ruby/object:Gem::Requirement
50
56
  requirements:
51
- - - ">="
57
+ - - "~>"
52
58
  - !ruby/object:Gem::Version
53
- version: '16.16'
59
+ version: '21.4'
54
60
  type: :runtime
55
61
  prerelease: false
56
62
  version_requirements: !ruby/object:Gem::Requirement
57
63
  requirements:
58
- - - ">="
64
+ - - "~>"
59
65
  - !ruby/object:Gem::Version
60
- version: '16.16'
66
+ version: '21.4'
61
67
  - !ruby/object:Gem::Dependency
62
68
  name: htmlentities
63
69
  requirement: !ruby/object:Gem::Requirement
@@ -146,44 +152,36 @@ dependencies:
146
152
  name: sanitize
147
153
  requirement: !ruby/object:Gem::Requirement
148
154
  requirements:
149
- - - "~>"
155
+ - - ">="
156
+ - !ruby/object:Gem::Version
157
+ version: 5.2.1
158
+ - - "<"
150
159
  - !ruby/object:Gem::Version
151
- version: '5'
160
+ version: '6'
152
161
  type: :runtime
153
162
  prerelease: false
154
163
  version_requirements: !ruby/object:Gem::Requirement
155
164
  requirements:
156
- - - "~>"
157
- - !ruby/object:Gem::Version
158
- version: '5'
159
- - !ruby/object:Gem::Dependency
160
- name: govuk-lint
161
- requirement: !ruby/object:Gem::Requirement
162
- requirements:
163
- - - "~>"
165
+ - - ">="
164
166
  - !ruby/object:Gem::Version
165
- version: 3.11.5
166
- type: :development
167
- prerelease: false
168
- version_requirements: !ruby/object:Gem::Requirement
169
- requirements:
170
- - - "~>"
167
+ version: 5.2.1
168
+ - - "<"
171
169
  - !ruby/object:Gem::Version
172
- version: 3.11.5
170
+ version: '6'
173
171
  - !ruby/object:Gem::Dependency
174
172
  name: minitest
175
173
  requirement: !ruby/object:Gem::Requirement
176
174
  requirements:
177
175
  - - "~>"
178
176
  - !ruby/object:Gem::Version
179
- version: 5.8.3
177
+ version: 5.14.1
180
178
  type: :development
181
179
  prerelease: false
182
180
  version_requirements: !ruby/object:Gem::Requirement
183
181
  requirements:
184
182
  - - "~>"
185
183
  - !ruby/object:Gem::Version
186
- version: 5.8.3
184
+ version: 5.14.1
187
185
  - !ruby/object:Gem::Dependency
188
186
  name: pry-byebug
189
187
  requirement: !ruby/object:Gem::Requirement
@@ -212,6 +210,20 @@ dependencies:
212
210
  - - "~>"
213
211
  - !ruby/object:Gem::Version
214
212
  version: 0.9.0
213
+ - !ruby/object:Gem::Dependency
214
+ name: rubocop-govuk
215
+ requirement: !ruby/object:Gem::Requirement
216
+ requirements:
217
+ - - "~>"
218
+ - !ruby/object:Gem::Version
219
+ version: 3.3.2
220
+ type: :development
221
+ prerelease: false
222
+ version_requirements: !ruby/object:Gem::Requirement
223
+ requirements:
224
+ - - "~>"
225
+ - !ruby/object:Gem::Version
226
+ version: 3.3.2
215
227
  - !ruby/object:Gem::Dependency
216
228
  name: simplecov
217
229
  requirement: !ruby/object:Gem::Requirement
@@ -359,23 +371,23 @@ signing_key:
359
371
  specification_version: 4
360
372
  summary: Markup language for single domain
361
373
  test_files:
374
+ - test/blockquote_extra_quote_remover_test.rb
375
+ - test/govspeak_test_helper.rb
376
+ - test/govspeak_structured_headers_test.rb
362
377
  - test/govspeak_attachment_link_test.rb
378
+ - test/govspeak_attachments_image_test.rb
363
379
  - test/test_helper.rb
380
+ - test/govspeak_attachments_inline_test.rb
381
+ - test/html_sanitizer_test.rb
364
382
  - test/govspeak_button_test.rb
365
- - test/govspeak_test.rb
383
+ - test/govspeak_images_bang_test.rb
384
+ - test/govspeak_images_test.rb
366
385
  - test/html_validator_test.rb
367
386
  - test/govspeak_attachment_test.rb
368
- - test/govspeak_contacts_test.rb
369
- - test/govspeak_test_helper.rb
370
- - test/blockquote_extra_quote_remover_test.rb
371
- - test/govspeak_table_with_headers_test.rb
372
- - test/govspeak_attachments_image_test.rb
373
- - test/html_sanitizer_test.rb
374
- - test/govspeak_link_test.rb
375
387
  - test/govspeak_extract_contact_content_ids_test.rb
376
- - test/govspeak_structured_headers_test.rb
377
- - test/govspeak_images_test.rb
378
- - test/presenters/h_card_presenter_test.rb
379
- - test/govspeak_images_bang_test.rb
388
+ - test/govspeak_test.rb
380
389
  - test/govspeak_link_extractor_test.rb
381
- - test/govspeak_attachments_inline_test.rb
390
+ - test/govspeak_link_test.rb
391
+ - test/govspeak_contacts_test.rb
392
+ - test/presenters/h_card_presenter_test.rb
393
+ - test/govspeak_table_with_headers_test.rb